source: josm/trunk/src/org/openstreetmap/josm/io/DiffResultProcessor.java@ 11702

Last change on this file since 11702 was 11553, checked in by Don-vip, 7 years ago

refactor handling of null values - use Java 8 Optional where possible

  • Property svn:eol-style set to native
File size: 7.2 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.StringReader;
8import java.util.Collection;
9import java.util.Collections;
10import java.util.Date;
11import java.util.HashMap;
12import java.util.HashSet;
13import java.util.Map;
14import java.util.Optional;
15import java.util.Set;
16
17import javax.xml.parsers.ParserConfigurationException;
18
19import org.openstreetmap.josm.data.osm.Changeset;
20import org.openstreetmap.josm.data.osm.DataSet;
21import org.openstreetmap.josm.data.osm.OsmPrimitive;
22import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
23import org.openstreetmap.josm.data.osm.PrimitiveId;
24import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
25import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
26import org.openstreetmap.josm.gui.progress.ProgressMonitor;
27import org.openstreetmap.josm.tools.CheckParameterUtil;
28import org.openstreetmap.josm.tools.Utils;
29import org.openstreetmap.josm.tools.XmlParsingException;
30import org.xml.sax.Attributes;
31import org.xml.sax.InputSource;
32import org.xml.sax.Locator;
33import org.xml.sax.SAXException;
34import org.xml.sax.helpers.DefaultHandler;
35
36public class DiffResultProcessor {
37
38 private static class DiffResultEntry {
39 private long newId;
40 private int newVersion;
41 }
42
43 /**
44 * mapping from old id to new id and version, the result of parsing the diff result
45 * replied by the server
46 */
47 private final Map<PrimitiveId, DiffResultEntry> diffResults = new HashMap<>();
48 /**
49 * the set of processed primitives *after* the new id, the new version and the new changeset id is set
50 */
51 private final Set<OsmPrimitive> processed;
52 /**
53 * the collection of primitives being uploaded
54 */
55 private final Collection<? extends OsmPrimitive> primitives;
56
57 /**
58 * Creates a diff result reader
59 *
60 * @param primitives the collection of primitives which have been uploaded. If null,
61 * assumes an empty collection.
62 */
63 public DiffResultProcessor(Collection<? extends OsmPrimitive> primitives) {
64 this.primitives = Optional.ofNullable(primitives).orElseGet(Collections::emptyList);
65 this.processed = new HashSet<>();
66 }
67
68 /**
69 * Parse the response from a diff upload to the OSM API.
70 *
71 * @param diffUploadResponse the response. Must not be null.
72 * @param progressMonitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
73 * @throws IllegalArgumentException if diffUploadRequest is null
74 * @throws XmlParsingException if the diffUploadRequest can't be parsed successfully
75 *
76 */
77 public void parse(String diffUploadResponse, ProgressMonitor progressMonitor) throws XmlParsingException {
78 if (progressMonitor == null) {
79 progressMonitor = NullProgressMonitor.INSTANCE;
80 }
81 CheckParameterUtil.ensureParameterNotNull(diffUploadResponse, "diffUploadResponse");
82 try {
83 progressMonitor.beginTask(tr("Parsing response from server..."));
84 InputSource inputSource = new InputSource(new StringReader(diffUploadResponse));
85 Utils.parseSafeSAX(inputSource, new Parser());
86 } catch (XmlParsingException e) {
87 throw e;
88 } catch (IOException | ParserConfigurationException | SAXException e) {
89 throw new XmlParsingException(e);
90 } finally {
91 progressMonitor.finishTask();
92 }
93 }
94
95 /**
96 * Postprocesses the diff result read and parsed from the server.
97 *
98 * Uploaded objects are assigned their new id (if they got assigned a new
99 * id by the server), their new version (if the version was incremented),
100 * and the id of the changeset to which they were uploaded.
101 *
102 * @param cs the current changeset. Ignored if null.
103 * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
104 * @return the collection of processed primitives
105 */
106 protected Set<OsmPrimitive> postProcess(Changeset cs, ProgressMonitor monitor) {
107 if (monitor == null) {
108 monitor = NullProgressMonitor.INSTANCE;
109 }
110 DataSet ds = null;
111 if (!primitives.isEmpty()) {
112 ds = primitives.iterator().next().getDataSet();
113 }
114 if (ds != null) {
115 ds.beginUpdate();
116 }
117 try {
118 monitor.beginTask("Postprocessing uploaded data ...");
119 monitor.setTicksCount(primitives.size());
120 monitor.setTicks(0);
121 for (OsmPrimitive p : primitives) {
122 monitor.worked(1);
123 DiffResultEntry entry = diffResults.get(p.getPrimitiveId());
124 if (entry == null) {
125 continue;
126 }
127 processed.add(p);
128 if (!p.isDeleted()) {
129 p.setOsmId(entry.newId, entry.newVersion);
130 p.setVisible(true);
131 } else {
132 p.setVisible(false);
133 }
134 if (cs != null && !cs.isNew()) {
135 p.setChangesetId(cs.getId());
136 p.setUser(cs.getUser());
137 // TODO is there a way to obtain the timestamp for non-closed changesets?
138 p.setTimestamp(Utils.firstNonNull(cs.getClosedAt(), new Date()));
139 }
140 }
141 return processed;
142 } finally {
143 if (ds != null) {
144 ds.endUpdate();
145 }
146 monitor.finishTask();
147 }
148 }
149
150 private class Parser extends DefaultHandler {
151 private Locator locator;
152
153 @Override
154 public void setDocumentLocator(Locator locator) {
155 this.locator = locator;
156 }
157
158 protected void throwException(String msg) throws XmlParsingException {
159 throw new XmlParsingException(msg).rememberLocation(locator);
160 }
161
162 @Override
163 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
164 try {
165 switch (qName) {
166 case "diffResult":
167 // the root element, ignore
168 break;
169 case "node":
170 case "way":
171 case "relation":
172 PrimitiveId id = new SimplePrimitiveId(
173 Long.parseLong(atts.getValue("old_id")),
174 OsmPrimitiveType.fromApiTypeName(qName)
175 );
176 DiffResultEntry entry = new DiffResultEntry();
177 if (atts.getValue("new_id") != null) {
178 entry.newId = Long.parseLong(atts.getValue("new_id"));
179 }
180 if (atts.getValue("new_version") != null) {
181 entry.newVersion = Integer.parseInt(atts.getValue("new_version"));
182 }
183 diffResults.put(id, entry);
184 break;
185 default:
186 throwException(tr("Unexpected XML element with name ''{0}''", qName));
187 }
188 } catch (NumberFormatException e) {
189 throw new XmlParsingException(e).rememberLocation(locator);
190 }
191 }
192 }
193}
Note: See TracBrowser for help on using the repository browser.