source: josm/trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java@ 5044

Last change on this file since 5044 was 5044, checked in by Don-vip, 12 years ago

fix #7471 - No suitable download task for XAPI queries with * for object type

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions.downloadtasks;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.util.Collection;
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.coor.LatLon;
15import org.openstreetmap.josm.data.osm.DataSet;
16import org.openstreetmap.josm.data.osm.DataSource;
17import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
18import org.openstreetmap.josm.gui.PleaseWaitRunnable;
19import org.openstreetmap.josm.gui.layer.Layer;
20import org.openstreetmap.josm.gui.layer.OsmDataLayer;
21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
22import org.openstreetmap.josm.io.BoundingBoxDownloader;
23import org.openstreetmap.josm.io.OsmServerLocationReader;
24import org.openstreetmap.josm.io.OsmServerReader;
25import org.openstreetmap.josm.io.OsmTransferCanceledException;
26import org.openstreetmap.josm.io.OsmTransferException;
27import org.xml.sax.SAXException;
28
29/**
30 * Open the download dialog and download the data.
31 * Run in the worker thread.
32 */
33public class DownloadOsmTask extends AbstractDownloadTask {
34 protected Bounds currentBounds;
35 protected DataSet downloadedData;
36 protected DownloadTask downloadTask;
37
38 protected OsmDataLayer targetLayer;
39
40 protected String newLayerName = null;
41
42 protected void rememberDownloadedData(DataSet ds) {
43 this.downloadedData = ds;
44 }
45
46 public DataSet getDownloadedData() {
47 return downloadedData;
48 }
49
50 public Future<?> download(boolean newLayer, Bounds downloadArea, ProgressMonitor progressMonitor) {
51
52 downloadTask = new DownloadTask(newLayer,
53 new BoundingBoxDownloader(downloadArea), progressMonitor);
54 currentBounds = new Bounds(downloadArea);
55 // We need submit instead of execute so we can wait for it to finish and get the error
56 // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
57 return Main.worker.submit(downloadTask);
58 }
59
60 /**
61 * Loads a given URL from the OSM Server
62 * @param True if the data should be saved to a new layer
63 * @param The URL as String
64 */
65 public Future<?> loadUrl(boolean new_layer, String url, ProgressMonitor progressMonitor) {
66 downloadTask = new DownloadTask(new_layer,
67 new OsmServerLocationReader(url),
68 progressMonitor);
69 currentBounds = null;
70 // Extract .osm filename from URL to set the new layer name
71 Matcher matcher = Pattern.compile("http://.*/(.*\\.osm)").matcher(url);
72 newLayerName = matcher.matches() ? matcher.group(1) : null;
73 return Main.worker.submit(downloadTask);
74 }
75
76 /* (non-Javadoc)
77 * @see org.openstreetmap.josm.actions.downloadtasks.DownloadTask#acceptsUrl(java.lang.String)
78 */
79 @Override
80 public boolean acceptsUrl(String url) {
81 return url != null && (
82 url.matches("http://.*/api/0.6/(map|nodes?|ways?|relations?|\\*).*")// OSM API 0.6 and XAPI
83 || url.matches("http://.*/interpreter\\?data=.*") // Overpass API
84 || url.matches("http://.*/xapi\\?.*\\[@meta\\].*") // Overpass API XAPI compatibility layer
85 || url.matches("http://.*/.*\\.osm") // Remote .osm files
86 );
87 }
88
89 public void cancel() {
90 if (downloadTask != null) {
91 downloadTask.cancel();
92 }
93 }
94
95 protected class DownloadTask extends PleaseWaitRunnable {
96 protected OsmServerReader reader;
97 protected DataSet dataSet;
98 protected boolean newLayer;
99
100 public DownloadTask(boolean newLayer, OsmServerReader reader, ProgressMonitor progressMonitor) {
101 super(tr("Downloading data"), progressMonitor, false);
102 this.reader = reader;
103 this.newLayer = newLayer;
104 }
105
106 protected DataSet parseDataSet() throws OsmTransferException {
107 return reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
108 }
109
110 @Override public void realRun() throws IOException, SAXException, OsmTransferException {
111 try {
112 if (isCanceled())
113 return;
114 dataSet = parseDataSet();
115 } catch(Exception e) {
116 if (isCanceled()) {
117 System.out.println(tr("Ignoring exception because download has been canceled. Exception was: {0}", e.toString()));
118 return;
119 }
120 if (e instanceof OsmTransferCanceledException) {
121 setCanceled(true);
122 return;
123 } else if (e instanceof OsmTransferException) {
124 rememberException(e);
125 } else {
126 rememberException(new OsmTransferException(e));
127 }
128 DownloadOsmTask.this.setFailed(true);
129 }
130 }
131
132 protected OsmDataLayer getEditLayer() {
133 if (!Main.isDisplayingMapView()) return null;
134 return Main.map.mapView.getEditLayer();
135 }
136
137 protected int getNumDataLayers() {
138 int count = 0;
139 if (!Main.isDisplayingMapView()) return 0;
140 Collection<Layer> layers = Main.map.mapView.getAllLayers();
141 for (Layer layer : layers) {
142 if (layer instanceof OsmDataLayer) {
143 count++;
144 }
145 }
146 return count;
147 }
148
149 protected OsmDataLayer getFirstDataLayer() {
150 if (!Main.isDisplayingMapView()) return null;
151 Collection<Layer> layers = Main.map.mapView.getAllLayersAsList();
152 for (Layer layer : layers) {
153 if (layer instanceof OsmDataLayer)
154 return (OsmDataLayer) layer;
155 }
156 return null;
157 }
158
159 protected OsmDataLayer createNewLayer(String layerName) {
160 if (layerName == null || layerName.isEmpty()) {
161 layerName = OsmDataLayer.createNewName();
162 }
163 return new OsmDataLayer(dataSet, layerName, null);
164 }
165
166 protected OsmDataLayer createNewLayer() {
167 return createNewLayer(null);
168 }
169
170 @Override protected void finish() {
171 if (isFailed() || isCanceled())
172 return;
173 if (dataSet == null)
174 return; // user canceled download or error occurred
175 if (dataSet.allPrimitives().isEmpty()) {
176 rememberErrorMessage(tr("No data found in this area."));
177 // need to synthesize a download bounds lest the visual indication of downloaded
178 // area doesn't work
179 dataSet.dataSources.add(new DataSource(currentBounds != null ? currentBounds : new Bounds(new LatLon(0, 0)), "OpenStreetMap server"));
180 }
181
182 rememberDownloadedData(dataSet);
183 int numDataLayers = getNumDataLayers();
184 if (newLayer || numDataLayers == 0 || (numDataLayers > 1 && getEditLayer() == null)) {
185 // the user explicitly wants a new layer, we don't have any layer at all
186 // or it is not clear which layer to merge to
187 //
188 targetLayer = createNewLayer(newLayerName);
189 final boolean isDisplayingMapView = Main.isDisplayingMapView();
190
191 Main.main.addLayer(targetLayer);
192
193 // If the mapView is not there yet, we cannot calculate the bounds (see constructor of MapView).
194 // Otherwise jump to the current download.
195 if (isDisplayingMapView) {
196 computeBboxAndCenterScale();
197 }
198 } else {
199 targetLayer = getEditLayer();
200 if (targetLayer == null) {
201 targetLayer = getFirstDataLayer();
202 }
203 targetLayer.mergeFrom(dataSet);
204 computeBboxAndCenterScale();
205 targetLayer.onPostDownloadFromServer();
206 }
207 }
208
209 protected void computeBboxAndCenterScale() {
210 BoundingXYVisitor v = new BoundingXYVisitor();
211 if (currentBounds != null) {
212 v.visit(currentBounds);
213 } else {
214 v.computeBoundingBox(dataSet.getNodes());
215 }
216 Main.map.mapView.recalculateCenterScale(v);
217 }
218
219 @Override protected void cancel() {
220 setCanceled(true);
221 if (reader != null) {
222 reader.cancel();
223 }
224 }
225 }
226}
Note: See TracBrowser for help on using the repository browser.