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