Ticket #13430: patch-paste-from-osm.patch

File patch-paste-from-osm.patch, 16.5 KB (added by michael2402, 9 years ago)
  • src/org/openstreetmap/josm/gui/GettingStarted.java

    diff --git a/src/org/openstreetmap/josm/gui/GettingStarted.java b/src/org/openstreetmap/josm/gui/GettingStarted.java
    index 3c05eea..f04b348 100644
    a b import javax.swing.event.HyperlinkListener;  
    2323
    2424import org.openstreetmap.josm.Main;
    2525import org.openstreetmap.josm.data.Version;
    26 import org.openstreetmap.josm.gui.datatransfer.FileTransferHandler;
     26import org.openstreetmap.josm.gui.datatransfer.OpenTransferHandler;
    2727import org.openstreetmap.josm.gui.preferences.server.ProxyPreference;
    2828import org.openstreetmap.josm.gui.preferences.server.ProxyPreferenceListener;
    2929import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
    public final class GettingStarted extends JPanel implements ProxyPreferenceListe  
    132132
    133133        getMOTD();
    134134
    135         setTransferHandler(new FileTransferHandler());
     135        setTransferHandler(new OpenTransferHandler());
    136136    }
    137137
    138138    private void getMOTD() {
  • new file src/org/openstreetmap/josm/gui/datatransfer/AbstractStackTransferHandler.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/AbstractStackTransferHandler.java b/src/org/openstreetmap/josm/gui/datatransfer/AbstractStackTransferHandler.java
    new file mode 100644
    index 0000000..de50169
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.datatransfer;
     3
     4import java.awt.datatransfer.UnsupportedFlavorException;
     5import java.io.IOException;
     6import java.util.Collection;
     7
     8import javax.swing.JComponent;
     9import javax.swing.TransferHandler;
     10
     11import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.data.coor.EastNorth;
     13import org.openstreetmap.josm.gui.datatransfer.importers.AbstractOsmDataPaster;
     14import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     15import org.openstreetmap.josm.tools.bugreport.BugReport;
     16
     17/**
     18 * A transfer handler class that allows you to manage a prioritized stack of transfer handlers.
     19 * @author Michael Zangl
     20 * @since xxx
     21 */
     22public abstract class AbstractStackTransferHandler extends TransferHandler {
     23
     24    protected abstract Collection<AbstractOsmDataPaster> getSupportedPasters();
     25
     26    @Override
     27    public int getSourceActions(JComponent c) {
     28        return COPY;
     29    }
     30
     31    @Override
     32    public boolean canImport(TransferSupport support) {
     33        // import everything for now, only support copy.
     34        for (AbstractOsmDataPaster df : getSupportedPasters()) {
     35            if (df.supports(support)) {
     36                return true;
     37            }
     38        }
     39        return false;
     40    }
     41
     42    @Override
     43    public boolean importData(TransferSupport support) {
     44        return importData(support, Main.getLayerManager().getEditLayer(), null);
     45    }
     46
     47    protected boolean importData(TransferSupport support, OsmDataLayer layer, EastNorth center) {
     48        for (AbstractOsmDataPaster df : getSupportedPasters()) {
     49            if (df.supports(support)) {
     50                try {
     51                    if (df.importData(support, layer, center)) {
     52                        return true;
     53                    }
     54                } catch (UnsupportedFlavorException | IOException e) {
     55                    Main.warn(e);
     56                } catch (RuntimeException e) {
     57                    BugReport.intercept(e).put("paster", df).put("flavors", () -> support.getDataFlavors()).warn();
     58                }
     59            }
     60        }
     61        return super.importData(support);
     62    }
     63
     64}
  • deleted file src/org/openstreetmap/josm/gui/datatransfer/FileTransferHandler.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/FileTransferHandler.java b/src/org/openstreetmap/josm/gui/datatransfer/FileTransferHandler.java
    deleted file mode 100644
    index 2274dfe..0000000
    + -  
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.datatransfer;
    3 
    4 import java.awt.datatransfer.UnsupportedFlavorException;
    5 import java.io.IOException;
    6 
    7 import javax.swing.JComponent;
    8 import javax.swing.TransferHandler;
    9 
    10 import org.openstreetmap.josm.Main;
    11 import org.openstreetmap.josm.gui.datatransfer.importers.FilePaster;
    12 
    13 /**
    14  * This transfer handler allows to drop files to open them.
    15  *
    16  * @author Michael Zangl
    17  * @since 10620
    18  */
    19 public class FileTransferHandler extends TransferHandler {
    20 
    21     private static final FilePaster filePaster = new FilePaster();
    22 
    23     @Override
    24     public int getSourceActions(JComponent c) {
    25         return COPY;
    26     }
    27 
    28     @Override
    29     public boolean canImport(TransferSupport support) {
    30         return filePaster.supports(support);
    31     }
    32 
    33     @Override
    34     public boolean importData(TransferSupport support) {
    35         try {
    36             if (filePaster.supports(support)) {
    37                 return filePaster.importData(support, null, null);
    38             }
    39         } catch (UnsupportedFlavorException | IOException e) {
    40             Main.warn(e, "Error while importing file.");
    41         }
    42         return super.importData(support);
    43     }
    44 }
  • new file src/org/openstreetmap/josm/gui/datatransfer/OpenTransferHandler.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/OpenTransferHandler.java b/src/org/openstreetmap/josm/gui/datatransfer/OpenTransferHandler.java
    new file mode 100644
    index 0000000..cf9a05c
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.datatransfer;
     3
     4import java.util.Arrays;
     5import java.util.Collection;
     6
     7import org.openstreetmap.josm.gui.datatransfer.importers.AbstractOsmDataPaster;
     8import org.openstreetmap.josm.gui.datatransfer.importers.FilePaster;
     9import org.openstreetmap.josm.gui.datatransfer.importers.OsmLinkPaster;
     10
     11/**
     12 * This transfer handler allows to e.g. drop files to open them.
     13 *
     14 * @author Michael Zangl
     15 * @since 10620
     16 * @since xxx rename
     17 */
     18public class OpenTransferHandler extends AbstractStackTransferHandler {
     19
     20    private static final Collection<AbstractOsmDataPaster> SUPPORTED = Arrays.asList(new FilePaster(), new OsmLinkPaster());
     21
     22    @Override
     23    protected Collection<AbstractOsmDataPaster> getSupportedPasters() {
     24        return SUPPORTED;
     25    }
     26}
  • src/org/openstreetmap/josm/gui/datatransfer/OsmTransferHandler.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/OsmTransferHandler.java b/src/org/openstreetmap/josm/gui/datatransfer/OsmTransferHandler.java
    index fdc8b89..a8f7dc8 100644
    a b import java.io.IOException;  
    88import java.util.Arrays;
    99import java.util.Collection;
    1010
    11 import javax.swing.TransferHandler;
    12 
    1311import org.openstreetmap.josm.Main;
    1412import org.openstreetmap.josm.data.coor.EastNorth;
    1513import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1614import org.openstreetmap.josm.gui.datatransfer.importers.AbstractOsmDataPaster;
    1715import org.openstreetmap.josm.gui.datatransfer.importers.FilePaster;
     16import org.openstreetmap.josm.gui.datatransfer.importers.OsmLinkPaster;
    1817import org.openstreetmap.josm.gui.datatransfer.importers.PrimitiveDataPaster;
    1918import org.openstreetmap.josm.gui.datatransfer.importers.PrimitiveTagTransferPaster;
    2019import org.openstreetmap.josm.gui.datatransfer.importers.TagTransferPaster;
    import org.openstreetmap.josm.gui.layer.OsmDataLayer;  
    2625 * @author Michael Zangl
    2726 * @since 10604
    2827 */
    29 public class OsmTransferHandler extends TransferHandler {
     28public class OsmTransferHandler extends AbstractStackTransferHandler {
    3029
    3130    private static final Collection<AbstractOsmDataPaster> SUPPORTED = Arrays.asList(
    3231            new FilePaster(), new PrimitiveDataPaster(),
    3332            new PrimitiveTagTransferPaster(),
    34             new TagTransferPaster(), new TextTagPaster());
     33            new TagTransferPaster(), new OsmLinkPaster(), new TextTagPaster());
    3534
    3635    @Override
    37     public boolean canImport(TransferSupport support) {
    38         // import everything for now, only support copy.
    39         for (AbstractOsmDataPaster df : SUPPORTED) {
    40             if (df.supports(support)) {
    41                 return true;
    42             }
    43         }
    44         return false;
    45     }
    46 
    47     @Override
    48     public boolean importData(TransferSupport support) {
    49         return importData(support, Main.getLayerManager().getEditLayer(), null);
    50     }
    51 
    52     private boolean importData(TransferSupport support, OsmDataLayer layer, EastNorth center) {
    53         for (AbstractOsmDataPaster df : SUPPORTED) {
    54             if (df.supports(support)) {
    55                 try {
    56                     if (df.importData(support, layer, center)) {
    57                         return true;
    58                     }
    59                 } catch (UnsupportedFlavorException | IOException e) {
    60                     Main.warn(e);
    61                 }
    62             }
    63         }
    64         return super.importData(support);
     36    protected Collection<AbstractOsmDataPaster> getSupportedPasters() {
     37        return SUPPORTED;
    6538    }
    6639
    6740    private boolean importTags(TransferSupport support, Collection<? extends OsmPrimitive> primitives) {
  • src/org/openstreetmap/josm/gui/datatransfer/importers/AbstractOsmDataPaster.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/importers/AbstractOsmDataPaster.java b/src/org/openstreetmap/josm/gui/datatransfer/importers/AbstractOsmDataPaster.java
    index f9aa4c3..619b9f9 100644
    a b public abstract class AbstractOsmDataPaster {  
    5656    /**
    5757     * Attempts to import the given transfer data.
    5858     * @param support The transfer support to import from.
    59      * @param layer The layer to paste at.
     59     * @param layer The layer to paste at. May be null.
    6060     * @param pasteAt The position to paste at.
    6161     * @return <code>true</code> if the import was successful.
    6262     * @throws UnsupportedFlavorException if the requested data flavor is not supported
  • new file src/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPaster.java

    diff --git a/src/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPaster.java b/src/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPaster.java
    new file mode 100644
    index 0000000..1f990c1
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.datatransfer.importers;
     3
     4import java.awt.Component;
     5import java.awt.datatransfer.DataFlavor;
     6import java.awt.datatransfer.UnsupportedFlavorException;
     7import java.io.IOException;
     8import java.util.Collections;
     9import java.util.List;
     10import java.util.regex.Matcher;
     11import java.util.regex.Pattern;
     12
     13import javax.swing.TransferHandler.TransferSupport;
     14
     15import org.openstreetmap.josm.Main;
     16import org.openstreetmap.josm.data.coor.EastNorth;
     17import org.openstreetmap.josm.data.coor.LatLon;
     18import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     19import org.openstreetmap.josm.data.osm.PrimitiveId;
     20import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
     21import org.openstreetmap.josm.data.preferences.BooleanProperty;
     22import org.openstreetmap.josm.gui.MapView;
     23import org.openstreetmap.josm.gui.io.DownloadPrimitivesWithReferrersTask;
     24import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     25
     26/**
     27 * Handles the paste / drop of an OSM address.
     28 * <p>
     29 * e.g. http://www.openstreetmap.org/node/123 downloads node 123
     30 *
     31 * @author Michael Zangl
     32 * @since xxx
     33 */
     34public class OsmLinkPaster extends AbstractOsmDataPaster {
     35
     36    private static final BooleanProperty PASTE_REFERRERS = new BooleanProperty("paste.url.download-referrers", true);
     37    private static final String OSM_SERVER = "^https?\\://(\\w+\\.)?(osm|openstreetmap)\\.org/";
     38
     39    /**
     40     * Create a new Osm address paster
     41     */
     42    public OsmLinkPaster() {
     43        super(DataFlavor.stringFlavor);
     44    }
     45
     46    @Override
     47    public boolean importData(TransferSupport support, OsmDataLayer layer, EastNorth pasteAt)
     48            throws UnsupportedFlavorException, IOException {
     49        if (!supports(support)) {
     50            throw new UnsupportedFlavorException(df);
     51        }
     52
     53        String transferData = (String) support.getTransferable().getTransferData(df);
     54        List<PrimitiveId> ids = parseIds(transferData);
     55
     56        if (!ids.isEmpty()) {
     57            Main.worker.submit(new DownloadPrimitivesWithReferrersTask(layer == null,
     58                    ids, PASTE_REFERRERS.get(), PASTE_REFERRERS.get(), null, null));
     59            return true;
     60        }
     61
     62        LatLon ll = parseLatLon(transferData);
     63        if (ll != null) {
     64            Component comp = support.getComponent();
     65            if (comp instanceof MapView) {
     66                ((MapView) comp).zoomTo(ll);
     67            }
     68        }
     69
     70        return false;
     71    }
     72
     73    protected static LatLon parseLatLon(String transferData) {
     74        Matcher matcher = Pattern
     75                .compile(OSM_SERVER + "#map=(?<zoom>\\d+)/(?<lat>-?\\d+\\.\\d+)/(?<lon>-?\\d+\\.\\d+)$")
     76                .matcher(transferData);
     77
     78        if (!matcher.matches()) {
     79            return null;
     80        } else {
     81            return new LatLon(Double.parseDouble(matcher.group("lat")), Double.parseDouble(matcher.group("lon")));
     82        }
     83    }
     84
     85    static List<PrimitiveId> parseIds(String transferData) {
     86        Matcher matcher = Pattern
     87                .compile(OSM_SERVER + "(?<type>node|way|relation)/(?<id>\\d+)(\\/.*)?$")
     88                .matcher(transferData);
     89
     90        if (!matcher.matches()) {
     91            return Collections.emptyList();
     92        }
     93
     94        OsmPrimitiveType type;
     95        switch (matcher.group("type")) {
     96        case "way":
     97            type = OsmPrimitiveType.WAY;
     98            break;
     99
     100        case "node":
     101            type = OsmPrimitiveType.NODE;
     102            break;
     103
     104        case "relation":
     105            type = OsmPrimitiveType.RELATION;
     106            break;
     107
     108        default:
     109            throw new AssertionError();
     110        }
     111
     112        return Collections.singletonList(new SimplePrimitiveId(Long.parseLong(matcher.group("id")), type));
     113    }
     114
     115}
  • new file test/unit/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPasterTest.java

    diff --git a/test/unit/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPasterTest.java b/test/unit/org/openstreetmap/josm/gui/datatransfer/importers/OsmLinkPasterTest.java
    new file mode 100644
    index 0000000..a227b93
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.datatransfer.importers;
     3
     4import static org.junit.Assert.assertArrayEquals;
     5
     6import org.junit.Rule;
     7import org.junit.Test;
     8import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     9import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
     10import org.openstreetmap.josm.testutils.JOSMTestRules;
     11
     12import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     13
     14/**
     15 * Test {@link OsmLinkPaster}
     16 * @author Michael Zangl
     17 * @since xxx
     18 */
     19public class OsmLinkPasterTest {
     20    /**
     21     * No dependencies
     22     */
     23    @Rule
     24    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     25    public JOSMTestRules test = new JOSMTestRules();
     26
     27    /**
     28     * Test of {@link OsmLinkPaster#parseIds(String)}
     29     */
     30    @Test
     31    public void testParseIds() {
     32        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.NODE) },
     33                OsmLinkPaster.parseIds("http://www.openstreetmap.org/node/1234").toArray());
     34        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.WAY) },
     35                OsmLinkPaster.parseIds("http://www.openstreetmap.org/way/1234").toArray());
     36        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.RELATION) },
     37                OsmLinkPaster.parseIds("http://www.openstreetmap.org/relation/1234").toArray());
     38
     39        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.NODE) },
     40                OsmLinkPaster.parseIds("http://www.osm.org/node/1234").toArray());
     41        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.WAY) },
     42                OsmLinkPaster.parseIds("http://osm.org/way/1234").toArray());
     43        assertArrayEquals(new Object[] { new SimplePrimitiveId(1234, OsmPrimitiveType.RELATION) },
     44                OsmLinkPaster.parseIds("https://www.openstreetmap.org/relation/1234").toArray());
     45
     46
     47        assertArrayEquals(new Object[0], OsmLinkPaster.parseIds("http://www.openstreetmap.org/xx/1234").toArray());
     48        assertArrayEquals(new Object[0], OsmLinkPaster.parseIds("http://www.openstreetmap.org/way/1234x").toArray());
     49        assertArrayEquals(new Object[0], OsmLinkPaster.parseIds("").toArray());
     50    }
     51
     52}