source: josm/src/org/openstreetmap/josm/io/OsmReader.java@ 39

Last change on this file since 39 was 39, checked in by imi, 18 years ago
  • Select objects via overview (middle mouse button)
  • bugfix in deleted objects showing in overview
  • Error message when saving unknown extension
  • bugfix when reading osm files with new elements referenced
File size: 7.3 KB
Line 
1package org.openstreetmap.josm.io;
2
3import java.io.IOException;
4import java.io.Reader;
5import java.util.Collection;
6import java.util.HashMap;
7import java.util.StringTokenizer;
8
9import org.jdom.Element;
10import org.jdom.JDOMException;
11import org.jdom.input.SAXBuilder;
12import org.openstreetmap.josm.data.GeoPoint;
13import org.openstreetmap.josm.data.osm.DataSet;
14import org.openstreetmap.josm.data.osm.Key;
15import org.openstreetmap.josm.data.osm.LineSegment;
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.OsmPrimitive;
18import org.openstreetmap.josm.data.osm.Track;
19import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
20
21/**
22 * Reads an osm xml stream and construct a DataSet out of it.
23 *
24 * @author imi
25 */
26public class OsmReader {
27
28 /**
29 * The data source from this reader.
30 */
31 public Reader source;
32
33 /**
34 * Construct a parser from a specific data source.
35 * @param source The data source, as example a FileReader to read from a file.
36 */
37 public OsmReader(Reader source) {
38 this.source = source;
39 }
40 static int i;
41 /**
42 * Read the input stream and return a DataSet from the stream.
43 */
44 public DataSet parse() throws JDOMException, IOException {
45 try {
46 final SAXBuilder builder = new SAXBuilder();
47 Element root = builder.build(source).getRootElement();
48 return parseDataSet(root);
49 } catch (NumberFormatException nfe) {
50 throw new JDOMException("NumberFormatException. Probably a tag is missing.", nfe);
51 } catch (NullPointerException npe) {
52 throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);
53 } catch (ClassCastException cce) {
54 throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce);
55 }
56 }
57
58
59 /**
60 * Read one node.
61 * @param e The element to parse
62 * @return The Waypoint read from the element
63 * @throws JDOMException In case of a parsing error.
64 */
65 private Node parseNode(Element e) throws JDOMException {
66 Node data = new Node();
67 data.coor = new GeoPoint(
68 Float.parseFloat(e.getAttributeValue("lat")),
69 Float.parseFloat(e.getAttributeValue("lon")));
70 if (Double.isNaN(data.coor.lat) ||
71 data.coor.lat < -90 || data.coor.lat > 90 ||
72 data.coor.lon < -180 || data.coor.lon > 180)
73 throw new JDOMException("Illegal lat or lon value: "+data.coor.lat+"/"+data.coor.lon);
74 parseCommon(data, e);
75 return data;
76 }
77
78 /**
79 * Parse any (yet unknown) object and return it.
80 */
81 private OsmPrimitive parseObject(Element e, DataSet data) throws JDOMException {
82 if (e.getName().equals("node"))
83 return parseNode(e);
84 else if (e.getName().equals("segment"))
85 return parseLineSegment(e, data);
86 else if (e.getName().equals("track"))
87 return parseTrack(e, data);
88 else if (e.getName().equals("property")) {
89 parseProperty(e, data);
90 return null;
91 }
92 throw new JDOMException("unknown tag: "+e.getName());
93 }
94
95 /**
96 * Read a data set from the element.
97 * @param e The element to parse
98 * @return The DataSet read from the element
99 * @throws JDOMException In case of a parsing error.
100 */
101 private DataSet parseDataSet(Element e) throws JDOMException {
102 DataSet data = new DataSet();
103 AddVisitor visitor = new AddVisitor(data);
104 for (Object o : e.getChildren()) {
105 Element child = (Element)o;
106 if (child.getName().equals("deleted")) {
107 for (Object delObj : child.getChildren()) {
108 OsmPrimitive osm = parseObject((Element)delObj, data);
109 if (osm != null) {
110 osm.visit(visitor);
111 osm.setDeleted(true);
112 }
113 }
114 } else {
115 OsmPrimitive osm = parseObject(child, data);
116 if (osm != null)
117 osm.visit(visitor);
118 }
119 }
120
121 // clear all negative ids (new to this file)
122 for (OsmPrimitive osm : data.allPrimitives())
123 if (osm.id < 0)
124 osm.id = 0;
125
126 return data;
127 }
128
129 /**
130 * Parse and return an line segment. The node information of the "from" and
131 * "to" attributes must already be in the dataset.
132 * @param e The line segment element to parse.
133 * @param data The dataset to obtain the node information from.
134 * @return The parsed line segment.
135 * @throws JDOMException In case of parsing errors.
136 */
137 private LineSegment parseLineSegment(Element e, DataSet data) throws JDOMException {
138 long startId = Long.parseLong(e.getAttributeValue("from"));
139 long endId = Long.parseLong(e.getAttributeValue("to"));
140
141 Node start = null, end = null;
142 for (Node n : data.nodes) {
143 if (n.id == startId)
144 start = n;
145 if (n.id == endId)
146 end = n;
147 }
148 if (start == null || end == null)
149 throw new JDOMException("The 'from' or 'to' object has not been transfered before.");
150 LineSegment ls = new LineSegment(start, end);
151 parseCommon(ls, e);
152 return ls;
153 }
154
155 /**
156 * Parse and read a track from the element.
157 *
158 * @param e The element that contain the track.
159 * @param data The DataSet to get segment information from.
160 * @return The parsed track.
161 * @throws JDOMException In case of a parsing error.
162 */
163 private Track parseTrack(Element e, DataSet data) throws JDOMException {
164 Track track = new Track();
165 parseCommon(track, e);
166 for (Object o : e.getChildren("segment")) {
167 Element child = (Element)o;
168 long id = Long.parseLong(child.getAttributeValue("uid"));
169 LineSegment ls = findLineSegment(data.lineSegments, id);
170 track.segments.add(ls);
171 }
172 return track;
173 }
174
175 /**
176 * Parse the common part (properties and uid) of the element.
177 * @param data To store the data in.
178 * @param e The element to extract the common information.
179 * @throws JDOMException In case of a parsing error
180 */
181 private void parseCommon(OsmPrimitive data, Element e) {
182 String suid = e.getAttributeValue("uid");
183 if (suid != null)
184 data.id = Long.parseLong(suid);
185
186 String propStr = e.getAttributeValue("tags");
187 if (propStr != null && !propStr.equals("")) {
188 data.keys = new HashMap<Key, String>();
189 StringTokenizer st = new StringTokenizer(propStr, ";");
190 while (st.hasMoreTokens()) {
191 StringTokenizer t = new StringTokenizer(st.nextToken(), "=");
192 if (t.countTokens() > 1)
193 data.keys.put(Key.get(t.nextToken()), t.nextToken());
194 else {
195 String token = t.nextToken();
196 if (!" ".equals(token))
197 data.keys.put(Key.get(token), "");
198 }
199 }
200 }
201 }
202
203 /**
204 * Parse a property tag and assign the property to a previous found object.
205 */
206 private void parseProperty(Element e, DataSet data) throws JDOMException {
207 long id = Long.parseLong(e.getAttributeValue("uid"));
208 OsmPrimitive osm = findObject(data, id);
209 Key key = Key.get(e.getAttributeValue("key"));
210 String value = e.getAttributeValue("value");
211 if (value != null) {
212 if (osm.keys == null)
213 osm.keys = new HashMap<Key, String>();
214 osm.keys.put(key, value);
215 }
216 }
217
218 /**
219 * Search for an object in the dataset by comparing the id.
220 */
221 private OsmPrimitive findObject(DataSet data, long id) throws JDOMException {
222 for (OsmPrimitive osm : data.nodes)
223 if (osm.id == id)
224 return osm;
225 for (OsmPrimitive osm : data.lineSegments)
226 if (osm.id == id)
227 return osm;
228 for (OsmPrimitive osm : data.tracks)
229 if (osm.id == id)
230 return osm;
231 throw new JDOMException("Unknown object reference: "+id);
232 }
233
234 /**
235 * Search for a segment in a collection by comparing the id.
236 */
237 private LineSegment findLineSegment(Collection<LineSegment> segments, long id) throws JDOMException {
238 for (LineSegment ls : segments)
239 if (ls.id == id)
240 return ls;
241 throw new JDOMException("Unknown line segment reference: "+id);
242 }
243}
Note: See TracBrowser for help on using the repository browser.