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