001    package org.openstreetmap.josm.io;
002    
003    import static org.openstreetmap.josm.tools.I18n.tr;
004    
005    import java.io.InputStream;
006    import java.util.Arrays;
007    
008    import javax.xml.stream.XMLStreamConstants;
009    import javax.xml.stream.XMLStreamException;
010    
011    import org.openstreetmap.josm.data.osm.DataSet;
012    import org.openstreetmap.josm.data.osm.OsmPrimitive;
013    import org.openstreetmap.josm.gui.progress.ProgressMonitor;
014    
015    public class OsmChangeReader extends OsmReader {
016    
017        public static final String[] ACTIONS = {"create", "modify", "delete"};
018        
019        /**
020         * constructor (for private and subclasses use only)
021         *
022         * @see #parseDataSet(InputStream, DataSet, ProgressMonitor)
023         */
024        protected OsmChangeReader() {
025        }
026        
027        /* (non-Javadoc)
028         * @see org.openstreetmap.josm.io.OsmReader#parseRoot()
029         */
030        @Override
031        protected void parseRoot() throws XMLStreamException {
032            if (parser.getLocalName().equals("osmChange")) {
033                parseOsmChange();
034            } else {
035                parseUnknown();
036            }
037        }
038    
039        private void parseOsmChange() throws XMLStreamException {
040            String v = parser.getAttributeValue(null, "version");
041            if (v == null) {
042                throwException(tr("Missing mandatory attribute ''{0}''.", "version"));
043            }
044            if (!v.equals("0.6")) {
045                throwException(tr("Unsupported version: {0}", v));
046            }
047            ds.setVersion(v);
048            while (parser.hasNext()) {
049                int event = parser.next();
050                if (event == XMLStreamConstants.START_ELEMENT) {
051                    if (Arrays.asList(ACTIONS).contains(parser.getLocalName())) {
052                        parseCommon(parser.getLocalName());
053                    } else {
054                        parseUnknown();
055                    }
056                } else if (event == XMLStreamConstants.END_ELEMENT) {
057                    return;
058                }
059            }
060        }
061    
062        private void parseCommon(String action) throws XMLStreamException {
063            while (parser.hasNext()) {
064                int event = parser.next();
065                if (event == XMLStreamConstants.START_ELEMENT) {
066                    OsmPrimitive p = null;
067                    if (parser.getLocalName().equals("node")) {
068                        p = parseNode();
069                    } else if (parser.getLocalName().equals("way")) {
070                        p = parseWay();
071                    } else if (parser.getLocalName().equals("relation")) {
072                        p = parseRelation();
073                    } else {
074                        parseUnknown();
075                    }
076                    if (p != null && action != null) {
077                        if (action.equals("modify")) {
078                            p.setModified(true);
079                        } else if (action.equals("delete")) {
080                            p.setDeleted(true);
081                        }
082                    }
083                } else if (event == XMLStreamConstants.END_ELEMENT) {
084                    return;
085                }
086            }
087        }
088        
089        /**
090         * Parse the given input source and return the dataset.
091         *
092         * @param source the source input stream. Must not be null.
093         * @param progressMonitor  the progress monitor. If null, {@link NullProgressMonitor#INSTANCE} is assumed
094         *
095         * @return the dataset with the parsed data
096         * @throws IllegalDataException thrown if the an error was found while parsing the data from the source
097         * @throws IllegalArgumentException thrown if source is null
098         */
099        public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
100            return new OsmChangeReader().doParseDataSet(source, progressMonitor);
101        }
102    }