source: josm/trunk/src/org/openstreetmap/josm/io/AbstractParser.java

Last change on this file was 18957, checked in by GerdP, 5 months ago

see #20405: simplify code

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.time.Instant;
7import java.util.HashMap;
8import java.util.Map;
9
10import org.openstreetmap.josm.data.coor.LatLon;
11import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
12import org.openstreetmap.josm.data.osm.RelationMemberData;
13import org.openstreetmap.josm.data.osm.User;
14import org.openstreetmap.josm.data.osm.history.HistoryNode;
15import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
16import org.openstreetmap.josm.data.osm.history.HistoryRelation;
17import org.openstreetmap.josm.data.osm.history.HistoryWay;
18import org.openstreetmap.josm.tools.date.DateUtils;
19import org.xml.sax.Attributes;
20import org.xml.sax.Locator;
21import org.xml.sax.SAXException;
22import org.xml.sax.helpers.DefaultHandler;
23
24/**
25 * Base class of {@link OsmChangesetContentParser} and {@link OsmHistoryReader} internal parsers.
26 * @since 6201
27 */
28public abstract class AbstractParser extends DefaultHandler {
29
30 /** the current primitive to be read */
31 protected HistoryOsmPrimitive currentPrimitive;
32 protected Locator locator;
33 /** if true, replace user information in input by anonymous user */
34 protected boolean useAnonymousUser;
35 private Map<RelationMemberData, RelationMemberData> memberCache = new HashMap<>();
36
37 @Override
38 public void setDocumentLocator(Locator locator) {
39 this.locator = locator;
40 }
41
42 protected abstract void throwException(String message) throws SAXException;
43
44 protected abstract void throwException(String message, Exception e) throws SAXException;
45
46 protected final long getMandatoryAttributeLong(Attributes attr, String name) throws SAXException {
47 String v = attr.getValue(name);
48 if (v == null) {
49 throwException(tr("Missing mandatory attribute ''{0}''.", name));
50 }
51 long l = 0L;
52 try {
53 l = Long.parseLong(v);
54 } catch (NumberFormatException e) {
55 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e);
56 }
57 if (l < 0) {
58 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v));
59 }
60 return l;
61 }
62
63 protected final Long getAttributeLong(Attributes attr, String name) throws SAXException {
64 String v = attr.getValue(name);
65 if (v == null)
66 return null;
67 Long l = 0L;
68 try {
69 l = Long.valueOf(v);
70 } catch (NumberFormatException e) {
71 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e);
72 }
73 if (l < 0) {
74 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v));
75 }
76 return l;
77 }
78
79 protected final Double getAttributeDouble(Attributes attr, String name) throws SAXException {
80 String v = attr.getValue(name);
81 if (v == null) {
82 return null;
83 }
84 double d = 0.0;
85 try {
86 d = Double.parseDouble(v);
87 } catch (NumberFormatException e) {
88 throwException(tr("Illegal value for attribute ''{0}'' of type double. Got ''{1}''.", name, v), e);
89 }
90 return d;
91 }
92
93 protected final String getMandatoryAttributeString(Attributes attr, String name) throws SAXException {
94 String v = attr.getValue(name);
95 if (v == null) {
96 throwException(tr("Missing mandatory attribute ''{0}''.", name));
97 }
98 return v;
99 }
100
101 protected boolean getMandatoryAttributeBoolean(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 if ("true".equals(v)) return true;
107 if ("false".equals(v)) return false;
108 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type boolean. Got ''{1}''.", name, v));
109 return false; // not reached
110 }
111
112 protected final HistoryOsmPrimitive createPrimitive(Attributes atts, OsmPrimitiveType type) throws SAXException {
113 long id = getMandatoryAttributeLong(atts, "id");
114 long version = getMandatoryAttributeLong(atts, "version");
115 Long changeset = getAttributeLong(atts, "changeset");
116 long changesetId = changeset != null ? changeset : 0L;
117 boolean visible = getMandatoryAttributeBoolean(atts, "visible");
118
119 User user = null;
120 if (!useAnonymousUser) {
121 Long uid = getAttributeLong(atts, "uid");
122 String userStr = atts.getValue("user");
123 if (userStr != null) {
124 if (uid != null) {
125 user = User.createOsmUser(uid, userStr);
126 user.setPreferredName(userStr);
127 } else {
128 user = User.createLocalUser(userStr);
129 }
130 }
131 }
132 if (user == null) {
133 user = User.getAnonymous();
134 }
135
136 String v = getMandatoryAttributeString(atts, "timestamp");
137 Instant timestamp = DateUtils.parseInstant(v);
138 HistoryOsmPrimitive primitive = null;
139 if (type == OsmPrimitiveType.NODE) {
140 Double lat = getAttributeDouble(atts, "lat");
141 Double lon = getAttributeDouble(atts, "lon");
142 LatLon coor = (lat != null && lon != null) ? new LatLon(lat, lon) : null;
143 primitive = new HistoryNode(id, version, visible, user, changesetId, timestamp, coor, changeset != null);
144
145 } else if (type == OsmPrimitiveType.WAY) {
146 primitive = new HistoryWay(id, version, visible, user, changesetId, timestamp, changeset != null);
147 } else if (type == OsmPrimitiveType.RELATION) {
148 primitive = new HistoryRelation(id, version, visible, user, changesetId, timestamp, changeset != null);
149 }
150 return primitive;
151 }
152
153 protected final void startNode(Attributes atts) throws SAXException {
154 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.NODE);
155 }
156
157 protected final void startWay(Attributes atts) throws SAXException {
158 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.WAY);
159 }
160
161 protected final void startRelation(Attributes atts) throws SAXException {
162 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.RELATION);
163 }
164
165 protected final void handleTag(Attributes atts) throws SAXException {
166 String key = getMandatoryAttributeString(atts, "k");
167 String value = getMandatoryAttributeString(atts, "v");
168 currentPrimitive.put(key, value);
169 }
170
171 protected final void handleNodeReference(Attributes atts) throws SAXException {
172 long ref = getMandatoryAttributeLong(atts, "ref");
173 ((HistoryWay) currentPrimitive).addNode(ref);
174 }
175
176 protected void handleMember(Attributes atts) throws SAXException {
177 long ref = getMandatoryAttributeLong(atts, "ref");
178 String v = getMandatoryAttributeString(atts, "type");
179 OsmPrimitiveType type = null;
180 try {
181 type = OsmPrimitiveType.fromApiTypeName(v);
182 } catch (IllegalArgumentException e) {
183 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type OsmPrimitiveType. Got ''{1}''.", "type", v), e);
184 }
185 String role = getMandatoryAttributeString(atts, "role");
186 RelationMemberData member = new RelationMemberData(role, type, ref);
187 // see #20405: cache equal instances of members
188 RelationMemberData cachedMember = memberCache.computeIfAbsent(member, m -> m);
189 ((HistoryRelation) currentPrimitive).addMember(cachedMember);
190 }
191
192 protected final boolean doStartElement(String qName, Attributes atts) throws SAXException {
193 switch (qName) {
194 case "node":
195 startNode(atts);
196 return true;
197 case "way":
198 startWay(atts);
199 return true;
200 case "relation":
201 startRelation(atts);
202 return true;
203 case "tag":
204 handleTag(atts);
205 return true;
206 case "nd":
207 handleNodeReference(atts);
208 return true;
209 case "member":
210 handleMember(atts);
211 return true;
212 default:
213 return false;
214 }
215 }
216}
Note: See TracBrowser for help on using the repository browser.