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.preferences.BooleanProperty;
016import org.openstreetmap.josm.data.projection.Projection;
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    /**
030     * default setting of autozoom per layer
031     */
032    public static final BooleanProperty PROP_DEFAULT_AUTOZOOM = new BooleanProperty("imagery.wmts.default_autozoom", true);
033    private static final String CACHE_REGION_NAME = "WMTS";
034
035    /**
036     * Creates WMTS layer from ImageryInfo
037     * @param info Imagery Info describing the layer
038     */
039    public WMTSLayer(ImageryInfo info) {
040        super(info);
041        autoZoom = PROP_DEFAULT_AUTOZOOM.get();
042    }
043
044    @Override
045    protected WMTSTileSource getTileSource(ImageryInfo info) {
046        try {
047            if (info.getImageryType() == ImageryType.WMTS && info.getUrl() != null) {
048                WMTSTileSource.checkUrl(info.getUrl());
049                WMTSTileSource tileSource = new WMTSTileSource(info);
050                info.setAttribution(tileSource);
051                return tileSource;
052            }
053            return null;
054        } catch (IOException e) {
055            Main.warn(e);
056            throw new IllegalArgumentException(e);
057        }
058    }
059
060    @Override
061    protected int getBestZoom() {
062        if (!Main.isDisplayingMapView())
063            return 0;
064        ScaleList scaleList = getNativeScales();
065        Scale snap = null;
066        if (scaleList == null) {
067            return getMaxZoomLvl();
068        }
069        snap = scaleList.getSnapScale(Main.map.mapView.getScale(), false);
070        return Math.max(
071                getMinZoomLvl(),
072                Math.min(
073                        snap != null ? snap.getIndex() : getMaxZoomLvl(),
074                        getMaxZoomLvl()
075                        )
076                );
077    }
078
079    @Override
080    protected int getMinZoomLvl() {
081        return 0;
082    }
083
084    @Override
085    public boolean isProjectionSupported(Projection proj) {
086        Set<String> supportedProjections = tileSource.getSupportedProjections();
087        return supportedProjections.contains(proj.toCode());
088    }
089
090    @Override
091    public String nameSupportedProjections() {
092        StringBuilder ret = new StringBuilder();
093        for (String e: tileSource.getSupportedProjections()) {
094            ret.append(e).append(", ");
095        }
096        return ret.length() > 2 ? ret.substring(0, ret.length()-2) : ret.toString();
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}