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

Last change on this file since 2474 was 2273, checked in by jttt, 15 years ago

Replace testing for id <= 0 with isNew() method

  • Property svn:eol-style set to native
File size: 8.5 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;
6
7import java.util.Collection;
8import java.util.LinkedList;
9import java.util.logging.Logger;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.data.osm.Changeset;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
15import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
16import org.openstreetmap.josm.gui.progress.ProgressMonitor;
17
18/**
19 * Class that uploads all changes to the osm server.
20 *
21 * This is done like this: - All objects with id = 0 are uploaded as new, except
22 * those in deleted, which are ignored - All objects in deleted list are
23 * deleted. - All remaining objects with modified flag set are updated.
24 */
25public class OsmServerWriter {
26 static private final Logger logger = Logger.getLogger(OsmServerWriter.class.getName());
27
28 /**
29 * This list contains all successfully processed objects. The caller of
30 * upload* has to check this after the call and update its dataset.
31 *
32 * If a server connection error occurs, this may contain fewer entries
33 * than where passed in the list to upload*.
34 */
35 private Collection<OsmPrimitive> processed;
36
37 private OsmApi api = OsmApi.getOsmApi();
38
39 private static final int MSECS_PER_SECOND = 1000;
40 private static final int SECONDS_PER_MINUTE = 60;
41 private static final int MSECS_PER_MINUTE = MSECS_PER_SECOND * SECONDS_PER_MINUTE;
42
43 long uploadStartTime;
44
45 public String timeLeft(int progress, int list_size) {
46 long now = System.currentTimeMillis();
47 long elapsed = now - uploadStartTime;
48 if (elapsed == 0) {
49 elapsed = 1;
50 }
51 float uploads_per_ms = (float)progress / elapsed;
52 float uploads_left = list_size - progress;
53 int ms_left = (int)(uploads_left / uploads_per_ms);
54 int minutes_left = ms_left / MSECS_PER_MINUTE;
55 int seconds_left = (ms_left / MSECS_PER_SECOND) % SECONDS_PER_MINUTE ;
56 String time_left_str = Integer.toString(minutes_left) + ":";
57 if (seconds_left < 10) {
58 time_left_str += "0";
59 }
60 time_left_str += Integer.toString(seconds_left);
61 return time_left_str;
62 }
63
64 /**
65 * Uploads the changes individually. Invokes one API call per uploaded primitmive.
66 *
67 * @param primitives the collection of primitives to upload
68 * @param progressMonitor the progress monitor
69 * @throws OsmTransferException thrown if an exception occurs
70 */
71 protected void uploadChangesIndividually(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
72 try {
73 progressMonitor.beginTask(tr("Starting to upload with one request per primitive ..."));
74 progressMonitor.setTicksCount(primitives.size());
75 uploadStartTime = System.currentTimeMillis();
76 for (OsmPrimitive osm : primitives) {
77 int progress = progressMonitor.getTicks();
78 String time_left_str = timeLeft(progress, primitives.size());
79 String msg = "";
80 switch(OsmPrimitiveType.from(osm)) {
81 case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
82 case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
83 case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
84 }
85 progressMonitor.subTask(
86 tr(msg,
87 Math.round(100.0*progress/primitives.size()),
88 progress,
89 primitives.size(),
90 time_left_str,
91 osm.getName() == null ? osm.getId() : osm.getName(),
92 osm.getId()));
93 makeApiRequest(osm,progressMonitor);
94 processed.add(osm);
95 progressMonitor.worked(1);
96 }
97 } catch(OsmTransferException e) {
98 throw e;
99 } catch(Exception e) {
100 throw new OsmTransferException(e);
101 } finally {
102 progressMonitor.finishTask();
103 }
104 }
105
106 /**
107 * Upload all changes in one diff upload
108 *
109 * @param primitives the collection of primitives to upload
110 * @param progressMonitor the progress monitor
111 * @throws OsmTransferException thrown if an exception occurs
112 */
113 protected void uploadChangesAsDiffUpload(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
114 try {
115 progressMonitor.beginTask(tr("Starting to upload in one request ..."));
116 processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
117 } catch(OsmTransferException e) {
118 throw e;
119 } catch(Exception e) {
120 throw new OsmTransferException(e);
121 } finally {
122 progressMonitor.finishTask();
123 }
124 }
125
126 /**
127 * Send the dataset to the server.
128 *
129 * @param apiVersion version of the data set
130 * @param primitives list of objects to send
131 * @param changeset the changeset the data is uploaded to. Must not be null.
132 * @param monitor the progress monitor. If null, assumes {@see NullProgressMonitor#INSTANCE}
133 * @throws IllegalArgumentException thrown if changeset is null
134 * @throws OsmTransferException thrown if something goes wrong
135 */
136 public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives, Changeset changeset, ProgressMonitor monitor) throws OsmTransferException {
137 if (changeset == null)
138 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "changeset"));
139 processed = new LinkedList<OsmPrimitive>();
140 monitor = monitor == null ? NullProgressMonitor.INSTANCE : monitor;
141 monitor.beginTask(tr("Uploading data ..."));
142 try {
143 api.initialize(monitor);
144 // check whether we can use diff upload
145 //
146 boolean canUseDiffUpload = api.hasSupportForDiffUploads();
147 if (apiVersion == null) {
148 System.out.println(tr("WARNING: no API version defined for data to upload. Falling back to version 0.6"));
149 apiVersion = "0.6";
150 }
151 boolean useDiffUpload = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0);
152 if (useDiffUpload && ! canUseDiffUpload) {
153 System.out.println(tr("WARNING: preference ''{0}'' or API version ''{1}'' of dataset requires to use diff uploads, but API is not able to handle them. Ignoring diff upload.", "osm-server.atomic-upload", apiVersion));
154 useDiffUpload = false;
155 }
156 if (changeset.getId() == 0) {
157 api.openChangeset(changeset,monitor.createSubTaskMonitor(0, false));
158 } else {
159 api.updateChangeset(changeset,monitor.createSubTaskMonitor(0, false));
160 }
161 api.setChangeset(changeset);
162 if (useDiffUpload) {
163 uploadChangesAsDiffUpload(primitives,monitor.createSubTaskMonitor(0,false));
164 } else {
165 uploadChangesIndividually(primitives,monitor.createSubTaskMonitor(0,false));
166 }
167 } catch(OsmTransferException e) {
168 throw e;
169 } catch(Exception e) {
170 throw new OsmTransferException(e);
171 } finally {
172 monitor.finishTask();
173 api.setChangeset(null);
174 }
175 }
176
177 void makeApiRequest(OsmPrimitive osm, ProgressMonitor progressMonitor) throws OsmTransferException {
178 if (osm.isDeleted()) {
179 api.deletePrimitive(osm, progressMonitor);
180 } else if (osm.isNew()) {
181 api.createPrimitive(osm, progressMonitor);
182 } else {
183 api.modifyPrimitive(osm,progressMonitor);
184 }
185 }
186
187 public void cancel() {
188 if (api != null) {
189 api.cancel();
190 }
191 }
192
193 /**
194 * Replies the collection of successfully processed primitives
195 *
196 * @return the collection of successfully processed primitives
197 */
198 public Collection<OsmPrimitive> getProcessedPrimitives() {
199 return processed;
200 }
201}
Note: See TracBrowser for help on using the repository browser.