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

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

fix #7857 - Mark osmChange primitives inside <modify> block as modified + allow to load remote .osc files

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