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

Last change on this file was 17787, checked in by simon04, 5 years ago

fix #20741 - Various code simplifications (patch by gaben)

  • Property svn:eol-style set to native
File size: 8.8 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.Objects;
9import java.util.Optional;
10import java.util.concurrent.Future;
11import java.util.regex.Matcher;
12import java.util.stream.Stream;
13
14import org.openstreetmap.josm.data.Bounds;
15import org.openstreetmap.josm.data.Bounds.ParseMethod;
16import org.openstreetmap.josm.data.ProjectionBounds;
17import org.openstreetmap.josm.data.gpx.GpxConstants;
18import org.openstreetmap.josm.data.gpx.GpxData;
19import org.openstreetmap.josm.gui.MainApplication;
20import org.openstreetmap.josm.gui.PleaseWaitRunnable;
21import org.openstreetmap.josm.gui.io.importexport.GpxImporter;
22import org.openstreetmap.josm.gui.io.importexport.GpxImporter.GpxImporterData;
23import org.openstreetmap.josm.gui.layer.GpxLayer;
24import org.openstreetmap.josm.gui.layer.GpxRouteLayer;
25import org.openstreetmap.josm.gui.layer.Layer;
26import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
27import org.openstreetmap.josm.gui.progress.ProgressMonitor;
28import org.openstreetmap.josm.gui.progress.ProgressTaskId;
29import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
30import org.openstreetmap.josm.io.BoundingBoxDownloader;
31import org.openstreetmap.josm.io.OsmServerLocationReader;
32import org.openstreetmap.josm.io.OsmServerReader;
33import org.openstreetmap.josm.io.OsmTransferException;
34import org.openstreetmap.josm.io.UrlPatterns.GpxUrlPattern;
35import org.openstreetmap.josm.spi.preferences.Config;
36import org.openstreetmap.josm.tools.Utils;
37import org.xml.sax.SAXException;
38
39/**
40 * Task allowing to download GPS data.
41 */
42public class DownloadGpsTask extends AbstractDownloadTask<GpxData> {
43
44 private DownloadTask downloadTask;
45 private GpxLayer gpxLayer;
46
47 protected String url;
48
49 @Override
50 public String[] getPatterns() {
51 return patterns(GpxUrlPattern.class);
52 }
53
54 @Override
55 public String getTitle() {
56 return tr("Download GPS");
57 }
58
59 @Override
60 public Future<?> download(DownloadParams settings, Bounds downloadArea, ProgressMonitor progressMonitor) {
61 downloadTask = new DownloadTask(settings,
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 MainApplication.worker.submit(downloadTask);
66 }
67
68 @Override
69 public Future<?> loadUrl(DownloadParams settings, String url, ProgressMonitor progressMonitor) {
70 this.url = Objects.requireNonNull(url);
71 final Optional<String> mappedUrl = Stream.of(GpxUrlPattern.USER_TRACE_ID, GpxUrlPattern.EDIT_TRACE_ID)
72 .map(p -> p.matcher(url))
73 .filter(Matcher::matches)
74 .map(m -> "https://www.openstreetmap.org/trace/" + m.group(2) + "/data")
75 .findFirst();
76 if (mappedUrl.isPresent()) {
77 return loadUrl(settings, mappedUrl.get(), progressMonitor);
78 }
79 if (Stream.of(GpxUrlPattern.TRACE_ID, GpxUrlPattern.EXTERNAL_GPX_SCRIPT,
80 GpxUrlPattern.EXTERNAL_GPX_FILE, GpxUrlPattern.TASKING_MANAGER)
81 .anyMatch(p -> p.matches(url))) {
82 downloadTask = new DownloadTask(settings,
83 new OsmServerLocationReader(url), progressMonitor);
84 // We need submit instead of execute so we can wait for it to finish and get the error
85 // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
86 return MainApplication.worker.submit(downloadTask);
87
88 } else if (GpxUrlPattern.TRACKPOINTS_BBOX.matches(url)) {
89 String[] table = url.split("[?=&]", -1);
90 for (int i = 0; i < table.length; i++) {
91 if ("bbox".equals(table[i]) && i < table.length-1)
92 return download(settings, new Bounds(table[i+1], ",", ParseMethod.LEFT_BOTTOM_RIGHT_TOP), progressMonitor);
93 }
94 }
95 return null;
96 }
97
98 @Override
99 public void cancel() {
100 if (downloadTask != null) {
101 downloadTask.cancel();
102 }
103 }
104
105 @Override
106 public ProjectionBounds getDownloadProjectionBounds() {
107 return gpxLayer != null ? gpxLayer.getViewProjectionBounds() : null;
108 }
109
110 class DownloadTask extends PleaseWaitRunnable {
111 private final OsmServerReader reader;
112 private GpxData rawData;
113 private final boolean newLayer;
114
115 DownloadTask(DownloadParams settings, OsmServerReader reader, ProgressMonitor progressMonitor) {
116 super(tr("Downloading GPS data"), progressMonitor, false);
117 this.reader = reader;
118 this.newLayer = settings.isNewLayer();
119 }
120
121 @Override
122 public void realRun() throws IOException, SAXException, OsmTransferException {
123 try {
124 if (isCanceled())
125 return;
126 rawData = reader.parseRawGps(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
127 } catch (OsmTransferException e) {
128 if (isCanceled())
129 return;
130 rememberException(e);
131 }
132 }
133
134 @Override
135 protected void finish() {
136 rememberDownloadedData(rawData);
137 if (rawData == null)
138 return;
139 String name = getLayerName();
140
141 GpxImporterData layers = GpxImporter.loadLayers(rawData, reader.isGpxParsedProperly(), name);
142
143 gpxLayer = layers.getGpxLayer();
144 addOrMergeLayer(gpxLayer, findGpxMergeLayer());
145 addOrMergeLayer(layers.getMarkerLayer(), findMarkerMergeLayer(gpxLayer));
146 addOrMergeLayer(layers.getGpxRouteLayer(), findGpxRouteMergeLayer(gpxLayer));
147
148 layers.getPostLayerTask().run();
149 }
150
151 private String getLayerName() {
152 // Extract .gpx filename from URL to set the new layer name
153 final Matcher matcher = url != null ? GpxUrlPattern.EXTERNAL_GPX_FILE.matcher(url) : null;
154 final String newLayerName = matcher != null && matcher.matches() ? matcher.group(1) : null;
155 final String metadataName = rawData != null ? rawData.getString(GpxConstants.META_NAME) : null;
156 final String defaultName = tr("Downloaded GPX Data");
157
158 if (Config.getPref().getBoolean("gpx.prefermetadataname", false)) {
159 return Utils.firstNotEmptyString(defaultName, metadataName, newLayerName);
160 } else {
161 return Utils.firstNotEmptyString(defaultName, newLayerName, metadataName);
162 }
163 }
164
165 private <L extends Layer> L addOrMergeLayer(L layer, L mergeLayer) {
166 if (layer == null) return null;
167 if (newLayer || mergeLayer == null) {
168 MainApplication.getLayerManager().addLayer(layer, zoomAfterDownload);
169 return layer;
170 } else {
171 mergeLayer.mergeFrom(layer);
172 mergeLayer.invalidate();
173 return mergeLayer;
174 }
175 }
176
177 private GpxLayer findGpxMergeLayer() {
178 boolean merge = Config.getPref().getBoolean("download.gps.mergeWithLocal", false);
179 Layer active = MainApplication.getLayerManager().getActiveLayer();
180 if (active instanceof GpxLayer && (merge || ((GpxLayer) active).data.fromServer))
181 return (GpxLayer) active;
182 return MainApplication.getLayerManager().getLayersOfType(GpxLayer.class).stream()
183 .filter(l -> merge || l.data.fromServer)
184 .findFirst().orElse(null);
185 }
186
187 private MarkerLayer findMarkerMergeLayer(GpxLayer fromLayer) {
188 return MainApplication.getLayerManager().getLayersOfType(MarkerLayer.class).stream()
189 .filter(l -> fromLayer != null && l.fromLayer == fromLayer)
190 .findFirst().orElse(null);
191 }
192
193 private GpxRouteLayer findGpxRouteMergeLayer(GpxLayer fromLayer) {
194 return MainApplication.getLayerManager().getLayersOfType(GpxRouteLayer.class).stream()
195 .filter(l -> fromLayer != null && l.fromLayer == fromLayer)
196 .findFirst().orElse(null);
197 }
198
199 @Override
200 protected void cancel() {
201 setCanceled(true);
202 if (reader != null) {
203 reader.cancel();
204 }
205 }
206
207 @Override
208 public ProgressTaskId canRunInBackground() {
209 return ProgressTaskIds.DOWNLOAD_GPS;
210 }
211 }
212
213 @Override
214 public String getConfirmationMessage(URL url) {
215 // TODO
216 return null;
217 }
218
219 @Override
220 public boolean isSafeForRemotecontrolRequests() {
221 return true;
222 }
223}
Note: See TracBrowser for help on using the repository browser.