001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.io;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.io.IOException;
007 import java.io.InputStream;
008
009 import org.openstreetmap.josm.data.Bounds;
010 import org.openstreetmap.josm.data.gpx.GpxData;
011 import org.openstreetmap.josm.data.osm.DataSet;
012 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
013 import org.xml.sax.SAXException;
014
015 public class BoundingBoxDownloader extends OsmServerReader {
016
017 /**
018 * The boundings of the desired map data.
019 */
020 protected final double lat1;
021 protected final double lon1;
022 protected final double lat2;
023 protected final double lon2;
024 protected final boolean crosses180th;
025
026 public BoundingBoxDownloader(Bounds downloadArea) {
027 this.lat1 = downloadArea.getMin().lat();
028 this.lon1 = downloadArea.getMin().lon();
029 this.lat2 = downloadArea.getMax().lat();
030 this.lon2 = downloadArea.getMax().lon();
031 this.crosses180th = downloadArea.crosses180thMeridian();
032 }
033
034 private GpxData downloadRawGps(String url, ProgressMonitor progressMonitor) throws IOException, OsmTransferException, SAXException {
035 boolean done = false;
036 GpxData result = null;
037 for (int i = 0;!done;++i) {
038 progressMonitor.subTask(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
039 InputStream in = getInputStream(url+i, progressMonitor.createSubTaskMonitor(1, true));
040 if (in == null) {
041 break;
042 }
043 progressMonitor.setTicks(0);
044 GpxReader reader = new GpxReader(in);
045 gpxParsedProperly = reader.parse(false);
046 GpxData currentGpx = reader.data;
047 if (result == null) {
048 result = currentGpx;
049 } else if (currentGpx.hasTrackPoints()) {
050 result.mergeFrom(currentGpx);
051 } else{
052 done = true;
053 }
054 in.close();
055 activeConnection = null;
056 }
057 result.fromServer = true;
058 return result;
059 }
060
061 /**
062 * Retrieve raw gps waypoints from the server API.
063 * @return A list of all primitives retrieved. Currently, the list of lists
064 * contain only one list, since the server cannot distinguish between
065 * ways.
066 */
067 @Override
068 public GpxData parseRawGps(ProgressMonitor progressMonitor) throws OsmTransferException {
069 progressMonitor.beginTask("", 1);
070 try {
071 progressMonitor.indeterminateSubTask(tr("Contacting OSM Server..."));
072 if (crosses180th) {
073 // API 0.6 does not support requests crossing the 180th meridian, so make two requests
074 GpxData result = downloadRawGps("trackpoints?bbox="+lon1+","+lat1+",180.0,"+lat2+"&page=", progressMonitor);
075 result.mergeFrom(downloadRawGps("trackpoints?bbox=-180.0,"+lat1+","+lon2+","+lat2+"&page=", progressMonitor));
076 return result;
077 } else {
078 // Simple request
079 return downloadRawGps("trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=", progressMonitor);
080 }
081 } catch (IllegalArgumentException e) {
082 // caused by HttpUrlConnection in case of illegal stuff in the response
083 if (cancel)
084 return null;
085 throw new OsmTransferException("Illegal characters within the HTTP-header response.", e);
086 } catch (IOException e) {
087 if (cancel)
088 return null;
089 throw new OsmTransferException(e);
090 } catch (SAXException e) {
091 throw new OsmTransferException(e);
092 } catch (OsmTransferException e) {
093 throw e;
094 } catch (RuntimeException e) {
095 if (cancel)
096 return null;
097 throw e;
098 } finally {
099 progressMonitor.finishTask();
100 }
101 }
102
103 protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) {
104 return "map?bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2;
105 }
106
107 /**
108 * Read the data from the osm server address.
109 * @return A data set containing all data retrieved from that url
110 */
111 @Override
112 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
113 progressMonitor.beginTask(tr("Contacting OSM Server..."), 10);
114 InputStream in = null;
115 try {
116 DataSet ds = null;
117 progressMonitor.indeterminateSubTask(null);
118 if (crosses180th) {
119 // API 0.6 does not support requests crossing the 180th meridian, so make two requests
120 in = getInputStream(getRequestForBbox(lon1, lat1, 180.0, lat2), progressMonitor.createSubTaskMonitor(9, false));
121 if (in == null)
122 return null;
123 ds = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false));
124
125 in = getInputStream(getRequestForBbox(-180.0, lat1, lon2, lat2), progressMonitor.createSubTaskMonitor(9, false));
126 if (in == null)
127 return null;
128 DataSet ds2 = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false));
129 if (ds2 == null)
130 return null;
131 ds.mergeFrom(ds2);
132
133 } else {
134 // Simple request
135 in = getInputStream(getRequestForBbox(lon1, lat1, lon2, lat2), progressMonitor.createSubTaskMonitor(9, false));
136 if (in == null)
137 return null;
138 ds = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false));
139 }
140 return ds;
141 } catch(OsmTransferException e) {
142 throw e;
143 } catch (Exception e) {
144 throw new OsmTransferException(e);
145 } finally {
146 progressMonitor.finishTask();
147 if (in != null) {
148 try {in.close();} catch(IOException e) {}
149 }
150 activeConnection = null;
151 }
152 }
153 }