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