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

Last change on this file since 6248 was 6248, checked in by Don-vip, 11 years ago

Rework console output:

  • new log level "error"
  • Replace nearly all calls to system.out and system.err to Main.(error|warn|info|debug)
  • Remove some unnecessary debug output
  • Some messages are modified (removal of "Info", "Warning", "Error" from the message itself -> notable i18n impact but limited to console error messages not seen by the majority of users, so that's ok)
  • 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;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;
11import org.openstreetmap.josm.data.APIDataSet;
12import org.openstreetmap.josm.data.osm.Changeset;
13import org.openstreetmap.josm.data.osm.IPrimitive;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
16import org.openstreetmap.josm.gui.DefaultNameFormatter;
17import org.openstreetmap.josm.gui.layer.OsmDataLayer;
18import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
19import org.openstreetmap.josm.gui.progress.ProgressMonitor;
20import org.openstreetmap.josm.io.OsmApi;
21import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
22import org.openstreetmap.josm.io.OsmServerWriter;
23import org.openstreetmap.josm.io.OsmTransferException;
24import org.openstreetmap.josm.tools.CheckParameterUtil;
25
26/**
27 * UploadLayerTask uploads the data managed by an {@link OsmDataLayer} asynchronously.
28 *
29 * <pre>
30 * ExecutorService executorService = ...
31 * UploadLayerTask task = new UploadLayerTask(layer, monitor);
32 * Future<?> taskFuture = executorServce.submit(task)
33 * try {
34 * // wait for the task to complete
35 * taskFuture.get();
36 * } catch(Exception e) {
37 * e.printStackTracek();
38 * }
39 * </pre>
40 */
41class UploadLayerTask extends AbstractIOTask implements Runnable {
42 private OsmServerWriter writer;
43 private OsmDataLayer layer;
44 private ProgressMonitor monitor;
45 private Changeset changeset;
46 private Collection<OsmPrimitive> toUpload;
47 private HashSet<IPrimitive> processedPrimitives;
48 private UploadStrategySpecification strategy;
49
50 /**
51 * Creates the upload task
52 *
53 * @param strategy the upload strategy specification
54 * @param layer the layer. Must not be null.
55 * @param monitor a progress monitor. If monitor is null, uses {@link NullProgressMonitor#INSTANCE}
56 * @param changeset the changeset to be used
57 * @throws IllegalArgumentException thrown, if layer is null
58 * @throws IllegalArgumentException thrown if strategy is null
59 */
60 public UploadLayerTask(UploadStrategySpecification strategy, OsmDataLayer layer, ProgressMonitor monitor, Changeset changeset) {
61 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
62 CheckParameterUtil.ensureParameterNotNull(strategy, "strategy");
63 if (monitor == null) {
64 monitor = NullProgressMonitor.INSTANCE;
65 }
66 this.layer = layer;
67 this.monitor = monitor;
68 this.changeset = changeset;
69 this.strategy = strategy;
70 processedPrimitives = new HashSet<IPrimitive>();
71 }
72
73 protected OsmPrimitive getPrimitive(OsmPrimitiveType type, long id) {
74 for (OsmPrimitive p: toUpload) {
75 if (OsmPrimitiveType.from(p).equals(type) && p.getId() == id)
76 return p;
77 }
78 return null;
79 }
80
81 /**
82 * Retries to recover the upload operation from an exception which was thrown because
83 * an uploaded primitive was already deleted on the server.
84 *
85 * @param e the exception throw by the API
86 * @param monitor a progress monitor
87 * @throws OsmTransferException thrown if we can't recover from the exception
88 */
89 protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor) throws OsmTransferException{
90 if (!e.isKnownPrimitive()) throw e;
91 OsmPrimitive p = getPrimitive(e.getPrimitiveType(), e.getPrimitiveId());
92 if (p == null) throw e;
93 if (p.isDeleted()) {
94 // we tried to delete an already deleted primitive.
95 //
96 Main.warn(tr("Object ''{0}'' is already deleted on the server. Skipping this object and retrying to upload.", p.getDisplayName(DefaultNameFormatter.getInstance())));
97 processedPrimitives.addAll(writer.getProcessedPrimitives());
98 processedPrimitives.add(p);
99 toUpload.removeAll(processedPrimitives);
100 return;
101 }
102 // exception was thrown because we tried to *update* an already deleted
103 // primitive. We can't resolve this automatically. Re-throw exception,
104 // a conflict is going to be created later.
105 throw e;
106 }
107
108 @Override
109 public void run() {
110 monitor.indeterminateSubTask(tr("Preparing objects to upload ..."));
111 APIDataSet ds = new APIDataSet(layer.data);
112 try {
113 ds.adjustRelationUploadOrder();
114 } catch(CyclicUploadDependencyException e) {
115 setLastException(e);
116 return;
117 }
118 toUpload = ds.getPrimitives();
119 if (toUpload.isEmpty())
120 return;
121 writer = new OsmServerWriter();
122 try {
123 while(true) {
124 try {
125 ProgressMonitor m = monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
126 if (isCanceled()) return;
127 writer.uploadOsm(strategy, toUpload, changeset, m);
128 processedPrimitives.addAll(writer.getProcessedPrimitives()); // OsmPrimitive in => OsmPrimitive out
129 break;
130 } catch(OsmApiPrimitiveGoneException e) {
131 recoverFromGoneOnServer(e, monitor);
132 }
133 }
134 if (strategy.isCloseChangesetAfterUpload()) {
135 if (changeset != null && changeset.getId() > 0) {
136 OsmApi.getOsmApi().closeChangeset(changeset, monitor.createSubTaskMonitor(0, false));
137 }
138 }
139 } catch (Exception sxe) {
140 if (isCanceled()) {
141 Main.info("Ignoring exception caught because upload is canceled. Exception is: " + sxe.toString());
142 return;
143 }
144 setLastException(sxe);
145 }
146
147 if (isCanceled())
148 return;
149 layer.cleanupAfterUpload(processedPrimitives);
150 layer.onPostUploadToServer();
151
152 // don't process exceptions remembered with setLastException().
153 // Caller is supposed to deal with them.
154 }
155
156 @Override
157 public void cancel() {
158 setCanceled(true);
159 if (writer != null) {
160 writer.cancel();
161 }
162 }
163}
Note: See TracBrowser for help on using the repository browser.