Changeset 7474 in josm for trunk


Ignore:
Timestamp:
2014-08-31T11:50:10+02:00 (10 years ago)
Author:
Don-vip
Message:

fix #10445 - Allow NoteReader to automatically determine XML style being parsed (patch by ToeBee)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/NoteReader.java

    r7451 r7474  
    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 {
     
    3234    private InputSource inputSource;
    3335    private List<Note> parsedNotes;
    34     private NoteParseMode parseMode;
    3536
    3637    /**
     
    3940     * needs to know which one it is handling.
    4041     */
    41     public enum NoteParseMode {API, DUMP}
    42 
    43     /**
    44      * Parser for the notes dump file format.
    45      * It is completely different from the API XML format.
    46      */
    47     private class DumpParser extends DefaultHandler {
     42    private enum NoteParseMode {API, DUMP}
     43
     44    /**
     45     * SAX handler to read note information from its XML representation.
     46     * Reads both API style and planet dump style formats.
     47     */
     48    private class Parser extends DefaultHandler {
     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);
     52
     53        private NoteParseMode parseMode;
    4854        private StringBuffer buffer = new StringBuffer();
    49         private final SimpleDateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.ENGLISH);
    50 
    51         private List<Note> notes = new ArrayList<Note>(100000);
    5255        private Note thisNote;
    53 
     56        private long commentUid;
     57        private String commentUsername;
     58        private Action noteAction;
    5459        private Date commentCreateDate;
    55         private String commentUsername;
    56         private long commentUid;
    57         private Action noteAction;
    5860        private Boolean commentIsNew;
     61        private List<Note> notes;
     62        String commentText;
    5963
    6064        @Override
     
    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);
     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
    8594            switch(qName) {
    8695            case "note":
     
    120129
    121130        @Override
     131        public void endElement(String namespaceURI, String localName, String qName) {
     132            if("note".equals(qName)) {
     133                notes.add(thisNote);
     134            }
     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            }
     153
     154            //the rest only applies to API mode
     155            switch (qName) {
     156            case "id":
     157                thisNote.setId(Long.parseLong(buffer.toString()));
     158                break;
     159            case "status":
     160                thisNote.setState(Note.State.valueOf(buffer.toString()));
     161                break;
     162            case "date_created":
     163                thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, buffer.toString()));
     164                break;
     165            case "date":
     166                commentCreateDate = parseDate(NOTE_DATE_FORMAT, buffer.toString());
     167                break;
     168            case "user":
     169                commentUsername = buffer.toString();
     170                break;
     171            case "uid":
     172                commentUid = Long.parseLong(buffer.toString());
     173                break;
     174            case "text":
     175                commentText = buffer.toString();
     176                buffer.setLength(0);
     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
     182            case "comment":
     183                break;
     184            }
     185        }
     186
     187        @Override
    122188        public void endDocument() throws SAXException  {
    123189            Main.info("parsed notes: " + notes.size());
    124190            parsedNotes = notes;
    125191        }
    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);
    150             }
    151         }
    152 
    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) {
    160             switch (qName) {
    161             case "id":
    162                 thisNote.setId(Long.parseLong(accumulator.toString()));
    163                 break;
    164             case "status":
    165                 thisNote.setState(Note.State.valueOf(accumulator.toString()));
    166                 break;
    167             case "date_created":
    168                 thisNote.setCreatedAt(parseDate(NOTE_DATE_FORMAT, accumulator.toString()));
    169                 break;
    170             case "note":
    171                 notes.add(thisNote);
    172                 break;
    173             case "date":
    174                 commentCreateDate = parseDate(NOTE_DATE_FORMAT, accumulator.toString());
    175                 break;
    176             case "user":
    177                 commentUsername = accumulator.toString();
    178                 break;
    179             case "uid":
    180                 commentUid = Long.parseLong(accumulator.toString());
    181                 break;
    182             case "text":
    183                 commentText = accumulator.toString();
    184                 break;
    185             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                 break;
    193             case "action":
    194                 commentAction = Action.valueOf(accumulator.toString());
    195                 break;
    196             }
    197         }
    198 
    199         @Override
    200         public void endDocument() throws SAXException  {
    201             Main.info("parsed notes: " + notes.size());
    202             parsedNotes = notes;
    203         }
    204     }
    205 
    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;
     192
     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    }
     
    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
     
    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();
Note: See TracChangeset for help on using the changeset viewer.