001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.remotecontrol.handler;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.util.Arrays;
007
008import org.openstreetmap.josm.Main;
009import org.openstreetmap.josm.data.imagery.ImageryInfo;
010import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
011import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
012import org.openstreetmap.josm.gui.layer.ImageryLayer;
013import org.openstreetmap.josm.gui.util.GuiHelper;
014import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
015import org.openstreetmap.josm.tools.Utils;
016
017/**
018 * Adds an imagery (WMS/TMS) layer. For instance, {@code /imagery?title=...&type=...&url=...}.
019 * @since 3715
020 */
021public class ImageryHandler extends RequestHandler.RawURLParseRequestHandler {
022
023    /**
024     * The remote control command name used to add an imagery layer.
025     */
026    public static final String command = "imagery";
027
028    @Override
029    public String getPermissionMessage() {
030        return tr("Remote Control has been asked to load an imagery layer from the following URL:")
031                + "<br>" + args.get("url");
032    }
033
034    @Override
035    public String[] getMandatoryParams() {
036        return new String[]{"url"};
037    }
038
039    @Override
040    public String[] getOptionalParams() {
041        return new String[] {"title", "type", "cookies", "min_zoom", "max_zoom"};
042    }
043
044    @Override
045    public PermissionPrefWithDefault getPermissionPref() {
046        return PermissionPrefWithDefault.LOAD_IMAGERY;
047    }
048
049    protected static ImageryInfo findBingEntry() {
050        for (ImageryInfo i : ImageryLayerInfo.instance.getDefaultLayers()) {
051            if (ImageryType.BING.equals(i.getImageryType())) {
052                return i;
053            }
054        }
055        return null;
056    }
057
058    protected ImageryInfo buildImageryInfo() {
059        String url = args.get("url");
060        String title = args.get("title");
061        String type = args.get("type");
062        final ImageryInfo bing = ImageryType.BING.getTypeString().equals(type) ? findBingEntry() : null;
063        if ((title == null || title.isEmpty()) && bing != null) {
064            title = bing.getName();
065        }
066        if (title == null || title.isEmpty()) {
067            title = tr("Remote imagery");
068        }
069        String cookies = args.get("cookies");
070        final ImageryInfo imgInfo = new ImageryInfo(title, url, type, null, cookies);
071        if (bing != null) {
072            imgInfo.setIcon(bing.getIcon());
073        }
074        String minZoom = args.get("min_zoom");
075        if (minZoom != null && !minZoom.isEmpty()) {
076            try {
077                imgInfo.setDefaultMinZoom(Integer.parseInt(minZoom));
078            } catch (NumberFormatException e) {
079                Main.error(e);
080            }
081        }
082        String maxZoom = args.get("max_zoom");
083        if (maxZoom != null && !maxZoom.isEmpty()) {
084            try {
085                imgInfo.setDefaultMaxZoom(Integer.parseInt(maxZoom));
086            } catch (NumberFormatException e) {
087                Main.error(e);
088            }
089        }
090        return imgInfo;
091    }
092
093    @Override
094    protected void handleRequest() throws RequestHandlerErrorException {
095        final ImageryInfo imgInfo = buildImageryInfo();
096        if (Main.isDisplayingMapView()) {
097            for (ImageryLayer layer : Main.map.mapView.getLayersOfType(ImageryLayer.class)) {
098                if (layer.getInfo().equals(imgInfo)) {
099                    Main.info("Imagery layer already exists: "+imgInfo);
100                    return;
101                }
102            }
103        }
104        GuiHelper.runInEDT(new Runnable() {
105            @Override
106            public void run() {
107                try {
108                    Main.main.addLayer(ImageryLayer.create(imgInfo));
109                } catch (IllegalArgumentException e) {
110                    Main.error(e, false);
111                }
112            }
113        });
114    }
115
116    @Override
117    protected void validateRequest() throws RequestHandlerBadRequestException {
118        String url = args != null ? args.get("url") : null;
119        String type = args != null ? args.get("type") : null;
120        String cookies = args != null ? args.get("cookies") : null;
121        try {
122            ImageryLayer.create(new ImageryInfo(null, url, type, null, cookies));
123        } catch (IllegalArgumentException e) {
124            throw new RequestHandlerBadRequestException(e.getMessage(), e);
125        }
126    }
127
128    @Override
129    public String getUsage() {
130        return "adds an imagery layer (e.g. WMS, TMS)";
131    }
132
133    @Override
134    public String[] getUsageExamples() {
135        final String types = Utils.join("|", Utils.transform(Arrays.asList(ImageryInfo.ImageryType.values()),
136                new Utils.Function<ImageryInfo.ImageryType, String>() {
137            @Override
138            public String apply(ImageryInfo.ImageryType x) {
139                return x.getTypeString();
140            }
141        }));
142        return new String[] {
143            "/imagery?title=osm&type=tms&url=https://a.tile.openstreetmap.org/%7Bzoom%7D/%7Bx%7D/%7By%7D.png",
144            "/imagery?title=landsat&type=wms&url=http://irs.gis-lab.info/?" +
145                    "layers=landsat&SRS=%7Bproj%7D&WIDTH=%7Bwidth%7D&HEIGHT=%7Bheight%7D&BBOX=%7Bbbox%7D",
146            "/imagery?title=...&type={"+types+"}&url=....[&cookies=...][&min_zoom=...][&max_zoom=...]"
147            };
148    }
149}