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

Revision 4734, 10.0 KB checked in by Don-vip, 5 months ago (diff)

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
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.