Ticket #10445: auto_xml_type.patch
File auto_xml_type.patch, 11.2 KB (added by , 10 years ago) |
---|
-
src/org/openstreetmap/josm/io/NoteReader.java
25 25 import org.xml.sax.helpers.DefaultHandler; 26 26 27 27 /** 28 * Class to read Note objects from their XML representation 28 * Class to read Note objects from their XML representation. It can take 29 * either API style XML which starts with an "osm" tag or a planet dump 30 * style XML which starts with an "osm-notes" tag. 29 31 */ 30 32 public class NoteReader { 31 33 32 34 private InputSource inputSource; 33 35 private List<Note> parsedNotes; 34 private NoteParseMode parseMode;35 36 36 37 /** 37 38 * Notes can be represented in two XML formats. One is returned by the API 38 39 * while the other is used to generate the notes dump file. The parser 39 40 * needs to know which one it is handling. 40 41 */ 41 p ublicenum NoteParseMode {API, DUMP}42 private enum NoteParseMode {API, DUMP} 42 43 43 44 /** 44 * Parser for the notes dump file format.45 * It is completely different from the API XML format.45 * SAX handler to read note information from its XML representation. 46 * Reads both API style and planet dump style formats. 46 47 */ 47 private class DumpParser extends DefaultHandler {48 private StringBuffer buffer = new StringBuffer(); 48 private class Parser extends DefaultHandler { 49 49 50 private final SimpleDateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.ENGLISH); 51 private final SimpleDateFormat NOTE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.ENGLISH); 50 52 51 private List<Note> notes = new ArrayList<Note>(100000); 53 private NoteParseMode parseMode; 54 private StringBuffer buffer = new StringBuffer(); 52 55 private Note thisNote; 53 54 private Date commentCreateDate; 56 private long commentUid; 55 57 private String commentUsername; 56 private long commentUid;57 58 private Action noteAction; 59 private Date commentCreateDate; 58 60 private Boolean commentIsNew; 61 private List<Note> notes; 62 String commentText; 59 63 60 64 @Override 61 65 public void characters(char[] ch, int start, int length) throws SAXException { … … 63 67 } 64 68 65 69 @Override 66 public void endElement(String uri, String localName, String qName) throws SAXException {67 switch (qName) {68 case "note":69 notes.add(thisNote);70 break;71 case "comment":72 User commentUser = User.createOsmUser(commentUid, commentUsername);73 thisNote.addComment(new NoteComment(commentCreateDate, commentUser, buffer.toString(), noteAction, commentIsNew));74 commentUid = 0;75 commentUsername = null;76 commentCreateDate = null;77 commentIsNew = null;78 break;79 }80 }81 82 @Override83 70 public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { 84 71 buffer.setLength(0); 85 72 switch(qName) { 73 case "osm": 74 parseMode = NoteParseMode.API; 75 notes = new ArrayList<Note>(100); 76 return; 77 case "osm-notes": 78 parseMode = NoteParseMode.DUMP; 79 notes = new ArrayList<Note>(10000); 80 return; 81 } 82 83 if (parseMode == NoteParseMode.API) { 84 if("note".equals(qName)) { 85 double lat = Double.parseDouble(attrs.getValue("lat")); 86 double lon = Double.parseDouble(attrs.getValue("lon")); 87 LatLon noteLatLon = new LatLon(lat, lon); 88 thisNote = new Note(noteLatLon); 89 } 90 return; 91 } 92 93 //The rest only applies for dump mode 94 switch(qName) { 86 95 case "note": 87 96 double lat = Double.parseDouble(attrs.getValue("lat")); 88 97 double lon = Double.parseDouble(attrs.getValue("lon")); … … 119 128 } 120 129 121 130 @Override 122 public void endDocument() throws SAXException { 123 Main.info("parsed notes: " + notes.size()); 124 parsedNotes = notes; 125 } 126 } 127 128 private class ApiParser extends DefaultHandler { 129 130 private StringBuffer accumulator = new StringBuffer(); 131 private final SimpleDateFormat NOTE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.ENGLISH); 132 133 private List<Note> notes = new ArrayList<Note>(); 134 private Note thisNote; 135 136 private Date commentCreateDate; 137 private String commentUsername; 138 private long commentUid; 139 private String commentText; 140 private Action commentAction; 141 142 @Override 143 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 144 accumulator.setLength(0); 145 if ("note".equals(qName)) { 146 double lat = Double.parseDouble(atts.getValue("lat")); 147 double lon = Double.parseDouble(atts.getValue("lon")); 148 LatLon noteLatLon = new LatLon(lat, lon); 149 thisNote = new Note(noteLatLon); 131 public void endElement(String namespaceURI, String localName, String qName) { 132 if("note".equals(qName)) { 133 notes.add(thisNote); 150 134 } 151 } 135 if("comment".equals(qName)) { 136 User commentUser = User.createOsmUser(commentUid, commentUsername); 137 if(parseMode == NoteParseMode.API) { 138 commentIsNew = false; 139 } 140 if(parseMode == NoteParseMode.DUMP) { 141 commentText = buffer.toString(); 142 } 143 thisNote.addComment(new NoteComment(commentCreateDate, commentUser, commentText, noteAction, commentIsNew)); 144 commentUid = 0; 145 commentUsername = null; 146 commentCreateDate = null; 147 commentIsNew = null; 148 commentText = null; 149 } 150 if(parseMode == NoteParseMode.DUMP) { 151 return; 152 } 152 153 153 @Override 154 public void characters(char[] ch, int start, int length) { 155 accumulator.append(ch, start, length); 156 } 157 158 @Override 159 public void endElement(String namespaceURI, String localName, String qName) { 154 //the rest only applies to API mode 160 155 switch (qName) { 161 156 case "id": 162 thisNote.setId(Long.parseLong( accumulator.toString()));157 thisNote.setId(Long.parseLong(buffer.toString())); 163 158 break; 164 159 case "status": 165 thisNote.setState(Note.State.valueOf( accumulator.toString()));160 thisNote.setState(Note.State.valueOf(buffer.toString())); 166 161 break; 167 162 case "date_created": 168 thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, accumulator.toString()));163 thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, buffer.toString())); 169 164 break; 170 case "note":171 notes.add(thisNote);172 break;173 165 case "date": 174 commentCreateDate = parseDate(NOTE_DATE_FORMAT, accumulator.toString());166 commentCreateDate = parseDate(NOTE_DATE_FORMAT, buffer.toString()); 175 167 break; 176 168 case "user": 177 commentUsername = accumulator.toString();169 commentUsername = buffer.toString(); 178 170 break; 179 171 case "uid": 180 commentUid = Long.parseLong( accumulator.toString());172 commentUid = Long.parseLong(buffer.toString()); 181 173 break; 182 174 case "text": 183 commentText = accumulator.toString(); 175 commentText = buffer.toString(); 176 buffer.setLength(0); 184 177 break; 178 case "action": 179 noteAction = Action.valueOf(buffer.toString()); 180 break; 181 case "note": //nothing to do for comment or note, already handled above 185 182 case "comment": 186 User commentUser = User.createOsmUser(commentUid, commentUsername);187 thisNote.addComment(new NoteComment(commentCreateDate, commentUser, commentText, commentAction, false));188 commentUid = 0;189 commentUsername = null;190 commentCreateDate = null;191 commentText = null;192 183 break; 193 case "action":194 commentAction = Action.valueOf(accumulator.toString());195 break;196 184 } 197 185 } 198 186 … … 201 189 Main.info("parsed notes: " + notes.size()); 202 190 parsedNotes = notes; 203 191 } 204 }205 192 206 /** 207 * Convenience method to handle the date parsing try/catch. Will return null if 208 * there is a parsing exception. This means whatever generated this XML is in error 209 * and there isn't anything we can do about it. 210 * @param dateStr - String to parse 211 * @return Parsed date, null if parsing fails 212 */ 213 private Date parseDate(SimpleDateFormat sdf, String dateStr) { 214 try { 215 return sdf.parse(dateStr); 216 } catch(ParseException e) { 217 Main.error("error parsing date in note parser"); 218 return null; 193 /** 194 * Convenience method to handle the date parsing try/catch. Will return null if 195 * there is a parsing exception. This means whatever generated this XML is in error 196 * and there isn't anything we can do about it. 197 * @param dateStr - String to parse 198 * @return Parsed date, null if parsing fails 199 */ 200 private Date parseDate(SimpleDateFormat sdf, String dateStr) { 201 try { 202 return sdf.parse(dateStr); 203 } catch(ParseException e) { 204 Main.error("error parsing date in note parser"); 205 return null; 206 } 219 207 } 220 208 } 221 209 222 210 /** 223 211 * Initializes the reader with a given InputStream 224 212 * @param source - InputStream containing Notes XML 225 * @param parseMode - Indicate if we are parsing API or dump file style XML226 213 * @throws IOException 227 214 */ 228 public NoteReader(InputStream source , NoteParseMode parseMode) throws IOException {215 public NoteReader(InputStream source) throws IOException { 229 216 this.inputSource = new InputSource(source); 230 this.parseMode = parseMode;231 217 } 232 218 233 219 /** … … 238 224 * @throws IOException 239 225 */ 240 226 public List<Note> parse() throws SAXException, IOException { 241 DefaultHandler parser; 242 if(parseMode == NoteParseMode.DUMP) { 243 parser = new DumpParser(); 244 } else { 245 parser = new ApiParser(); 246 } 227 DefaultHandler parser = new Parser(); 247 228 try { 248 229 SAXParserFactory factory = SAXParserFactory.newInstance(); 249 230 factory.setNamespaceAware(true);