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_WMTS = 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_WMTS.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        if (scaleList == null) {
066            return getMaxZoomLvl();
067        }
068        Scale snap = scaleList.getSnapScale(Main.map.mapView.getScale(), false);
069        return Math.max(
070                getMinZoomLvl(),
071                Math.min(
072                        snap != null ? snap.getIndex() : getMaxZoomLvl(),
073                        getMaxZoomLvl()
074                        )
075                );
076    }
077
078    @Override
079    protected int getMinZoomLvl() {
080        return 0;
081    }
082
083    @Override
084    public boolean isProjectionSupported(Projection proj) {
085        Set<String> supportedProjections = tileSource.getSupportedProjections();
086        return supportedProjections.contains(proj.toCode());
087    }
088
089    @Override
090    public String nameSupportedProjections() {
091        StringBuilder ret = new StringBuilder();
092        for (String e: tileSource.getSupportedProjections()) {
093            ret.append(e).append(", ");
094        }
095        return ret.length() > 2 ? ret.substring(0, ret.length()-2) : ret.toString();
096    }
097
098    @Override
099    public void projectionChanged(Projection oldValue, Projection newValue) {
100        super.projectionChanged(oldValue, newValue);
101        tileSource.initProjection(newValue);
102    }
103
104    @Override
105    protected Class<? extends TileLoader> getTileLoaderClass() {
106        return WMSCachedTileLoader.class;
107    }
108
109    @Override
110    protected String getCacheName() {
111        return CACHE_REGION_NAME;
112    }
113
114    /**
115     * @return cache region for WMTS layer
116     */
117    public static CacheAccess<String, BufferedImageCacheEntry> getCache() {
118        return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME);
119    }
120
121    @Override
122    public ScaleList getNativeScales() {
123        return tileSource.getNativeScales();
124    }
125}