source: josm/trunk/src/org/openstreetmap/josm/gui/io/UploadLayerTask.java@ 16438

Last change on this file since 16438 was 16438, checked in by simon04, 4 years ago

see #19251 - Java 8: use Stream

  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.Collection;
7import java.util.HashSet;
8import java.util.Optional;
9import java.util.Set;
10
11import org.openstreetmap.josm.data.APIDataSet;
12import org.openstreetmap.josm.data.osm.Changeset;
13import org.openstreetmap.josm.data.osm.CyclicUploadDependencyException;
14import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
15import org.openstreetmap.josm.data.osm.IPrimitive;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
18import org.openstreetmap.josm.gui.layer.OsmDataLayer;
19import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
20import org.openstreetmap.josm.gui.progress.ProgressMonitor;
21import org.openstreetmap.josm.io.OsmApi;
22import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
23import org.openstreetmap.josm.io.OsmServerWriter;
24import org.openstreetmap.josm.io.OsmTransferException;
25import org.openstreetmap.josm.io.UploadStrategySpecification;
26import org.openstreetmap.josm.tools.CheckParameterUtil;
27import org.openstreetmap.josm.tools.Logging;
28
29/**
30 * UploadLayerTask uploads the data managed by an {@link OsmDataLayer} asynchronously.
31 *
32 * <pre>
33 * ExecutorService executorService = ...
34 * UploadLayerTask task = new UploadLayerTask(layer, monitor);
35 * Future&lt;?&gt; taskFuture = executorService.submit(task)
36 * try {
37 * // wait for the task to complete
38 * taskFuture.get();
39 * } catch (Exception e) {
40 * e.printStackTrace();
41 * }
42 * </pre>
43 */
44public class UploadLayerTask extends AbstractIOTask {
45 private OsmServerWriter writer;
46 private final OsmDataLayer layer;
47 private final ProgressMonitor monitor;
48 private final Changeset changeset;
49 private Collection<OsmPrimitive> toUpload;
50 private final Set<IPrimitive> processedPrimitives;
51 private final UploadStrategySpecification strategy;
52
53 /**
54 * Creates the upload task
55 *
56 * @param strategy the upload strategy specification
57 * @param layer the layer. Must not be null.
58 * @param monitor a progress monitor. If monitor is null, uses {@link NullProgressMonitor#INSTANCE}
59 * @param changeset the changeset to be used
60 * @throws IllegalArgumentException if layer is null
61 * @throws IllegalArgumentException if strategy is null
62 */
63 public UploadLayerTask(UploadStrategySpecification strategy, OsmDataLayer layer, ProgressMonitor monitor, Changeset changeset) {
64 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
65 CheckParameterUtil.ensureParameterNotNull(strategy, "strategy");
66 this.layer = layer;
67 this.monitor = Optional.ofNullable(monitor).orElse(NullProgressMonitor.INSTANCE);
68 this.changeset = changeset;
69 this.strategy = strategy;
70 processedPrimitives = new HashSet<>();
71 }
72
73 protected OsmPrimitive getPrimitive(OsmPrimitiveType type, long id) {
74 return toUpload.stream()
75 .filter(p -> OsmPrimitiveType.from(p) == type && p.getId() == id)
76 .findFirst().orElse(null);
77 }
78
79 /**
80 * Retries to recover the upload operation from an exception which was thrown because
81 * an uploaded primitive was already deleted on the server.
82 *
83 * @param e the exception throw by the API
84 * @throws OsmTransferException if we can't recover from the exception
85 */
86 protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e) throws OsmTransferException {
87 if (!e.isKnownPrimitive()) throw e;
88 OsmPrimitive p = getPrimitive(e.getPrimitiveType(), e.getPrimitiveId());
89 if (p == null) throw e;
90 if (p.isDeleted()) {
91 // we tried to delete an already deleted primitive.
92 Logging.warn(tr("Object ''{0}'' is already deleted on the server. Skipping this object and retrying to upload.",
93 p.getDisplayName(DefaultNameFormatter.getInstance())));
94 processedPrimitives.addAll(writer.getProcessedPrimitives());
95 processedPrimitives.add(p);
96 toUpload.removeAll(processedPrimitives);
97 return;
98 }
99 // exception was thrown because we tried to *update* an already deleted primitive. We can't resolve this automatically.
100 // Re-throw exception, a conflict is going to be created later.
101 throw e;
102 }
103
104 @Override
105 public void run() {
106 monitor.indeterminateSubTask(tr("Preparing objects to upload ..."));
107 APIDataSet ds = new APIDataSet(layer.getDataSet());
108 try {
109 ds.adjustRelationUploadOrder();
110 } catch (CyclicUploadDependencyException e) {
111 setLastException(e);
112 return;
113 }
114 toUpload = ds.getPrimitives();
115 if (toUpload.isEmpty())
116 return;
117 writer = new OsmServerWriter();
118 try {
119 while (true) {
120 try {
121 ProgressMonitor m = monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
122 if (isCanceled()) return;
123 writer.uploadOsm(strategy, toUpload, changeset, m);
124 processedPrimitives.addAll(writer.getProcessedPrimitives()); // OsmPrimitive in => OsmPrimitive out
125 break;
126 } catch (OsmApiPrimitiveGoneException e) {
127 recoverFromGoneOnServer(e);
128 }
129 }
130 if (strategy.isCloseChangesetAfterUpload() && changeset != null && changeset.getId() > 0) {
131 OsmApi.getOsmApi().closeChangeset(changeset, monitor.createSubTaskMonitor(0, false));
132 }
133 } catch (OsmTransferException sxe) {
134 if (isCanceled()) {
135 Logging.info("Ignoring exception caught because upload is canceled. Exception is: " + sxe);
136 return;
137 }
138 setLastException(sxe);
139 }
140
141 if (isCanceled())
142 return;
143 layer.cleanupAfterUpload(processedPrimitives);
144 layer.onPostUploadToServer();
145
146 // don't process exceptions remembered with setLastException().
147 // Caller is supposed to deal with them.
148 }
149
150 @Override
151 public void cancel() {
152 setCanceled(true);
153 if (writer != null) {
154 writer.cancel();
155 }
156 }
157}
Note: See TracBrowser for help on using the repository browser.