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