source: josm/src/org/openstreetmap/josm/io/GpxReader.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 static org.openstreetmap.josm.io.GpxWriter.GPX;
4import static org.openstreetmap.josm.io.GpxWriter.OSM;
5import static org.openstreetmap.josm.io.GpxWriter.JOSM;
6
7import java.io.IOException;
8import java.io.Reader;
9import java.util.HashMap;
10
11import org.jdom.Element;
12import org.jdom.JDOMException;
13import org.jdom.input.SAXBuilder;
14import org.openstreetmap.josm.data.GeoPoint;
15import org.openstreetmap.josm.data.osm.DataSet;
16import org.openstreetmap.josm.data.osm.Key;
17import org.openstreetmap.josm.data.osm.LineSegment;
18import org.openstreetmap.josm.data.osm.Node;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20import org.openstreetmap.josm.data.osm.Track;
21
22/**
23 * Reads an gpx stream and construct a DataSet out of it.
24 * Some information may not be imported, but GpxReader tries its best to load
25 * all data possible in the key/value structure.
26 *
27 * @author imi
28 */
29public class GpxReader {
30
31 /**
32 * The data source from this reader.
33 */
34 public Reader source;
35
36 /**
37 * Construct a parser from a specific data source.
38 * @param source The data source, as example a FileReader to read from a file.
39 */
40 public GpxReader(Reader source) {
41 this.source = source;
42 }
43
44 /**
45 * Read the input stream and return a DataSet from the stream.
46 */
47 public DataSet parse() throws JDOMException, IOException {
48 try {
49 final SAXBuilder builder = new SAXBuilder();
50 Element root = builder.build(source).getRootElement();
51 return parseDataSet(root);
52 } catch (NullPointerException npe) {
53 throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);
54 } catch (ClassCastException cce) {
55 throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce);
56 }
57 }
58
59
60 /**
61 * Read one node (waypoint).
62 * @param e The element to parse
63 * @return The Waypoint read from the element
64 */
65 private Node parseWaypoint(Element e) {
66 Node data = new Node();
67 data.coor = new GeoPoint(
68 Float.parseFloat(e.getAttributeValue("lat")),
69 Float.parseFloat(e.getAttributeValue("lon")));
70
71 for (Object o : e.getChildren()) {
72 Element child = (Element)o;
73 if (child.getName().equals("extensions"))
74 parseKeyValueExtensions(data, child);
75 else if (child.getName().equals("link"))
76 parseKeyValueLink(data, child);
77 else
78 parseKeyValueTag(data, child);
79 }
80 return data;
81 }
82
83 /**
84 * Read a data set from the element.
85 * @param e The element to parse
86 * @return The DataSet read from the element
87 */
88 private DataSet parseDataSet(Element e) {
89 DataSet data = new DataSet();
90 // read waypoints not contained in tracks or areas
91 for (Object o : e.getChildren("wpt", GPX))
92 addNode(data, parseWaypoint((Element)o));
93
94 // read tracks (and line segments)
95 for (Object trackElement : e.getChildren("trk", GPX))
96 parseTrack((Element)trackElement, data);
97
98 return data;
99 }
100
101 /**
102 * Parse and read a track from the element. Store it in the dataSet, as well
103 * as all nodes in it.
104 *
105 * @param e The element that contain the track.
106 * @param ds The DataSet to store the data in.
107 */
108 private void parseTrack(Element e, DataSet ds) {
109 Track track = new Track();
110 boolean realLineSegment = false; // is this track just a fake?
111
112 for (Object o : e.getChildren()) {
113 Element child = (Element)o;
114
115 if (child.getName().equals("trkseg")) {
116 Node start = null;
117 for (Object w : child.getChildren("trkpt", GPX)) {
118 Node node = parseWaypoint((Element)w);
119 node = addNode(ds, node);
120 if (start == null)
121 start = node;
122 else {
123 LineSegment lineSegment = new LineSegment(start, node);
124 parseKeyValueExtensions(lineSegment, child.getChild("extensions", GPX));
125 track.segments.add(lineSegment);
126 start = null;
127 }
128 }
129 } else if (child.getName().equals("extensions")) {
130 parseKeyValueExtensions(track, child);
131 if (child.getChild("segment", JOSM) != null)
132 realLineSegment = true;
133 } else if (child.getName().equals("link"))
134 parseKeyValueLink(track, child);
135 else
136 parseKeyValueTag(track, child);
137 }
138 ds.lineSegments.addAll(track.segments);
139 if (!realLineSegment)
140 ds.tracks.add(track);
141 }
142
143
144 /**
145 * Adds the node to allNodes if it is not already listed. Does respect the
146 * preference setting "mergeNodes". Return the node in the list that correspond
147 * to the node in the list (either the new added or the old found).
148 *
149 * If reading raw gps data, mergeNodes are always on (To save memory. You
150 * can't edit raw gps nodes anyway.)
151 *
152 * @param data The DataSet to add the node to.
153 * @param node The node that should be added.
154 * @return Either the parameter node or the old node found in the dataset.
155 */
156 private Node addNode(DataSet data, Node node) {
157 for (Node n : data.nodes)
158 if (node.coor.equalsLatLon(n.coor))
159 return n;
160 data.nodes.add(node);
161 return node;
162 }
163
164 /**
165 * Parse the extensions tag and add all properties found as key/value.
166 * <code>osm.keys</code> may be <code>null</code>, in which case it is
167 * created first. If <code>e</code> is <code>null</code>, nothing
168 * happens.
169 *
170 * @param osm The primitive to store the properties.
171 * @param e The extensions element to read the properties from.
172 */
173 private void parseKeyValueExtensions(OsmPrimitive osm, Element e) {
174 if (e != null) {
175 for (Object o : e.getChildren("property", OSM)) {
176 if (osm.keys == null)
177 osm.keys = new HashMap<Key, String>();
178 Element child = (Element)o;
179 String keyname = child.getAttributeValue("key");
180 if (keyname != null) {
181 Key key = Key.get(keyname);
182 String value = child.getAttributeValue("value");
183 if (value == null)
184 value = "";
185 osm.keys.put(key, value);
186 }
187 }
188 Element idElement = e.getChild("uid", JOSM);
189 if (idElement != null)
190 osm.id = Long.parseLong(idElement.getText());
191 osm.modified = e.getChild("modified", JOSM) != null;
192 osm.modifiedProperties = e.getChild("modifiedProperties", JOSM) != null;
193 }
194 }
195
196 /**
197 * If the element is not <code>null</code>, read the data from it and put
198 * it as the key with the name of the elements name in the given object.
199 *
200 * The <code>keys</code> - field of the element could be <code>null</code>,
201 * in which case it is created first.
202 *
203 * @param osm The osm primitive to put the key into.
204 * @param e The element to look for data.
205 */
206 private void parseKeyValueTag(OsmPrimitive osm, Element e) {
207 if (e != null) {
208 if (osm.keys == null)
209 osm.keys = new HashMap<Key, String>();
210 osm.keys.put(Key.get(e.getName()), e.getValue());
211 }
212 }
213
214 /**
215 * Parse the GPX linkType data information and store it as value in the
216 * primitives <i>link</i> key. <code>osm.keys</code> may be
217 * <code>null</code>, in which case it is created first. If
218 * <code>e</code> is <code>null</code>, nothing happens.
219 *
220 * The format stored is: mimetype;url
221 * Example: text/html;http://www.openstreetmap.org
222 *
223 * @param osm The osm primitive to store the data in.
224 * @param e The element in gpx:linkType - format.
225 */
226 private void parseKeyValueLink(OsmPrimitive osm, Element e) {
227 if (e != null) {
228 if (osm.keys == null)
229 osm.keys = new HashMap<Key, String>();
230 String link = e.getChildText("type") + ";" + e.getChildText("text");
231 osm.keys.put(Key.get("link"), link);
232 }
233 }
234}
Note: See TracBrowser for help on using the repository browser.