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 changesetId = getMandatoryAttributeLong(atts, "changeset"); 111 boolean visible = getMandatoryAttributeBoolean(atts, "visible"); 112 113 Long uid = getAttributeLong(atts, "uid"); 114 String userStr = atts.getValue("user"); 115 User user; 116 if (userStr != null) { 117 if (uid != null) { 118 user = User.createOsmUser(uid, userStr); 119 } else { 120 user = User.createLocalUser(userStr); 121 } 122 } else { 123 user = User.getAnonymous(); 124 } 125 126 String v = getMandatoryAttributeString(atts, "timestamp"); 127 Date timestamp = DateUtils.fromString(v); 128 HistoryOsmPrimitive primitive = null; 129 if (type.equals(OsmPrimitiveType.NODE)) { 130 Double lat = getAttributeDouble(atts, "lat"); 131 Double lon = getAttributeDouble(atts, "lon"); 132 LatLon coor = (lat != null && lon != null) ? new LatLon(lat, lon) : null; 133 primitive = new HistoryNode(id, version, visible, user, changesetId, timestamp, coor); 134 135 } else if (type.equals(OsmPrimitiveType.WAY)) { 136 primitive = new HistoryWay(id, version, visible, user, changesetId, timestamp); 137 } else if (type.equals(OsmPrimitiveType.RELATION)) { 138 primitive = new HistoryRelation(id, version, visible, user, changesetId, timestamp); 139 } 140 return primitive; 141 } 142 143 protected final void startNode(Attributes atts) throws SAXException { 144 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.NODE); 145 } 146 147 protected final void startWay(Attributes atts) throws SAXException { 148 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.WAY); 149 } 150 151 protected final void startRelation(Attributes atts) throws SAXException { 152 currentPrimitive = createPrimitive(atts, OsmPrimitiveType.RELATION); 153 } 154 155 protected final void handleTag(Attributes atts) throws SAXException { 156 String key = getMandatoryAttributeString(atts, "k"); 157 String value = getMandatoryAttributeString(atts, "v"); 158 currentPrimitive.put(key, value); 159 } 160 161 protected final void handleNodeReference(Attributes atts) throws SAXException { 162 long ref = getMandatoryAttributeLong(atts, "ref"); 163 ((HistoryWay) currentPrimitive).addNode(ref); 164 } 165 166 protected void handleMember(Attributes atts) throws SAXException { 167 long ref = getMandatoryAttributeLong(atts, "ref"); 168 String v = getMandatoryAttributeString(atts, "type"); 169 OsmPrimitiveType type = null; 170 try { 171 type = OsmPrimitiveType.fromApiTypeName(v); 172 } catch (IllegalArgumentException e) { 173 throwException(tr("Illegal value for mandatory attribute ''{0}'' of type OsmPrimitiveType. Got ''{1}''.", "type", v), e); 174 } 175 String role = getMandatoryAttributeString(atts, "role"); 176 RelationMemberData member = new RelationMemberData(role, type, ref); 177 ((HistoryRelation) currentPrimitive).addMember(member); 178 } 179 180 protected final boolean doStartElement(String qName, Attributes atts) throws SAXException { 181 switch (qName) { 182 case "node": 183 startNode(atts); 184 return true; 185 case "way": 186 startWay(atts); 187 return true; 188 case "relation": 189 startRelation(atts); 190 return true; 191 case "tag": 192 handleTag(atts); 193 return true; 194 case "nd": 195 handleNodeReference(atts); 196 return true; 197 case "member": 198 handleMember(atts); 199 return true; 200 default: 201 return false; 202 } 203 } 204}