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

Last change on this file since 35 was 35, checked in by imi, 18 years ago
  • fixed bug in UTM
  • upload of nodes and segments
  • fixed bugs in display the selection
File size: 7.2 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 return data;
122 }
123
124 /**
125 * Parse and return an line segment. The node information of the "from" and
126 * "to" attributes must already be in the dataset.
127 * @param e The line segment element to parse.
128 * @param data The dataset to obtain the node information from.
129 * @return The parsed line segment.
130 * @throws JDOMException In case of parsing errors.
131 */
132 private LineSegment parseLineSegment(Element e, DataSet data) throws JDOMException {
133 long startId = Long.parseLong(e.getAttributeValue("from"));
134 long endId = Long.parseLong(e.getAttributeValue("to"));
135
136 Node start = null, end = null;
137 for (Node n : data.nodes) {
138 if (n.id == startId)
139 start = n;
140 if (n.id == endId)
141 end = n;
142 }
143 if (start == null || end == null)
144 throw new JDOMException("The 'from' or 'to' object has not been transfered before.");
145 LineSegment ls = new LineSegment(start, end);
146 parseCommon(ls, e);
147 return ls;
148 }
149
150 /**
151 * Parse and read a track from the element.
152 *
153 * @param e The element that contain the track.
154 * @param data The DataSet to get segment information from.
155 * @return The parsed track.
156 * @throws JDOMException In case of a parsing error.
157 */
158 private Track parseTrack(Element e, DataSet data) throws JDOMException {
159 Track track = new Track();
160 parseCommon(track, e);
161 for (Object o : e.getChildren("segment")) {
162 Element child = (Element)o;
163 long id = Long.parseLong(child.getAttributeValue("uid"));
164 LineSegment ls = findLineSegment(data.lineSegments, id);
165 track.segments.add(ls);
166 }
167 return track;
168 }
169
170 /**
171 * Parse the common part (properties and uid) of the element.
172 * @param data To store the data in.
173 * @param e The element to extract the common information.
174 * @throws JDOMException In case of a parsing error
175 */
176 private void parseCommon(OsmPrimitive data, Element e) {
177 String suid = e.getAttributeValue("uid");
178 if (suid != null)
179 data.id = Long.parseLong(suid);
180 if (data.id < 0)
181 data.id = 0;
182
183 String propStr = e.getAttributeValue("tags");
184 if (propStr != null && !propStr.equals("")) {
185 data.keys = new HashMap<Key, String>();
186 StringTokenizer st = new StringTokenizer(propStr, ";");
187 while (st.hasMoreTokens()) {
188 StringTokenizer t = new StringTokenizer(st.nextToken(), "=");
189 if (t.countTokens() > 1)
190 data.keys.put(Key.get(t.nextToken()), t.nextToken());
191 else {
192 String token = t.nextToken();
193 if (!" ".equals(token))
194 data.keys.put(Key.get(token), "");
195 }
196 }
197 }
198 }
199
200 /**
201 * Parse a property tag and assign the property to a previous found object.
202 */
203 private void parseProperty(Element e, DataSet data) throws JDOMException {
204 long id = Long.parseLong(e.getAttributeValue("uid"));
205 OsmPrimitive osm = findObject(data, id);
206 Key key = Key.get(e.getAttributeValue("key"));
207 String value = e.getAttributeValue("value");
208 if (value != null) {
209 if (osm.keys == null)
210 osm.keys = new HashMap<Key, String>();
211 osm.keys.put(key, value);
212 }
213 }
214
215 /**
216 * Search for an object in the dataset by comparing the id.
217 */
218 private OsmPrimitive findObject(DataSet data, long id) throws JDOMException {
219 for (OsmPrimitive osm : data.nodes)
220 if (osm.id == id)
221 return osm;
222 for (OsmPrimitive osm : data.lineSegments)
223 if (osm.id == id)
224 return osm;
225 for (OsmPrimitive osm : data.tracks)
226 if (osm.id == id)
227 return osm;
228 throw new JDOMException("Unknown object reference: "+id);
229 }
230
231 /**
232 * Search for a segment in a collection by comparing the id.
233 */
234 private LineSegment findLineSegment(Collection<LineSegment> segments, long id) throws JDOMException {
235 for (LineSegment ls : segments)
236 if (ls.id == id)
237 return ls;
238 throw new JDOMException("Unknown line segment reference: "+id);
239 }
240}
Note: See TracBrowser for help on using the repository browser.