[27] | 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.GeoPoint;
|
---|
| 12 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
| 13 | import org.openstreetmap.josm.data.osm.LineSegment;
|
---|
| 14 | import org.openstreetmap.josm.data.osm.Node;
|
---|
| 15 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
[64] | 16 | import org.openstreetmap.josm.data.osm.Way;
|
---|
[33] | 17 | import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
|
---|
[27] | 18 |
|
---|
| 19 | /**
|
---|
[58] | 20 | * Reads the old osm 0.2 format.
|
---|
[27] | 21 | *
|
---|
| 22 | * @author imi
|
---|
| 23 | */
|
---|
[58] | 24 | public class OsmReaderOld {
|
---|
[27] | 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 | */
|
---|
[58] | 35 | public OsmReaderOld(Reader source) {
|
---|
[27] | 36 | this.source = source;
|
---|
| 37 | }
|
---|
[58] | 38 |
|
---|
[27] | 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);
|
---|
[29] | 47 | } catch (NumberFormatException nfe) {
|
---|
| 48 | throw new JDOMException("NumberFormatException. Probably a tag is missing.", nfe);
|
---|
[27] | 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 {
|
---|
[66] | 64 | Node data = new Node(new GeoPoint(
|
---|
[44] | 65 | Double.parseDouble(e.getAttributeValue("lat")),
|
---|
[66] | 66 | Double.parseDouble(e.getAttributeValue("lon"))));
|
---|
[27] | 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 | /**
|
---|
[33] | 76 | * Parse any (yet unknown) object and return it.
|
---|
[27] | 77 | */
|
---|
[33] | 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 parseLineSegment(e, data);
|
---|
[64] | 83 | else if (e.getName().equals("way"))
|
---|
| 84 | return parseWay(e, data);
|
---|
[33] | 85 | else if (e.getName().equals("property")) {
|
---|
| 86 | parseProperty(e, data);
|
---|
| 87 | return null;
|
---|
[27] | 88 | }
|
---|
[33] | 89 | throw new JDOMException("unknown tag: "+e.getName());
|
---|
[27] | 90 | }
|
---|
[33] | 91 |
|
---|
[27] | 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();
|
---|
[33] | 100 | AddVisitor visitor = new AddVisitor(data);
|
---|
[27] | 101 | for (Object o : e.getChildren()) {
|
---|
| 102 | Element child = (Element)o;
|
---|
[53] | 103 | OsmPrimitive osm = parseObject(child, data);
|
---|
| 104 | if (osm != null)
|
---|
| 105 | osm.visit(visitor);
|
---|
[27] | 106 | }
|
---|
[39] | 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;
|
---|
[27] | 112 |
|
---|
| 113 | return data;
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | /**
|
---|
| 117 | * Parse and return an line segment. The node information of the "from" and
|
---|
| 118 | * "to" attributes must already be in the dataset.
|
---|
| 119 | * @param e The line segment element to parse.
|
---|
| 120 | * @param data The dataset to obtain the node information from.
|
---|
| 121 | * @return The parsed line segment.
|
---|
| 122 | * @throws JDOMException In case of parsing errors.
|
---|
| 123 | */
|
---|
| 124 | private LineSegment parseLineSegment(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 | LineSegment ls = new LineSegment(start, end);
|
---|
| 138 | parseCommon(ls, e);
|
---|
| 139 | return ls;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | /**
|
---|
[64] | 143 | * Parse and read a way from the element.
|
---|
[27] | 144 | *
|
---|
[64] | 145 | * @param e The element that contain the way.
|
---|
[27] | 146 | * @param data The DataSet to get segment information from.
|
---|
[64] | 147 | * @return The parsed way.
|
---|
[27] | 148 | * @throws JDOMException In case of a parsing error.
|
---|
| 149 | */
|
---|
[64] | 150 | private Way parseWay(Element e, DataSet data) throws JDOMException {
|
---|
| 151 | Way way = new Way();
|
---|
| 152 | parseCommon(way, e);
|
---|
[27] | 153 | for (Object o : e.getChildren("segment")) {
|
---|
| 154 | Element child = (Element)o;
|
---|
| 155 | long id = Long.parseLong(child.getAttributeValue("uid"));
|
---|
[30] | 156 | LineSegment ls = findLineSegment(data.lineSegments, id);
|
---|
[64] | 157 | way.segments.add(ls);
|
---|
[27] | 158 | }
|
---|
[64] | 159 | return way;
|
---|
[27] | 160 | }
|
---|
| 161 |
|
---|
| 162 | /**
|
---|
[33] | 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()) {
|
---|
[45] | 177 | String next = st.nextToken();
|
---|
| 178 | if (next.trim().equals(""))
|
---|
| 179 | continue;
|
---|
| 180 | int equalPos = next.indexOf('=');
|
---|
| 181 | if (equalPos == -1)
|
---|
[66] | 182 | data.put(next, "");
|
---|
[33] | 183 | else {
|
---|
[45] | 184 | String keyStr = next.substring(0, equalPos);
|
---|
[66] | 185 | data.put(keyStr, next.substring(equalPos+1));
|
---|
[33] | 186 | }
|
---|
| 187 | }
|
---|
| 188 | }
|
---|
[53] | 189 |
|
---|
| 190 | String action = e.getAttributeValue("action");
|
---|
| 191 | if ("delete".equals(action))
|
---|
| 192 | data.setDeleted(true);
|
---|
| 193 | else if ("modify".equals(action))
|
---|
| 194 | data.modified = data.modifiedProperties = true;
|
---|
| 195 | else if ("modify/property".equals(action))
|
---|
| 196 | data.modifiedProperties = true;
|
---|
| 197 | else if ("modify/object".equals(action))
|
---|
| 198 | data.modified = true;
|
---|
[33] | 199 | }
|
---|
| 200 |
|
---|
| 201 | /**
|
---|
| 202 | * Parse a property tag and assign the property to a previous found object.
|
---|
| 203 | */
|
---|
| 204 | private void parseProperty(Element e, DataSet data) throws JDOMException {
|
---|
| 205 | long id = Long.parseLong(e.getAttributeValue("uid"));
|
---|
| 206 | OsmPrimitive osm = findObject(data, id);
|
---|
[64] | 207 | String key = e.getAttributeValue("key");
|
---|
[35] | 208 | String value = e.getAttributeValue("value");
|
---|
[66] | 209 | if (value != null)
|
---|
| 210 | osm.put(key, value);
|
---|
[33] | 211 | }
|
---|
| 212 |
|
---|
| 213 | /**
|
---|
| 214 | * Search for an object in the dataset by comparing the id.
|
---|
| 215 | */
|
---|
| 216 | private OsmPrimitive findObject(DataSet data, long id) throws JDOMException {
|
---|
| 217 | for (OsmPrimitive osm : data.nodes)
|
---|
| 218 | if (osm.id == id)
|
---|
| 219 | return osm;
|
---|
| 220 | for (OsmPrimitive osm : data.lineSegments)
|
---|
| 221 | if (osm.id == id)
|
---|
| 222 | return osm;
|
---|
[64] | 223 | for (OsmPrimitive osm : data.waies)
|
---|
[33] | 224 | if (osm.id == id)
|
---|
| 225 | return osm;
|
---|
| 226 | throw new JDOMException("Unknown object reference: "+id);
|
---|
| 227 | }
|
---|
| 228 |
|
---|
| 229 | /**
|
---|
[27] | 230 | * Search for a segment in a collection by comparing the id.
|
---|
| 231 | */
|
---|
[32] | 232 | private LineSegment findLineSegment(Collection<LineSegment> segments, long id) throws JDOMException {
|
---|
[27] | 233 | for (LineSegment ls : segments)
|
---|
| 234 | if (ls.id == id)
|
---|
| 235 | return ls;
|
---|
[32] | 236 | throw new JDOMException("Unknown line segment reference: "+id);
|
---|
[27] | 237 | }
|
---|
| 238 | }
|
---|