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

Last change on this file since 5132 was 4734, checked in by Don-vip, 12 years ago

fix #7194 - Reworking of osmChange downloads (Fail to update a way loaded from osmChange that have been deleted after)

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