source: josm/trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java

Last change on this file was 14946, checked in by GerdP, 5 years ago

see #17459: remove duplicated code in reverter corehacks
Step 1: Add needed code to core methods.
Major changes:
1) If a changeset contains multiple versions for a primitive, class ChangesetDataSet keeps the first and the last version (not just the last) and provides methods to access them, unused method getPrimitivesByModificationType() was removed
2) The changeset reader classes have a new field useAnonymousUser. If set, the user found in a changeset is replaced by the anonymous user.

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.InputStreamReader;
9import java.io.StringReader;
10import java.nio.charset.StandardCharsets;
11
12import javax.xml.parsers.ParserConfigurationException;
13
14import org.openstreetmap.josm.data.osm.ChangesetDataSet;
15import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType;
16import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
17import org.openstreetmap.josm.gui.progress.ProgressMonitor;
18import org.openstreetmap.josm.tools.CheckParameterUtil;
19import org.openstreetmap.josm.tools.Logging;
20import org.openstreetmap.josm.tools.XmlParsingException;
21import org.openstreetmap.josm.tools.XmlUtils;
22import org.xml.sax.Attributes;
23import org.xml.sax.InputSource;
24import org.xml.sax.SAXException;
25import org.xml.sax.SAXParseException;
26
27/**
28 * Parser for OSM changeset content.
29 * @since 2688
30 */
31public class OsmChangesetContentParser {
32
33 private final InputSource source;
34 private final ChangesetDataSet data = new ChangesetDataSet();
35
36 private class Parser extends AbstractParser {
37 Parser(boolean useAnonymousUser) {
38 this.useAnonymousUser = useAnonymousUser;
39 }
40
41 /** the current change modification type */
42 private ChangesetDataSet.ChangesetModificationType currentModificationType;
43
44 @Override
45 protected void throwException(String message) throws XmlParsingException {
46 throw new XmlParsingException(message).rememberLocation(locator);
47 }
48
49 @Override
50 protected void throwException(String message, Exception e) throws XmlParsingException {
51 throw new XmlParsingException(message, e).rememberLocation(locator);
52 }
53
54 @Override
55 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
56 if (super.doStartElement(qName, atts)) {
57 // done
58 return;
59 }
60 switch (qName) {
61 case "osmChange":
62 // do nothing
63 break;
64 case "create":
65 currentModificationType = ChangesetModificationType.CREATED;
66 break;
67 case "modify":
68 currentModificationType = ChangesetModificationType.UPDATED;
69 break;
70 case "delete":
71 currentModificationType = ChangesetModificationType.DELETED;
72 break;
73 default:
74 Logging.warn(tr("Unsupported start element ''{0}'' in changeset content at position ({1},{2}). Skipping.",
75 qName, locator.getLineNumber(), locator.getColumnNumber()));
76 }
77 }
78
79 @Override
80 public void endElement(String uri, String localName, String qName) throws SAXException {
81 switch (qName) {
82 case "node":
83 case "way":
84 case "relation":
85 if (currentModificationType == null) {
86 // CHECKSTYLE.OFF: LineLength
87 throwException(tr("Illegal document structure. Found node, way, or relation outside of ''create'', ''modify'', or ''delete''."));
88 // CHECKSTYLE.ON: LineLength
89 }
90 data.put(currentPrimitive, currentModificationType);
91 break;
92 case "create":
93 case "modify":
94 case "delete":
95 currentModificationType = null;
96 break;
97 case "osmChange":
98 case "tag":
99 case "nd":
100 case "member":
101 // do nothing
102 break;
103 default:
104 Logging.warn(tr("Unsupported end element ''{0}'' in changeset content at position ({1},{2}). Skipping.",
105 qName, locator.getLineNumber(), locator.getColumnNumber()));
106 }
107 }
108
109 @Override
110 public void error(SAXParseException e) throws SAXException {
111 throwException(null, e);
112 }
113
114 @Override
115 public void fatalError(SAXParseException e) throws SAXException {
116 throwException(null, e);
117 }
118 }
119
120 /**
121 * Constructs a new {@code OsmChangesetContentParser}.
122 *
123 * @param source the input stream with the changeset content as XML document. Must not be null.
124 * @throws IllegalArgumentException if source is {@code null}.
125 */
126 public OsmChangesetContentParser(InputStream source) {
127 CheckParameterUtil.ensureParameterNotNull(source, "source");
128 this.source = new InputSource(new InputStreamReader(source, StandardCharsets.UTF_8));
129 }
130
131 /**
132 * Constructs a new {@code OsmChangesetContentParser}.
133 *
134 * @param source the input stream with the changeset content as XML document. Must not be null.
135 * @throws IllegalArgumentException if source is {@code null}.
136 */
137 public OsmChangesetContentParser(String source) {
138 CheckParameterUtil.ensureParameterNotNull(source, "source");
139 this.source = new InputSource(new StringReader(source));
140 }
141
142 /**
143 * Parses the content.
144 *
145 * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
146 * @return the parsed data
147 * @throws XmlParsingException if something went wrong. Check for chained
148 * exceptions.
149 */
150 public ChangesetDataSet parse(ProgressMonitor progressMonitor) throws XmlParsingException {
151 return parse(progressMonitor, false);
152 }
153
154 /**
155 * Parses the content.
156 *
157 * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
158 * @param useAnonymousUser if true, replace all user information with the anonymous user
159 * @return the parsed data
160 * @throws XmlParsingException if something went wrong. Check for chained
161 * exceptions.
162 * @since 14946
163 */
164 public ChangesetDataSet parse(ProgressMonitor progressMonitor, boolean useAnonymousUser) throws XmlParsingException {
165 if (progressMonitor == null) {
166 progressMonitor = NullProgressMonitor.INSTANCE;
167 }
168 try {
169 progressMonitor.beginTask("");
170 progressMonitor.indeterminateSubTask(tr("Parsing changeset content ..."));
171 XmlUtils.parseSafeSAX(source, new Parser(useAnonymousUser));
172 } catch (XmlParsingException e) {
173 throw e;
174 } catch (ParserConfigurationException | SAXException | IOException e) {
175 throw new XmlParsingException(e);
176 } finally {
177 progressMonitor.finishTask();
178 }
179 return data;
180 }
181
182 /**
183 * Parses the content from the input source
184 *
185 * @return the parsed data
186 * @throws XmlParsingException if something went wrong. Check for chained
187 * exceptions.
188 */
189 public ChangesetDataSet parse() throws XmlParsingException {
190 return parse(null, false);
191 }
192}
Note: See TracBrowser for help on using the repository browser.