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

Last change on this file since 4310 was 4310, checked in by stoecker, 13 years ago

fix #6680, fix #6677 - i18n issues

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