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.Collections; 009import java.util.List; 010import java.util.regex.Matcher; 011import java.util.regex.Pattern; 012 013import javax.swing.TransferHandler.TransferSupport; 014 015import org.openstreetmap.josm.Main; 016import org.openstreetmap.josm.data.coor.EastNorth; 017import org.openstreetmap.josm.data.coor.LatLon; 018import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 019import org.openstreetmap.josm.data.osm.PrimitiveId; 020import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 021import org.openstreetmap.josm.data.preferences.BooleanProperty; 022import org.openstreetmap.josm.gui.MapView; 023import org.openstreetmap.josm.gui.io.DownloadPrimitivesWithReferrersTask; 024import org.openstreetmap.josm.gui.layer.OsmDataLayer; 025 026/** 027 * Handles the paste / drop of an OSM address. 028 * <p> 029 * e.g. http://www.openstreetmap.org/node/123 downloads node 123 030 * 031 * @author Michael Zangl 032 * @since 10881 033 */ 034public class OsmLinkPaster extends AbstractOsmDataPaster { 035 036 private static final BooleanProperty PASTE_REFERRERS = new BooleanProperty("paste.url.download-referrers", true); 037 private static final String OSM_SERVER = "^https?\\://(\\w+\\.)?(osm|openstreetmap)\\.org/"; 038 039 /** 040 * Create a new Osm address paster 041 */ 042 public OsmLinkPaster() { 043 super(DataFlavor.stringFlavor); 044 } 045 046 @Override 047 public boolean importData(TransferSupport support, OsmDataLayer layer, EastNorth pasteAt) 048 throws UnsupportedFlavorException, IOException { 049 if (!supports(support)) { 050 throw new UnsupportedFlavorException(df); 051 } 052 053 String transferData = (String) support.getTransferable().getTransferData(df); 054 List<PrimitiveId> ids = parseIds(transferData); 055 056 if (!ids.isEmpty()) { 057 Main.worker.submit(new DownloadPrimitivesWithReferrersTask(layer == null, 058 ids, PASTE_REFERRERS.get(), PASTE_REFERRERS.get(), null, null)); 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 protected 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 085 static List<PrimitiveId> parseIds(String transferData) { 086 Matcher matcher = Pattern 087 .compile(OSM_SERVER + "(?<type>node|way|relation)/(?<id>\\d+)(\\/.*)?$") 088 .matcher(transferData); 089 090 if (!matcher.matches()) { 091 return Collections.emptyList(); 092 } 093 094 OsmPrimitiveType type; 095 switch (matcher.group("type")) { 096 case "way": 097 type = OsmPrimitiveType.WAY; 098 break; 099 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}