source: josm/trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java@ 10604

Last change on this file since 10604 was 10432, checked in by Don-vip, 8 years ago

fix #13001 - Add MainPanel + some new methods (patch by michael2402, modified) - gsoc-core

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions.downloadtasks;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.net.URL;
8import java.util.concurrent.Future;
9import java.util.regex.Matcher;
10import java.util.regex.Pattern;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.data.Bounds;
14import org.openstreetmap.josm.data.Bounds.ParseMethod;
15import org.openstreetmap.josm.data.ViewportData;
16import org.openstreetmap.josm.data.gpx.GpxData;
17import org.openstreetmap.josm.gui.PleaseWaitRunnable;
18import org.openstreetmap.josm.gui.layer.GpxLayer;
19import org.openstreetmap.josm.gui.layer.Layer;
20import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
22import org.openstreetmap.josm.gui.progress.ProgressTaskId;
23import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
24import org.openstreetmap.josm.io.BoundingBoxDownloader;
25import org.openstreetmap.josm.io.GpxImporter;
26import org.openstreetmap.josm.io.GpxImporter.GpxImporterData;
27import org.openstreetmap.josm.io.OsmServerLocationReader;
28import org.openstreetmap.josm.io.OsmServerReader;
29import org.openstreetmap.josm.io.OsmTransferException;
30import org.openstreetmap.josm.tools.CheckParameterUtil;
31import org.xml.sax.SAXException;
32
33/**
34 * Task allowing to download GPS data.
35 */
36public class DownloadGpsTask extends AbstractDownloadTask<GpxData> {
37
38 private DownloadTask downloadTask;
39
40 private static final String PATTERN_TRACE_ID = "https?://.*(osm|openstreetmap).org/trace/\\p{Digit}+/data";
41
42 private static final String PATTERN_TRACKPOINTS_BBOX = "https?://.*/api/0.6/trackpoints\\?bbox=.*,.*,.*,.*";
43
44 private static final String PATTERN_EXTERNAL_GPX_SCRIPT = "https?://.*exportgpx.*";
45 private static final String PATTERN_EXTERNAL_GPX_FILE = "https?://.*/(.*\\.gpx)";
46
47 protected String newLayerName;
48
49 @Override
50 public String[] getPatterns() {
51 return new String[] {PATTERN_EXTERNAL_GPX_FILE, PATTERN_EXTERNAL_GPX_SCRIPT, PATTERN_TRACE_ID, PATTERN_TRACKPOINTS_BBOX};
52 }
53
54 @Override
55 public String getTitle() {
56 return tr("Download GPS");
57 }
58
59 @Override
60 public Future<?> download(boolean newLayer, Bounds downloadArea, ProgressMonitor progressMonitor) {
61 downloadTask = new DownloadTask(newLayer,
62 new BoundingBoxDownloader(downloadArea), progressMonitor);
63 // We need submit instead of execute so we can wait for it to finish and get the error
64 // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
65 return Main.worker.submit(downloadTask);
66 }
67
68 @Override
69 public Future<?> loadUrl(boolean newLayer, String url, ProgressMonitor progressMonitor) {
70 CheckParameterUtil.ensureParameterNotNull(url, "url");
71 if (url.matches(PATTERN_TRACE_ID)
72 || url.matches(PATTERN_EXTERNAL_GPX_SCRIPT)
73 || url.matches(PATTERN_EXTERNAL_GPX_FILE)) {
74 downloadTask = new DownloadTask(newLayer,
75 new OsmServerLocationReader(url), progressMonitor);
76 // Extract .gpx filename from URL to set the new layer name
77 Matcher matcher = Pattern.compile(PATTERN_EXTERNAL_GPX_FILE).matcher(url);
78 newLayerName = matcher.matches() ? matcher.group(1) : null;
79 // We need submit instead of execute so we can wait for it to finish and get the error
80 // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
81 return Main.worker.submit(downloadTask);
82
83 } else if (url.matches(PATTERN_TRACKPOINTS_BBOX)) {
84 String[] table = url.split("\\?|=|&");
85 for (int i = 0; i < table.length; i++) {
86 if ("bbox".equals(table[i]) && i < table.length-1)
87 return download(newLayer, new Bounds(table[i+1], ",", ParseMethod.LEFT_BOTTOM_RIGHT_TOP), progressMonitor);
88 }
89 }
90 return null;
91 }
92
93 @Override
94 public void cancel() {
95 if (downloadTask != null) {
96 downloadTask.cancel();
97 }
98 }
99
100 class DownloadTask extends PleaseWaitRunnable {
101 private final OsmServerReader reader;
102 private GpxData rawData;
103 private final boolean newLayer;
104
105 DownloadTask(boolean newLayer, OsmServerReader reader, ProgressMonitor progressMonitor) {
106 super(tr("Downloading GPS data"), progressMonitor, false);
107 this.reader = reader;
108 this.newLayer = newLayer;
109 }
110
111 @Override
112 public void realRun() throws IOException, SAXException, OsmTransferException {
113 try {
114 if (isCanceled())
115 return;
116 ProgressMonitor subMonitor = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
117 rawData = reader.parseRawGps(subMonitor);
118 } catch (OsmTransferException e) {
119 if (isCanceled())
120 return;
121 rememberException(e);
122 }
123 }
124
125 @Override
126 protected void finish() {
127 rememberDownloadedData(rawData);
128 if (rawData == null)
129 return;
130 String name = newLayerName != null ? newLayerName : tr("Downloaded GPX Data");
131
132 GpxImporterData layers = GpxImporter.loadLayers(rawData, reader.isGpxParsedProperly(), name,
133 tr("Markers from {0}", name));
134
135 GpxLayer gpxLayer = addOrMergeLayer(layers.getGpxLayer(), findGpxMergeLayer());
136 addOrMergeLayer(layers.getMarkerLayer(), findMarkerMergeLayer(gpxLayer));
137
138 layers.getPostLayerTask().run();
139 }
140
141 private <L extends Layer> L addOrMergeLayer(L layer, L mergeLayer) {
142 if (layer == null) return null;
143 if (newLayer || mergeLayer == null) {
144 Main.getLayerManager().addLayer(layer);
145 return layer;
146 } else {
147 mergeLayer.mergeFrom(layer);
148 mergeLayer.invalidate();
149 if (Main.map != null) {
150 Main.map.mapView.scheduleZoomTo(new ViewportData(layer.getViewProjectionBounds()));
151 }
152 return mergeLayer;
153 }
154 }
155
156 private GpxLayer findGpxMergeLayer() {
157 boolean merge = Main.pref.getBoolean("download.gps.mergeWithLocal", false);
158 Layer active = Main.getLayerManager().getActiveLayer();
159 if (active instanceof GpxLayer && (merge || ((GpxLayer) active).data.fromServer))
160 return (GpxLayer) active;
161 for (GpxLayer l : Main.getLayerManager().getLayersOfType(GpxLayer.class)) {
162 if (merge || l.data.fromServer)
163 return l;
164 }
165 return null;
166 }
167
168 private MarkerLayer findMarkerMergeLayer(GpxLayer fromLayer) {
169 for (MarkerLayer l : Main.getLayerManager().getLayersOfType(MarkerLayer.class)) {
170 if (fromLayer != null && l.fromLayer == fromLayer)
171 return l;
172 }
173 return null;
174 }
175
176 @Override
177 protected void cancel() {
178 setCanceled(true);
179 if (reader != null) {
180 reader.cancel();
181 }
182 }
183
184 @Override
185 public ProgressTaskId canRunInBackground() {
186 return ProgressTaskIds.DOWNLOAD_GPS;
187 }
188 }
189
190 @Override
191 public String getConfirmationMessage(URL url) {
192 // TODO
193 return null;
194 }
195
196 @Override
197 public boolean isSafeForRemotecontrolRequests() {
198 return true;
199 }
200
201 /**
202 * Determines if the given URL denotes an OSM gpx-related API call.
203 * @param url The url to check
204 * @return true if the url matches "Trace ID" API call or "Trackpoints bbox" API call, false otherwise
205 * @see GpxData#fromServer
206 * @since 5745
207 */
208 public static final boolean isFromServer(String url) {
209 return url != null && (url.matches(PATTERN_TRACE_ID) || url.matches(PATTERN_TRACKPOINTS_BBOX));
210 }
211}
Note: See TracBrowser for help on using the repository browser.