source: josm/trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java@ 4701

Last change on this file since 4701 was 4602, checked in by bastiK, 12 years ago

upgrade historic users to real users, so their CT status can be shown in the history panel

  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.InputStreamReader;
9import java.util.Date;
10
11import javax.xml.parsers.ParserConfigurationException;
12import javax.xml.parsers.SAXParserFactory;
13
14import org.openstreetmap.josm.data.coor.LatLon;
15import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
16import org.openstreetmap.josm.data.osm.User;
17import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
18import org.openstreetmap.josm.data.osm.history.HistoryNode;
19import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
20import org.openstreetmap.josm.data.osm.history.HistoryRelation;
21import org.openstreetmap.josm.data.osm.history.HistoryWay;
22import org.openstreetmap.josm.gui.progress.ProgressMonitor;
23import org.openstreetmap.josm.tools.DateUtils;
24import org.xml.sax.Attributes;
25import org.xml.sax.InputSource;
26import org.xml.sax.Locator;
27import org.xml.sax.SAXException;
28import org.xml.sax.helpers.DefaultHandler;
29
30/**
31 * Parser for OSM history data.
32 *
33 * It is slightly different from {@see OsmReader} because we don't build an internal graph of
34 * {@see OsmPrimitive}s. We use objects derived from {@see HistoryOsmPrimitive} instead and we
35 * keep the data in a dedicated {@see HistoryDataSet}.
36 *
37 */
38public class OsmHistoryReader {
39
40 private final InputStream in;
41 private final HistoryDataSet data;
42
43 private class Parser extends DefaultHandler {
44
45 /** the current primitive to be read */
46 private HistoryOsmPrimitive current;
47 private Locator locator;
48
49 @Override
50 public void setDocumentLocator(Locator locator) {
51 this.locator = locator;
52 }
53
54 protected String getCurrentPosition() {
55 if (locator == null)
56 return "";
57 return "(" + locator.getLineNumber() + "," + locator.getColumnNumber() + ")";
58 }
59
60 protected void throwException(String message) throws SAXException {
61 throw new SAXException(
62 getCurrentPosition()
63 + message
64 );
65 }
66
67 protected long getMandatoryAttributeLong(Attributes attr, String name) throws SAXException{
68 String v = attr.getValue(name);
69 if (v == null) {
70 throwException(tr("Missing mandatory attribute ''{0}''.", name));
71 }
72 Long l = 0l;
73 try {
74 l = Long.parseLong(v);
75 } catch(NumberFormatException e) {
76 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v));
77 }
78 if (l < 0) {
79 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v));
80 }
81 return l;
82 }
83
84 protected Long getAttributeLong(Attributes attr, String name) throws SAXException {
85 String v = attr.getValue(name);
86 if (v == null)
87 return null;
88 Long l = null;
89 try {
90 l = Long.parseLong(v);
91 } catch(NumberFormatException e) {
92 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v));
93 }
94 if (l < 0) {
95 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v));
96 }
97 return l;
98 }
99
100 protected Double getMandatoryAttributeDouble(Attributes attr, String name) throws SAXException{
101 String v = attr.getValue(name);
102 if (v == null) {
103 throwException(tr("Missing mandatory attribute ''{0}''.", name));
104 }
105 double d = 0.0;
106 try {
107 d = Double.parseDouble(v);
108 } catch(NumberFormatException e) {
109 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type double. Got ''{1}''.", name, v));
110 }
111 return d;
112 }
113
114 protected String getMandatoryAttributeString(Attributes attr, String name) throws SAXException{
115 String v = attr.getValue(name);
116 if (v == null) {
117 throwException(tr("Missing mandatory attribute ''{0}''.", name));
118 }
119 return v;
120 }
121
122 protected boolean getMandatoryAttributeBoolean(Attributes attr, String name) throws SAXException{
123 String v = attr.getValue(name);
124 if (v == null) {
125 throwException(tr("Missing mandatory attribute ''{0}''.", name));
126 }
127 if ("true".equals(v)) return true;
128 if ("false".equals(v)) return false;
129 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type boolean. Got ''{1}''.", name, v));
130 // not reached
131 return false;
132 }
133
134 protected HistoryOsmPrimitive createPrimitive(Attributes atts, OsmPrimitiveType type) throws SAXException {
135 long id = getMandatoryAttributeLong(atts,"id");
136 long version = getMandatoryAttributeLong(atts,"version");
137 long changesetId = getMandatoryAttributeLong(atts,"changeset");
138 boolean visible= getMandatoryAttributeBoolean(atts, "visible");
139 Long uid = getAttributeLong(atts, "uid");
140 String userStr = atts.getValue("user");
141 User user;
142 if (userStr != null) {
143 if (uid != null) {
144 user = User.createOsmUser(uid, userStr);
145 } else {
146 user = User.createLocalUser(userStr);
147 }
148 } else {
149 user = User.getAnonymous();
150 }
151 String v = getMandatoryAttributeString(atts, "timestamp");
152 Date timestamp = DateUtils.fromString(v);
153 HistoryOsmPrimitive primitive = null;
154 if (type.equals(OsmPrimitiveType.NODE)) {
155 double lat = getMandatoryAttributeDouble(atts, "lat");
156 double lon = getMandatoryAttributeDouble(atts, "lon");
157 primitive = new HistoryNode(
158 id,version,visible,user,changesetId,timestamp, new LatLon(lat,lon)
159 );
160
161 } else if (type.equals(OsmPrimitiveType.WAY)) {
162 primitive = new HistoryWay(
163 id,version,visible,user,changesetId,timestamp
164 );
165 }if (type.equals(OsmPrimitiveType.RELATION)) {
166 primitive = new HistoryRelation(
167 id,version,visible,user,changesetId,timestamp
168 );
169 }
170 return primitive;
171 }
172
173 protected void startNode(Attributes atts) throws SAXException {
174 current= createPrimitive(atts, OsmPrimitiveType.NODE);
175 }
176
177 protected void startWay(Attributes atts) throws SAXException {
178 current= createPrimitive(atts, OsmPrimitiveType.WAY);
179 }
180 protected void startRelation(Attributes atts) throws SAXException {
181 current= createPrimitive(atts, OsmPrimitiveType.RELATION);
182 }
183
184 protected void handleTag(Attributes atts) throws SAXException {
185 String key= getMandatoryAttributeString(atts, "k");
186 String value= getMandatoryAttributeString(atts, "v");
187 current.put(key,value);
188 }
189
190 protected void handleNodeReference(Attributes atts) throws SAXException {
191 long ref = getMandatoryAttributeLong(atts, "ref");
192 ((HistoryWay)current).addNode(ref);
193 }
194
195 protected void handleMember(Attributes atts) throws SAXException {
196 long ref = getMandatoryAttributeLong(atts, "ref");
197 String v = getMandatoryAttributeString(atts, "type");
198 OsmPrimitiveType type = null;
199 try {
200 type = OsmPrimitiveType.fromApiTypeName(v);
201 } catch(IllegalArgumentException e) {
202 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type OsmPrimitiveType. Got ''{1}''.", "type", v));
203 }
204 String role = getMandatoryAttributeString(atts, "role");
205 org.openstreetmap.josm.data.osm.history.RelationMember member = new org.openstreetmap.josm.data.osm.history.RelationMember(role, type,ref);
206 ((HistoryRelation)current).addMember(member);
207 }
208
209 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
210 if (qName.equals("node")) {
211 startNode(atts);
212 } else if (qName.equals("way")) {
213 startWay(atts);
214 } else if (qName.equals("relation")) {
215 startRelation(atts);
216 } else if (qName.equals("tag")) {
217 handleTag(atts);
218 } else if (qName.equals("nd")) {
219 handleNodeReference(atts);
220 } else if (qName.equals("member")) {
221 handleMember(atts);
222 }
223 }
224
225 @Override
226 public void endElement(String uri, String localName, String qName) throws SAXException {
227 if (qName.equals("node")
228 || qName.equals("way")
229 || qName.equals("relation")) {
230 data.put(current);
231 }
232 }
233 }
234
235 public OsmHistoryReader(InputStream source) {
236 this.in = source;
237 this.data = new HistoryDataSet();
238 }
239
240 public HistoryDataSet parse(ProgressMonitor progressMonitor) throws SAXException, IOException {
241 InputSource inputSource = new InputSource(new InputStreamReader(in, "UTF-8"));
242 progressMonitor.beginTask(tr("Parsing OSM history data ..."));
243 try {
244 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser());
245 } catch (ParserConfigurationException e1) {
246 e1.printStackTrace(); // broken SAXException chaining
247 throw new SAXException(e1);
248 } finally {
249 progressMonitor.finishTask();
250 }
251 return data;
252 }
253}
Note: See TracBrowser for help on using the repository browser.