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 032 @Override 033 public void setDocumentLocator(Locator locator) { 034 this.locator = locator; 035 } 036 037 protected abstract void throwException(String message) throws SAXException; 038 039 protected abstract void throwException(String message, Exception e) throws SAXException; 040 041 protected final long getMandatoryAttributeLong(Attributes attr, String name) throws SAXException { 042 String v = attr.getValue(name); 043 if (v == null) { 044 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 045 } 046 long l = 0L; 047 try { 048 l = Long.parseLong(v); 049 } catch (NumberFormatException e) { 050 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e); 051 } 052 if (l < 0) { 053 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v)); 054 } 055 return l; 056 } 057 058 protected final Long getAttributeLong(Attributes attr, String name) throws SAXException { 059 String v = attr.getValue(name); 060 if (v == null) 061 return null; 062 Long l = 0L; 063 try { 064 l = Long.valueOf(v); 065 } catch (NumberFormatException e) { 066 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long. Got ''{1}''.", name, v), e); 067 } 068 if (l < 0) { 069 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type long (>=0). Got ''{1}''.", name, v)); 070 } 071 return l; 072 } 073 074 protected final Double getAttributeDouble(Attributes attr, String name) throws SAXException { 075 String v = attr.getValue(name); 076 if (v == null) { 077 return null; 078 } 079 double d = 0.0; 080 try { 081 d = Double.parseDouble(v); 082 } catch (NumberFormatException e) { 083 throwException(tr("Illegal value for attribute ''{0}'' of type double. Got ''{1}''.", name, v), e); 084 } 085 return d; 086 } 087 088 protected final String getMandatoryAttributeString(Attributes attr, String name) throws SAXException { 089 String v = attr.getValue(name); 090 if (v == null) { 091 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 092 } 093 return v; 094 } 095 096 protected boolean getMandatoryAttributeBoolean(Attributes attr, String name) throws SAXException { 097 String v = attr.getValue(name); 098 if (v == null) { 099 throwException(tr("Missing mandatory attribute ''{0}''.", name)); 100 } 101 if ("true".equals(v)) return true; 102 if ("false".equals(v)) return false; 103 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type boolean. Got ''{1}''.", name, v)); 104 return false; // not reached 105 } 106 107 protected final HistoryOsmPrimitive createPrimitive(Attributes atts, OsmPrimitiveType type) throws SAXException { 108 long id = getMandatoryAttributeLong(atts, "id"); 109 long version = getMandatoryAttributeLong(atts, "version"); 110 Long changeset = getAttributeLong(atts, "changeset"); 111 long changesetId = changeset != null ? changeset : 0L; 112 boolean visible = getMandatoryAttributeBoolean(atts, "visible"); 113 114 Long uid = getAttributeLong(atts, "uid"); 115 String userStr = atts.getValue("user"); 116 User user; 117 if (userStr != null) { 118 if (uid != null) { 119 user = User.createOsmUser(uid, userStr); 120 user.setPreferredName(userStr); 121 } else { 122 user = User.createLocalUser(userStr); 123 } 124 } else { 125 user = User.getAnonymous(); 126 } 127 128 String v = getMandatoryAttributeString(atts, "timestamp"); 129 Date timestamp = DateUtils.fromString(v); 130 HistoryOsmPrimitive primitive = null; 131 if (type.equals(OsmPrimitiveType.NODE)) { 132 Double lat = getAttributeDouble(atts, "lat"); 133 Double lon = getAttributeDouble(atts, "lon"); 134 LatLon coor = (lat != null && lon != null) ? new LatLon(lat, lon) : null; 135 primitive = new HistoryNode(id, version, visible, user, changesetId, timestamp, coor, changeset != null); 136 137 } else if (type.equals(OsmPrimitiveType.WAY)) { 138 primitive = new HistoryWay(id, version, visible, user, changesetId, timestamp, changeset != null); 139 } else if (type.equals(OsmPrimitiveType.RELATION)) { 140 primitive = new HistoryRelation(id, version, visible, user, changesetId, timestamp, changeset != null); 141 } 142 return primitive; 143 } 144 145 protected final void startNode(Attributes atts) throws SAXException { 146 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.NODE); 147 } 148 149 protected final void startWay(Attributes atts) throws SAXException { 150 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.WAY); 151 } 152 153 protected final void startRelation(Attributes atts) throws SAXException { 154 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.RELATION); 155 } 156 157 protected final void handleTag(Attributes atts) throws SAXException { 158 String key = getMandatoryAttributeString(atts, "k"); 159 String value = getMandatoryAttributeString(atts, "v"); 160 currentPrimitive.put(key, value); 161 } 162 163 protected final void handleNodeReference(Attributes atts) throws SAXException { 164 long ref = getMandatoryAttributeLong(atts, "ref"); 165 ((HistoryWay) currentPrimitive).addNode(ref); 166 } 167 168 protected void handleMember(Attributes atts) throws SAXException { 169 long ref = getMandatoryAttributeLong(atts, "ref"); 170 String v = getMandatoryAttributeString(atts, "type"); 171 OsmPrimitiveType type = null; 172 try { 173 type = OsmPrimitiveType.fromApiTypeName(v); 174 } catch (IllegalArgumentException e) { 175 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type OsmPrimitiveType. Got ''{1}''.", "type", v), e); 176 } 177 String role = getMandatoryAttributeString(atts, "role"); 178 RelationMemberData member = new RelationMemberData(role, type, ref); 179 ((HistoryRelation) currentPrimitive).addMember(member); 180 } 181 182 protected final boolean doStartElement(String qName, Attributes atts) throws SAXException { 183 switch (qName) { 184 case "node": 185 startNode(atts); 186 return true; 187 case "way": 188 startWay(atts); 189 return true; 190 case "relation": 191 startRelation(atts); 192 return true; 193 case "tag": 194 handleTag(atts); 195 return true; 196 case "nd": 197 handleNodeReference(atts); 198 return true; 199 case "member": 200 handleMember(atts); 201 return true; 202 default: 203 return false; 204 } 205 } 206}