Ticket #10445: auto_xml_type.patch

File auto_xml_type.patch, 11.2 KB (added by ToeBee, 10 years ago)
  • src/org/openstreetmap/josm/io/NoteReader.java

     
    2525import org.xml.sax.helpers.DefaultHandler;
    2626
    2727/**
    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.
    2931 */
    3032public class NoteReader {
    3133
    3234    private InputSource inputSource;
    3335    private List<Note> parsedNotes;
    34     private NoteParseMode parseMode;
    3536
    3637    /**
    3738     * Notes can be represented in two XML formats. One is returned by the API
    3839     * while the other is used to generate the notes dump file. The parser
    3940     * needs to know which one it is handling.
    4041     */
    41     public enum NoteParseMode {API, DUMP}
     42    private enum NoteParseMode {API, DUMP}
    4243
    4344    /**
    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.
    4647     */
    47     private class DumpParser extends DefaultHandler {
    48         private StringBuffer buffer = new StringBuffer();
     48    private class Parser extends DefaultHandler {
     49
    4950        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);
    5052
    51         private List<Note> notes = new ArrayList<Note>(100000);
     53        private NoteParseMode parseMode;
     54        private StringBuffer buffer = new StringBuffer();
    5255        private Note thisNote;
    53 
    54         private Date commentCreateDate;
     56        private long commentUid;
    5557        private String commentUsername;
    56         private long commentUid;
    5758        private Action noteAction;
     59        private Date commentCreateDate;
    5860        private Boolean commentIsNew;
     61        private List<Note> notes;
     62        String commentText;
    5963
    6064        @Override
    6165        public void characters(char[] ch, int start, int length) throws SAXException {
     
    6367        }
    6468
    6569        @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         @Override
    8370        public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
    8471            buffer.setLength(0);
    8572            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) {
    8695            case "note":
    8796                double lat = Double.parseDouble(attrs.getValue("lat"));
    8897                double lon = Double.parseDouble(attrs.getValue("lon"));
     
    119128        }
    120129
    121130        @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);
    150134            }
    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            }
    152153
    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
    160155            switch (qName) {
    161156            case "id":
    162                 thisNote.setId(Long.parseLong(accumulator.toString()));
     157                thisNote.setId(Long.parseLong(buffer.toString()));
    163158                break;
    164159            case "status":
    165                 thisNote.setState(Note.State.valueOf(accumulator.toString()));
     160                thisNote.setState(Note.State.valueOf(buffer.toString()));
    166161                break;
    167162            case "date_created":
    168                 thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, accumulator.toString()));
     163                thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, buffer.toString()));
    169164                break;
    170             case "note":
    171                 notes.add(thisNote);
    172                 break;
    173165            case "date":
    174                 commentCreateDate = parseDate(NOTE_DATE_FORMAT, accumulator.toString());
     166                commentCreateDate = parseDate(NOTE_DATE_FORMAT, buffer.toString());
    175167                break;
    176168            case "user":
    177                 commentUsername = accumulator.toString();
     169                commentUsername = buffer.toString();
    178170                break;
    179171            case "uid":
    180                 commentUid = Long.parseLong(accumulator.toString());
     172                commentUid = Long.parseLong(buffer.toString());
    181173                break;
    182174            case "text":
    183                 commentText = accumulator.toString();
     175                commentText = buffer.toString();
     176                buffer.setLength(0);
    184177                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
    185182            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;
    192183                break;
    193             case "action":
    194                 commentAction = Action.valueOf(accumulator.toString());
    195                 break;
    196184            }
    197185        }
    198186
     
    201189            Main.info("parsed notes: " + notes.size());
    202190            parsedNotes = notes;
    203191        }
    204     }
    205192
    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            }
    219207        }
    220208    }
    221209
    222210    /**
    223211     * Initializes the reader with a given InputStream
    224212     * @param source - InputStream containing Notes XML
    225      * @param parseMode - Indicate if we are parsing API or dump file style XML
    226213     * @throws IOException
    227214     */
    228     public NoteReader(InputStream source, NoteParseMode parseMode) throws IOException {
     215    public NoteReader(InputStream source) throws IOException {
    229216        this.inputSource = new InputSource(source);
    230         this.parseMode = parseMode;
    231217    }
    232218
    233219    /**
     
    238224     * @throws IOException
    239225     */
    240226    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();
    247228        try {
    248229            SAXParserFactory factory = SAXParserFactory.newInstance();
    249230            factory.setNamespaceAware(true);