001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.Date; 007 008import org.openstreetmap.josm.data.coor.LatLon; 009import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 010import org.openstreetmap.josm.data.osm.RelationMemberData; 011import org.openstreetmap.josm.data.osm.User; 012import org.openstreetmap.josm.data.osm.history.HistoryNode; 013import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 014import org.openstreetmap.josm.data.osm.history.HistoryRelation; 015import org.openstreetmap.josm.data.osm.history.HistoryWay; 016import org.openstreetmap.josm.tools.date.DateUtils; 017import org.xml.sax.Attributes; 018import org.xml.sax.Locator; 019import org.xml.sax.SAXException; 020import org.xml.sax.helpers.DefaultHandler; 021 022/** 023 * Base class of {@link OsmChangesetContentParser} and {@link OsmHistoryReader} internal parsers. 024 * @since 6201 025 */ 026public abstract class AbstractParser extends DefaultHandler { 027 028 /** the current primitive to be read */ 029 protected HistoryOsmPrimitive currentPrimitive; 030 protected Locator locator; 031 /** if true, replace user information in input by anonymous user */ 032 protected boolean useAnonymousUser; 033 034 @Override 035 public void setDocumentLocator(Locator locator) { 036 this.locator = locator; 037 } 038 039 protected abstract void throwException(String message) throws SAXException; 040 041 protected abstract void throwException(String message, Exception e) throws SAXException; 042 043 protected final long getMandatoryAttributeLong(Attributes attr, String name) throws SAXException { 044 String v = attr.getValue(name); 045 if (v == null) { 046 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 047 } 048 long l = 0L; 049 try { 050 l = Long.parseLong(v); 051 } catch (NumberFormatException e) { 052 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e); 053 } 054 if (l < 0) { 055 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v)); 056 } 057 return l; 058 } 059 060 protected final Long getAttributeLong(Attributes attr, String name) throws SAXException { 061 String v = attr.getValue(name); 062 if (v == null) 063 return null; 064 Long l = 0L; 065 try { 066 l = Long.valueOf(v); 067 } catch (NumberFormatException e) { 068 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e); 069 } 070 if (l < 0) { 071 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v)); 072 } 073 return l; 074 } 075 076 protected final Double getAttributeDouble(Attributes attr, String name) throws SAXException { 077 String v = attr.getValue(name); 078 if (v == null) { 079 return null; 080 } 081 double d = 0.0; 082 try { 083 d = Double.parseDouble(v); 084 } catch (NumberFormatException e) { 085 throwException(tr("Illegal value for attribute ''{0}'' of type double. Got ''{1}''.", name, v), e); 086 } 087 return d; 088 } 089 090 protected final String getMandatoryAttributeString(Attributes attr, String name) throws SAXException { 091 String v = attr.getValue(name); 092 if (v == null) { 093 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 094 } 095 return v; 096 } 097 098 protected boolean getMandatoryAttributeBoolean(Attributes attr, String name) throws SAXException { 099 String v = attr.getValue(name); 100 if (v == null) { 101 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 102 } 103 if ("true".equals(v)) return true; 104 if ("false".equals(v)) return false; 105 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type boolean. Got ''{1}''.", name, v)); 106 return false; // not reached 107 } 108 109 protected final HistoryOsmPrimitive createPrimitive(Attributes atts, OsmPrimitiveType type) throws SAXException { 110 long id = getMandatoryAttributeLong(atts, "id"); 111 long version = getMandatoryAttributeLong(atts, "version"); 112 Long changeset = getAttributeLong(atts, "changeset"); 113 long changesetId = changeset != null ? changeset : 0L; 114 boolean visible = getMandatoryAttributeBoolean(atts, "visible"); 115 116 User user = null; 117 if (!useAnonymousUser) { 118 Long uid = getAttributeLong(atts, "uid"); 119 String userStr = atts.getValue("user"); 120 if (userStr != null) { 121 if (uid != null) { 122 user = User.createOsmUser(uid, userStr); 123 user.setPreferredName(userStr); 124 } else { 125 user = User.createLocalUser(userStr); 126 } 127 } 128 } 129 if (user == null) { 130 user = User.getAnonymous(); 131 } 132 133 String v = getMandatoryAttributeString(atts, "timestamp"); 134 Date timestamp = DateUtils.fromString(v); 135 HistoryOsmPrimitive primitive = null; 136 if (type == OsmPrimitiveType.NODE) { 137 Double lat = getAttributeDouble(atts, "lat"); 138 Double lon = getAttributeDouble(atts, "lon"); 139 LatLon coor = (lat != null && lon != null) ? new LatLon(lat, lon) : null; 140 primitive = new HistoryNode(id, version, visible, user, changesetId, timestamp, coor, changeset != null); 141 142 } else if (type == OsmPrimitiveType.WAY) { 143 primitive = new HistoryWay(id, version, visible, user, changesetId, timestamp, changeset != null); 144 } else if (type == OsmPrimitiveType.RELATION) { 145 primitive = new HistoryRelation(id, version, visible, user, changesetId, timestamp, changeset != null); 146 } 147 return primitive; 148 } 149 150 protected final void startNode(Attributes atts) throws SAXException { 151 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.NODE); 152 } 153 154 protected final void startWay(Attributes atts) throws SAXException { 155 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.WAY); 156 } 157 158 protected final void startRelation(Attributes atts) throws SAXException { 159 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.RELATION); 160 } 161 162 protected final void handleTag(Attributes atts) throws SAXException { 163 String key = getMandatoryAttributeString(atts, "k"); 164 String value = getMandatoryAttributeString(atts, "v"); 165 currentPrimitive.put(key, value); 166 } 167 168 protected final void handleNodeReference(Attributes atts) throws SAXException { 169 long ref = getMandatoryAttributeLong(atts, "ref"); 170 ((HistoryWay) currentPrimitive).addNode(ref); 171 } 172 173 protected void handleMember(Attributes atts) throws SAXException { 174 long ref = getMandatoryAttributeLong(atts, "ref"); 175 String v = getMandatoryAttributeString(atts, "type"); 176 OsmPrimitiveType type = null; 177 try { 178 type = OsmPrimitiveType.fromApiTypeName(v); 179 } catch (IllegalArgumentException e) { 180 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type OsmPrimitiveType. Got ''{1}''.", "type", v), e); 181 } 182 String role = getMandatoryAttributeString(atts, "role"); 183 RelationMemberData member = new RelationMemberData(role, type, ref); 184 ((HistoryRelation) currentPrimitive).addMember(member); 185 } 186 187 protected final boolean doStartElement(String qName, Attributes atts) throws SAXException { 188 switch (qName) { 189 case "node": 190 startNode(atts); 191 return true; 192 case "way": 193 startWay(atts); 194 return true; 195 case "relation": 196 startRelation(atts); 197 return true; 198 case "tag": 199 handleTag(atts); 200 return true; 201 case "nd": 202 handleNodeReference(atts); 203 return true; 204 case "member": 205 handleMember(atts); 206 return true; 207 default: 208 return false; 209 } 210 } 211}