001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.datatransfer.importers;
003
004import java.awt.Component;
005import java.awt.datatransfer.DataFlavor;
006import java.awt.datatransfer.UnsupportedFlavorException;
007import java.io.IOException;
008import java.util.regex.Matcher;
009import java.util.regex.Pattern;
010
011import javax.swing.TransferHandler.TransferSupport;
012
013import org.openstreetmap.josm.actions.OpenLocationAction;
014import org.openstreetmap.josm.data.coor.EastNorth;
015import org.openstreetmap.josm.data.coor.LatLon;
016import org.openstreetmap.josm.gui.MapView;
017import org.openstreetmap.josm.gui.layer.OsmDataLayer;
018
019/**
020 * Handles the paste / drop of an OSM address.
021 * <p>
022 * e.g. http://www.openstreetmap.org/node/123 downloads node 123
023 *
024 * @author Michael Zangl
025 * @since 10881
026 */
027public class OsmLinkPaster extends AbstractOsmDataPaster {
028
029    static final class NoWarnOpenLocationAction extends OpenLocationAction {
030
031        NoWarnOpenLocationAction() {
032            super(null);
033        }
034
035        @Override
036        protected void warnNoSuitableTasks(String url) {
037            // ignore this.
038        }
039    }
040
041    private static final String OSM_SERVER = "^https?\\://(\\w+\\.)?(osm|openstreetmap)\\.org/";
042
043    /**
044     * Create a new Osm address paster
045     */
046    public OsmLinkPaster() {
047        super(DataFlavor.stringFlavor);
048    }
049
050    @Override
051    public boolean importData(TransferSupport support, OsmDataLayer layer, EastNorth pasteAt)
052            throws UnsupportedFlavorException, IOException {
053        if (!supports(support)) {
054            throw new UnsupportedFlavorException(df);
055        }
056
057        String transferData = (String) support.getTransferable().getTransferData(df);
058        if (!new NoWarnOpenLocationAction().openUrl(transferData).isEmpty()) {
059            return true;
060        }
061
062        LatLon ll = parseLatLon(transferData);
063        if (ll != null) {
064            Component comp = support.getComponent();
065            if (comp instanceof MapView) {
066                ((MapView) comp).zoomTo(ll);
067            }
068        }
069
070        return false;
071    }
072
073    static LatLon parseLatLon(String transferData) {
074        Matcher matcher = Pattern
075                .compile(OSM_SERVER + "#map=(?<zoom>\\d+)/(?<lat>-?\\d+\\.\\d+)/(?<lon>-?\\d+\\.\\d+)$")
076                .matcher(transferData);
077
078        if (!matcher.matches()) {
079            return null;
080        } else {
081            return new LatLon(Double.parseDouble(matcher.group("lat")), Double.parseDouble(matcher.group("lon")));
082        }
083    }
084}