source: josm/trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java@ 18877

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

see #15229 - see #15182 - deprecate gui.JosmUserIdentityManager - replaced by data.UserIdentityManager

  • Property svn:eol-style set to native
File size: 10.7 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[626]2package org.openstreetmap.josm.io;
3
[1990]4import static org.openstreetmap.josm.tools.I18n.marktr;
[626]5import static org.openstreetmap.josm.tools.I18n.tr;
[2852]6import static org.openstreetmap.josm.tools.I18n.trn;
[626]7
[2569]8import java.util.ArrayList;
[626]9import java.util.Collection;
[2569]10import java.util.Iterator;
[626]11import java.util.LinkedList;
[2569]12import java.util.List;
[11288]13import java.util.concurrent.TimeUnit;
[1523]14
[12743]15import org.openstreetmap.josm.data.UserIdentityManager;
[2040]16import org.openstreetmap.josm.data.osm.Changeset;
[7656]17import org.openstreetmap.josm.data.osm.OsmPrimitive;
[1814]18import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
[2198]19import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
[1811]20import org.openstreetmap.josm.gui.progress.ProgressMonitor;
[2852]21import org.openstreetmap.josm.tools.CheckParameterUtil;
[626]22
23/**
24 * Class that uploads all changes to the osm server.
25 *
26 * This is done like this: - All objects with id = 0 are uploaded as new, except
27 * those in deleted, which are ignored - All objects in deleted list are
28 * deleted. - All remaining objects with modified flag set are updated.
29 */
[1523]30public class OsmServerWriter {
[1137]31 /**
32 * This list contains all successfully processed objects. The caller of
33 * upload* has to check this after the call and update its dataset.
34 *
35 * If a server connection error occurs, this may contain fewer entries
36 * than where passed in the list to upload*.
37 */
[7656]38 private Collection<OsmPrimitive> processed;
[626]39
[8126]40 private static volatile List<OsmServerWritePostprocessor> postprocessors;
[10217]41
42 /**
43 * Registers a post-processor.
44 * @param pp post-processor to register
45 */
[4645]46 public static void registerPostprocessor(OsmServerWritePostprocessor pp) {
47 if (postprocessors == null) {
[7005]48 postprocessors = new ArrayList<>();
[4645]49 }
50 postprocessors.add(pp);
51 }
[8510]52
[10217]53 /**
54 * Unregisters a post-processor.
55 * @param pp post-processor to unregister
56 */
[4645]57 public static void unregisterPostprocessor(OsmServerWritePostprocessor pp) {
58 if (postprocessors != null) {
59 postprocessors.remove(pp);
60 }
61 }
62
[9078]63 private final OsmApi api = OsmApi.getOsmApi();
[8840]64 private boolean canceled;
[1628]65
[8285]66 private long uploadStartTime;
[1169]67
[10217]68 protected String timeLeft(int progress, int listSize) {
[1137]69 long now = System.currentTimeMillis();
70 long elapsed = now - uploadStartTime;
[1663]71 if (elapsed == 0) {
[1137]72 elapsed = 1;
[1663]73 }
[10001]74 double uploadsPerMs = (double) progress / elapsed;
[10181]75 double uploadsLeft = (double) listSize - progress;
[10001]76 long msLeft = (long) (uploadsLeft / uploadsPerMs);
[11288]77 long minutesLeft = msLeft / TimeUnit.MINUTES.toMillis(1);
78 long secondsLeft = (msLeft / TimeUnit.SECONDS.toMillis(1)) % TimeUnit.MINUTES.toSeconds(1);
[10001]79 StringBuilder timeLeftStr = new StringBuilder().append(minutesLeft).append(':');
80 if (secondsLeft < 10) {
81 timeLeftStr.append('0');
[1663]82 }
[10001]83 return timeLeftStr.append(secondsLeft).toString();
[1137]84 }
[1169]85
[1523]86 /**
[11480]87 * Uploads the changes individually. Invokes one API call per uploaded primitive.
[2512]88 *
[1894]89 * @param primitives the collection of primitives to upload
90 * @param progressMonitor the progress monitor
[8291]91 * @throws OsmTransferException if an exception occurs
[1894]92 */
[8509]93 protected void uploadChangesIndividually(Collection<? extends OsmPrimitive> primitives, ProgressMonitor progressMonitor)
94 throws OsmTransferException {
[1894]95 try {
[2078]96 progressMonitor.beginTask(tr("Starting to upload with one request per primitive ..."));
[1894]97 progressMonitor.setTicksCount(primitives.size());
98 uploadStartTime = System.currentTimeMillis();
[7656]99 for (OsmPrimitive osm : primitives) {
[10217]100 String msg;
[1989]101 switch(OsmPrimitiveType.from(osm)) {
[2273]102 case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
103 case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
104 case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
[10217]105 default: throw new AssertionError();
[1989]106 }
[10217]107 int progress = progressMonitor.getTicks();
[1894]108 progressMonitor.subTask(
[1989]109 tr(msg,
110 Math.round(100.0*progress/primitives.size()),
111 progress,
112 primitives.size(),
[10217]113 timeLeft(progress, primitives.size()),
114 osm.getName() == null ? osm.getId() : osm.getName(), osm.getId()));
[8510]115 makeApiRequest(osm, progressMonitor);
[1894]116 processed.add(osm);
117 progressMonitor.worked(1);
118 }
119 } finally {
[2115]120 progressMonitor.finishTask();
[1894]121 }
122 }
123
124 /**
125 * Upload all changes in one diff upload
[2512]126 *
[1894]127 * @param primitives the collection of primitives to upload
128 * @param progressMonitor the progress monitor
[8291]129 * @throws OsmTransferException if an exception occurs
[1894]130 */
[8509]131 protected void uploadChangesAsDiffUpload(Collection<? extends OsmPrimitive> primitives, ProgressMonitor progressMonitor)
132 throws OsmTransferException {
[1894]133 try {
[2078]134 progressMonitor.beginTask(tr("Starting to upload in one request ..."));
[1894]135 processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
136 } finally {
[2115]137 progressMonitor.finishTask();
[1894]138 }
139 }
140
141 /**
[2569]142 * Upload all changes in one diff upload
143 *
144 * @param primitives the collection of primitives to upload
145 * @param progressMonitor the progress monitor
[6830]146 * @param chunkSize the size of the individual upload chunks. &gt; 0 required.
[8291]147 * @throws IllegalArgumentException if chunkSize &lt;= 0
148 * @throws OsmTransferException if an exception occurs
[2569]149 */
[8509]150 protected void uploadChangesInChunks(Collection<? extends OsmPrimitive> primitives, ProgressMonitor progressMonitor, int chunkSize)
[10217]151 throws OsmTransferException {
[8510]152 if (chunkSize <= 0)
[2569]153 throw new IllegalArgumentException(tr("Value >0 expected for parameter ''{0}'', got {1}", "chunkSize", chunkSize));
154 try {
155 progressMonitor.beginTask(tr("Starting to upload in chunks..."));
[7656]156 List<OsmPrimitive> chunk = new ArrayList<>(chunkSize);
157 Iterator<? extends OsmPrimitive> it = primitives.iterator();
[8510]158 int numChunks = (int) Math.ceil((double) primitives.size() / (double) chunkSize);
159 int i = 0;
160 while (it.hasNext()) {
[2569]161 i++;
162 if (canceled) return;
163 int j = 0;
164 chunk.clear();
[8510]165 while (it.hasNext() && j < chunkSize) {
[2569]166 if (canceled) return;
167 j++;
168 chunk.add(it.next());
169 }
[2852]170 progressMonitor.setCustomText(
171 trn("({0}/{1}) Uploading {2} object...",
172 "({0}/{1}) Uploading {2} objects...",
173 chunk.size(), i, numChunks, chunk.size()));
[2569]174 processed.addAll(api.uploadDiff(chunk, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
175 }
176 } finally {
177 progressMonitor.finishTask();
178 }
179 }
180
181 /**
[1628]182 * Send the dataset to the server.
[1677]183 *
[2569]184 * @param strategy the upload strategy. Must not be null.
[1663]185 * @param primitives list of objects to send
[2198]186 * @param changeset the changeset the data is uploaded to. Must not be null.
[5266]187 * @param monitor the progress monitor. If null, assumes {@link NullProgressMonitor#INSTANCE}
[8291]188 * @throws IllegalArgumentException if changeset is null
189 * @throws IllegalArgumentException if strategy is null
190 * @throws OsmTransferException if something goes wrong
[1523]191 */
[8510]192 public void uploadOsm(UploadStrategySpecification strategy, Collection<? extends OsmPrimitive> primitives,
193 Changeset changeset, ProgressMonitor monitor) throws OsmTransferException {
[2852]194 CheckParameterUtil.ensureParameterNotNull(changeset, "changeset");
[7005]195 processed = new LinkedList<>();
[2198]196 monitor = monitor == null ? NullProgressMonitor.INSTANCE : monitor;
197 monitor.beginTask(tr("Uploading data ..."));
[1811]198 try {
[2198]199 api.initialize(monitor);
[2040]200 // check whether we can use diff upload
[2115]201 if (changeset.getId() == 0) {
[8510]202 api.openChangeset(changeset, monitor.createSubTaskMonitor(0, false));
[9528]203 // update the user information
[12743]204 changeset.setUser(UserIdentityManager.getInstance().asUser());
[2115]205 } else {
[8510]206 api.updateChangeset(changeset, monitor.createSubTaskMonitor(0, false));
[2115]207 }
208 api.setChangeset(changeset);
[2569]209 switch(strategy.getStrategy()) {
210 case SINGLE_REQUEST_STRATEGY:
[8510]211 uploadChangesAsDiffUpload(primitives, monitor.createSubTaskMonitor(0, false));
[2569]212 break;
213 case INDIVIDUAL_OBJECTS_STRATEGY:
[8510]214 uploadChangesIndividually(primitives, monitor.createSubTaskMonitor(0, false));
[2569]215 break;
216 case CHUNKED_DATASET_STRATEGY:
[10216]217 default:
[8510]218 uploadChangesInChunks(primitives, monitor.createSubTaskMonitor(0, false), strategy.getChunkSize());
[2569]219 break;
[1071]220 }
[1811]221 } finally {
[4645]222 executePostprocessors(monitor);
[2198]223 monitor.finishTask();
224 api.setChangeset(null);
[1137]225 }
226 }
[1169]227
[7656]228 void makeApiRequest(OsmPrimitive osm, ProgressMonitor progressMonitor) throws OsmTransferException {
[2025]229 if (osm.isDeleted()) {
[1879]230 api.deletePrimitive(osm, progressMonitor);
[2273]231 } else if (osm.isNew()) {
[2035]232 api.createPrimitive(osm, progressMonitor);
[1137]233 } else {
[4645]234 api.modifyPrimitive(osm, progressMonitor);
[1137]235 }
236 }
[624]237
[10217]238 /**
239 * Cancel operation.
240 */
[2037]241 public void cancel() {
[2569]242 this.canceled = true;
[2037]243 if (api != null) {
244 api.cancel();
[1581]245 }
[1137]246 }
[1894]247
248 /**
249 * Replies the collection of successfully processed primitives
[2512]250 *
[1894]251 * @return the collection of successfully processed primitives
252 */
[7656]253 public Collection<OsmPrimitive> getProcessedPrimitives() {
[1894]254 return processed;
255 }
[4645]256
257 /**
258 * Calls all registered upload postprocessors.
[9231]259 * @param pm progress monitor
[4645]260 */
261 public void executePostprocessors(ProgressMonitor pm) {
262 if (postprocessors != null) {
263 for (OsmServerWritePostprocessor pp : postprocessors) {
264 pp.postprocessUploadedPrimitives(processed, pm);
265 }
266 }
267 }
[626]268}
Note: See TracBrowser for help on using the repository browser.