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

Last change on this file since 5097 was 5097, checked in by simon04, 12 years ago

see #7511 - make DownloadDialog, Osm download related classes more adaptable

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