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

Last change on this file since 2937 was 2852, checked in by mjulius, 14 years ago

fix messages for io

  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.Iterator;
11import java.util.LinkedList;
12import java.util.List;
13import java.util.logging.Logger;
14
15import org.openstreetmap.josm.data.osm.Changeset;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
18import org.openstreetmap.josm.gui.io.UploadStrategySpecification;
19import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
20import org.openstreetmap.josm.gui.progress.ProgressMonitor;
21import org.openstreetmap.josm.tools.CheckParameterUtil;
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 */
30public class OsmServerWriter {
31 static private final Logger logger = Logger.getLogger(OsmServerWriter.class.getName());
32
33 /**
34 * This list contains all successfully processed objects. The caller of
35 * upload* has to check this after the call and update its dataset.
36 *
37 * If a server connection error occurs, this may contain fewer entries
38 * than where passed in the list to upload*.
39 */
40 private Collection<OsmPrimitive> processed;
41
42 private OsmApi api = OsmApi.getOsmApi();
43 private boolean canceled = false;
44
45 private static final int MSECS_PER_SECOND = 1000;
46 private static final int SECONDS_PER_MINUTE = 60;
47 private static final int MSECS_PER_MINUTE = MSECS_PER_SECOND * SECONDS_PER_MINUTE;
48
49 long uploadStartTime;
50
51 public String timeLeft(int progress, int list_size) {
52 long now = System.currentTimeMillis();
53 long elapsed = now - uploadStartTime;
54 if (elapsed == 0) {
55 elapsed = 1;
56 }
57 float uploads_per_ms = (float)progress / elapsed;
58 float uploads_left = list_size - progress;
59 int ms_left = (int)(uploads_left / uploads_per_ms);
60 int minutes_left = ms_left / MSECS_PER_MINUTE;
61 int seconds_left = (ms_left / MSECS_PER_SECOND) % SECONDS_PER_MINUTE ;
62 String time_left_str = Integer.toString(minutes_left) + ":";
63 if (seconds_left < 10) {
64 time_left_str += "0";
65 }
66 time_left_str += Integer.toString(seconds_left);
67 return time_left_str;
68 }
69
70 /**
71 * Uploads the changes individually. Invokes one API call per uploaded primitmive.
72 *
73 * @param primitives the collection of primitives to upload
74 * @param progressMonitor the progress monitor
75 * @throws OsmTransferException thrown if an exception occurs
76 */
77 protected void uploadChangesIndividually(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
78 try {
79 progressMonitor.beginTask(tr("Starting to upload with one request per primitive ..."));
80 progressMonitor.setTicksCount(primitives.size());
81 uploadStartTime = System.currentTimeMillis();
82 for (OsmPrimitive osm : primitives) {
83 int progress = progressMonitor.getTicks();
84 String time_left_str = timeLeft(progress, primitives.size());
85 String msg = "";
86 switch(OsmPrimitiveType.from(osm)) {
87 case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
88 case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
89 case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
90 }
91 progressMonitor.subTask(
92 tr(msg,
93 Math.round(100.0*progress/primitives.size()),
94 progress,
95 primitives.size(),
96 time_left_str,
97 osm.getName() == null ? osm.getId() : osm.getName(),
98 osm.getId()));
99 makeApiRequest(osm,progressMonitor);
100 processed.add(osm);
101 progressMonitor.worked(1);
102 }
103 } catch(OsmTransferException e) {
104 throw e;
105 } catch(Exception e) {
106 throw new OsmTransferException(e);
107 } finally {
108 progressMonitor.finishTask();
109 }
110 }
111
112 /**
113 * Upload all changes in one diff upload
114 *
115 * @param primitives the collection of primitives to upload
116 * @param progressMonitor the progress monitor
117 * @throws OsmTransferException thrown if an exception occurs
118 */
119 protected void uploadChangesAsDiffUpload(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
120 try {
121 progressMonitor.beginTask(tr("Starting to upload in one request ..."));
122 processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
123 } catch(OsmTransferException e) {
124 throw e;
125 } finally {
126 progressMonitor.finishTask();
127 }
128 }
129
130 /**
131 * Upload all changes in one diff upload
132 *
133 * @param primitives the collection of primitives to upload
134 * @param progressMonitor the progress monitor
135 * @param chunkSize the size of the individual upload chunks. > 0 required.
136 * @throws IllegalArgumentException thrown if chunkSize <= 0
137 * @throws OsmTransferException thrown if an exception occurs
138 */
139 protected void uploadChangesInChunks(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor, int chunkSize) throws OsmTransferException, IllegalArgumentException {
140 if (chunkSize <=0)
141 throw new IllegalArgumentException(tr("Value >0 expected for parameter ''{0}'', got {1}", "chunkSize", chunkSize));
142 try {
143 progressMonitor.beginTask(tr("Starting to upload in chunks..."));
144 List<OsmPrimitive> chunk = new ArrayList<OsmPrimitive>(chunkSize);
145 Iterator<OsmPrimitive> it = primitives.iterator();
146 int numChunks = (int)Math.ceil((double)primitives.size() / (double)chunkSize);
147 int i= 0;
148 while(it.hasNext()) {
149 i++;
150 if (canceled) return;
151 int j = 0;
152 chunk.clear();
153 while(it.hasNext() && j < chunkSize) {
154 if (canceled) return;
155 j++;
156 chunk.add(it.next());
157 }
158 progressMonitor.setCustomText(
159 trn("({0}/{1}) Uploading {2} object...",
160 "({0}/{1}) Uploading {2} objects...",
161 chunk.size(), i, numChunks, chunk.size()));
162 processed.addAll(api.uploadDiff(chunk, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
163 }
164 } catch(OsmTransferException e) {
165 throw e;
166 } finally {
167 progressMonitor.finishTask();
168 }
169 }
170
171 /**
172 * Send the dataset to the server.
173 *
174 * @param strategy the upload strategy. Must not be null.
175 * @param primitives list of objects to send
176 * @param changeset the changeset the data is uploaded to. Must not be null.
177 * @param monitor the progress monitor. If null, assumes {@see NullProgressMonitor#INSTANCE}
178 * @throws IllegalArgumentException thrown if changeset is null
179 * @throws IllegalArgumentException thrown if strategy is null
180 * @throws OsmTransferException thrown if something goes wrong
181 */
182 public void uploadOsm(UploadStrategySpecification strategy, Collection<OsmPrimitive> primitives, Changeset changeset, ProgressMonitor monitor) throws OsmTransferException {
183 CheckParameterUtil.ensureParameterNotNull(changeset, "changeset");
184 processed = new LinkedList<OsmPrimitive>();
185 monitor = monitor == null ? NullProgressMonitor.INSTANCE : monitor;
186 monitor.beginTask(tr("Uploading data ..."));
187 try {
188 api.initialize(monitor);
189 // check whether we can use diff upload
190 if (changeset.getId() == 0) {
191 api.openChangeset(changeset,monitor.createSubTaskMonitor(0, false));
192 } else {
193 api.updateChangeset(changeset,monitor.createSubTaskMonitor(0, false));
194 }
195 api.setChangeset(changeset);
196 switch(strategy.getStrategy()) {
197 case SINGLE_REQUEST_STRATEGY:
198 uploadChangesAsDiffUpload(primitives,monitor.createSubTaskMonitor(0,false));
199 break;
200 case INDIVIDUAL_OBJECTS_STRATEGY:
201 uploadChangesIndividually(primitives,monitor.createSubTaskMonitor(0,false));
202 break;
203 case CHUNKED_DATASET_STRATEGY:
204 uploadChangesInChunks(primitives,monitor.createSubTaskMonitor(0,false), strategy.getChunkSize());
205 break;
206 }
207 } catch(OsmTransferException e) {
208 throw e;
209 } finally {
210 monitor.finishTask();
211 api.setChangeset(null);
212 }
213 }
214
215 void makeApiRequest(OsmPrimitive osm, ProgressMonitor progressMonitor) throws OsmTransferException {
216 if (osm.isDeleted()) {
217 api.deletePrimitive(osm, progressMonitor);
218 } else if (osm.isNew()) {
219 api.createPrimitive(osm, progressMonitor);
220 } else {
221 api.modifyPrimitive(osm,progressMonitor);
222 }
223 }
224
225 public void cancel() {
226 this.canceled = true;
227 if (api != null) {
228 api.cancel();
229 }
230 }
231
232 /**
233 * Replies the collection of successfully processed primitives
234 *
235 * @return the collection of successfully processed primitives
236 */
237 public Collection<OsmPrimitive> getProcessedPrimitives() {
238 return processed;
239 }
240}
Note: See TracBrowser for help on using the repository browser.