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