001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer;
003
004import java.io.IOException;
005import java.util.Set;
006
007import org.apache.commons.jcs.access.CacheAccess;
008import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
009import org.openstreetmap.josm.Main;
010import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
011import org.openstreetmap.josm.data.imagery.ImageryInfo;
012import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
013import org.openstreetmap.josm.data.imagery.WMSCachedTileLoader;
014import org.openstreetmap.josm.data.imagery.WMTSTileSource;
015import org.openstreetmap.josm.data.projection.Projection;
016import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings;
017
018/**
019 * WMTS layer based on AbstractTileSourceLayer. Overrides few methods to align WMTS to Tile based computations
020 * but most magic is done within WMTSTileSource class.
021 *
022 * Full specification of the protocol available at:
023 * http://www.opengeospatial.org/standards/wmts
024 *
025 * @author Wiktor Niesiobędzki
026 *
027 */
028public class WMTSLayer extends AbstractCachedTileSourceLayer<WMTSTileSource> implements NativeScaleLayer {
029    private static final String PREFERENCE_PREFIX = "imagery.wmts";
030
031    /**
032     * Registers all setting properties
033     */
034    static {
035        new TileSourceDisplaySettings(PREFERENCE_PREFIX);
036    }
037
038    private static final String CACHE_REGION_NAME = "WMTS";
039
040    /**
041     * Creates WMTS layer from ImageryInfo
042     * @param info Imagery Info describing the layer
043     */
044    public WMTSLayer(ImageryInfo info) {
045        super(info);
046    }
047
048    @Override
049    protected TileSourceDisplaySettings createDisplaySettings() {
050        return new TileSourceDisplaySettings(PREFERENCE_PREFIX);
051    }
052
053    @Override
054    protected WMTSTileSource getTileSource() {
055        try {
056            if (info.getImageryType() == ImageryType.WMTS && info.getUrl() != null) {
057                WMTSTileSource.checkUrl(info.getUrl());
058                WMTSTileSource tileSource = new WMTSTileSource(info);
059                info.setAttribution(tileSource);
060                return tileSource;
061            }
062            return null;
063        } catch (IOException e) {
064            Main.warn(e);
065            throw new IllegalArgumentException(e);
066        }
067    }
068
069    @Override
070    protected int getBestZoom() {
071        if (!Main.isDisplayingMapView())
072            return 0;
073        ScaleList scaleList = getNativeScales();
074        if (scaleList == null) {
075            return getMaxZoomLvl();
076        }
077        Scale snap = scaleList.getSnapScale(Main.map.mapView.getScale(), false);
078        return Math.max(
079                getMinZoomLvl(),
080                Math.min(
081                        snap != null ? snap.getIndex() : getMaxZoomLvl(),
082                        getMaxZoomLvl()
083                        )
084                );
085    }
086
087    @Override
088    protected int getMinZoomLvl() {
089        return 0;
090    }
091
092    @Override
093    public boolean isProjectionSupported(Projection proj) {
094        Set<String> supportedProjections = tileSource.getSupportedProjections();
095        return supportedProjections.contains(proj.toCode());
096    }
097
098    @Override
099    public String nameSupportedProjections() {
100        StringBuilder ret = new StringBuilder();
101        for (String e: tileSource.getSupportedProjections()) {
102            ret.append(e).append(", ");
103        }
104        return ret.length() > 2 ? ret.substring(0, ret.length()-2) : ret.toString();
105    }
106
107    @Override
108    public void projectionChanged(Projection oldValue, Projection newValue) {
109        super.projectionChanged(oldValue, newValue);
110        tileSource.initProjection(newValue);
111    }
112
113    @Override
114    protected Class<? extends TileLoader> getTileLoaderClass() {
115        return WMSCachedTileLoader.class;
116    }
117
118    @Override
119    protected String getCacheName() {
120        return CACHE_REGION_NAME;
121    }
122
123    /**
124     * @return cache region for WMTS layer
125     */
126    public static CacheAccess<String, BufferedImageCacheEntry> getCache() {
127        return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME);
128    }
129
130    @Override
131    public ScaleList getNativeScales() {
132        return tileSource.getNativeScales();
133    }
134}