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