Changeset 2598 in josm for trunk/src/org
- Timestamp:
- 2009-12-09T21:24:32+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java
r2325 r2598 15 15 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTaskList; 16 16 import org.openstreetmap.josm.data.osm.DataSource; 17 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 17 18 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 18 19 import org.openstreetmap.josm.tools.Shortcut; … … 38 39 protected void updateEnabledState() { 39 40 setEnabled(getEditLayer() != null); 41 } 42 43 public void updateLayer(OsmDataLayer layer) { 44 40 45 } 41 46 -
trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java
r2578 r2598 3 3 4 4 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 5 import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull; 5 6 import static org.openstreetmap.josm.tools.I18n.tr; 6 7 7 8 import java.awt.event.ActionEvent; 8 9 import java.awt.event.KeyEvent; 9 import java.io.IOException;10 10 import java.util.Collection; 11 11 import java.util.Collections; … … 15 15 import org.openstreetmap.josm.Main; 16 16 import org.openstreetmap.josm.data.osm.DataSet; 17 import org.openstreetmap.josm.data.osm.DataSetMerger;18 import org.openstreetmap.josm.data.osm.Node;19 17 import org.openstreetmap.josm.data.osm.OsmPrimitive; 20 18 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 21 import org.openstreetmap.josm.data.osm.Relation; 22 import org.openstreetmap.josm.data.osm.Way; 19 import org.openstreetmap.josm.data.osm.PrimitiveId; 23 20 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 24 import org.openstreetmap.josm.gui. PleaseWaitRunnable;21 import org.openstreetmap.josm.gui.io.UpdatePrimitivesTask; 25 22 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 26 import org.openstreetmap.josm.gui.progress.ProgressMonitor;27 23 import org.openstreetmap.josm.io.MultiFetchServerObjectReader; 28 import org.openstreetmap.josm.io.OsmServerObjectReader;29 import org.openstreetmap.josm.io.OsmTransferException;30 24 import org.openstreetmap.josm.tools.Shortcut; 31 import org.xml.sax.SAXException;32 25 33 26 /** … … 42 35 * @param id the primitive id 43 36 */ 44 p rotectedvoid handlePrimitiveGoneException(long id, OsmPrimitiveType type) {37 public void handlePrimitiveGoneException(long id, OsmPrimitiveType type) { 45 38 MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader(); 46 39 reader.append(getCurrentDataSet(),id, type); … … 62 55 */ 63 56 public void updatePrimitives(final Collection<OsmPrimitive> selection) { 64 UpdatePrimitivesTask task = new UpdatePrimitivesTask( selection);57 UpdatePrimitivesTask task = new UpdatePrimitivesTask(Main.main.getEditLayer(),selection); 65 58 Main.worker.submit(task); 66 59 } … … 70 63 * with the data currently kept on the server. 71 64 * 72 * @param id the id of a primitive in the {@see DataSet} of the current edit layer 65 * @param id the id of a primitive in the {@see DataSet} of the current edit layer. Must not be null. 66 * @throws IllegalArgumentException thrown if id is null 73 67 * @exception IllegalStateException thrown if there is no primitive with <code>id</code> in 74 68 * the current dataset … … 76 70 * 77 71 */ 78 public void updatePrimitive(OsmPrimitiveType type, long id) throws IllegalStateException{ 72 public void updatePrimitive(PrimitiveId id) throws IllegalStateException, IllegalArgumentException{ 73 ensureParameterNotNull(id, "id"); 79 74 if (getEditLayer() == null) 80 75 throw new IllegalStateException(tr("No current dataset found")); 81 OsmPrimitive primitive = getEditLayer().data.getPrimitiveById(id , type);76 OsmPrimitive primitive = getEditLayer().data.getPrimitiveById(id); 82 77 if (primitive == null) 83 78 throw new IllegalStateException(tr("Didn''t find an object with id {0} in the current dataset", id)); … … 132 127 updatePrimitives(selection); 133 128 } 134 135 /**136 * The asynchronous task for updating the data using multi fetch.137 *138 */139 static class UpdatePrimitivesTask extends PleaseWaitRunnable {140 //static private final Logger logger = Logger.getLogger(UpdatePrimitivesTask.class.getName());141 142 private DataSet ds;143 private boolean canceled;144 private Exception lastException;145 private Collection<? extends OsmPrimitive> toUpdate;146 private MultiFetchServerObjectReader reader;147 148 /**149 *150 * @param toUpdate a collection of primitives to update from the server151 */152 public UpdatePrimitivesTask(Collection<? extends OsmPrimitive> toUpdate) {153 super(tr("Update objects"), false /* don't ignore exception*/);154 canceled = false;155 this.toUpdate = toUpdate;156 }157 158 @Override159 protected void cancel() {160 canceled = true;161 if (reader != null) {162 reader.cancel();163 }164 }165 166 @Override167 protected void finish() {168 if (canceled)169 return;170 if (lastException != null) {171 ExceptionDialogUtil.explainException(lastException);172 return;173 }174 if (ds != null && Main.main.getEditLayer() != null) {175 Main.main.getEditLayer().mergeFrom(ds);176 Main.main.getEditLayer().onPostDownloadFromServer();177 }178 }179 180 protected void initMultiFetchReaderWithNodes(MultiFetchServerObjectReader reader) {181 for (OsmPrimitive primitive : toUpdate) {182 if (primitive instanceof Node && !primitive.isNew()) {183 reader.append((Node)primitive);184 } else if (primitive instanceof Way) {185 Way way = (Way)primitive;186 for (Node node: way.getNodes()) {187 if (!node.isNew()) {188 reader.append(node);189 }190 }191 }192 }193 }194 195 protected void initMultiFetchReaderWithWays(MultiFetchServerObjectReader reader) {196 for (OsmPrimitive primitive : toUpdate) {197 if (primitive instanceof Way && !primitive.isNew()) {198 reader.append((Way)primitive);199 }200 }201 }202 203 protected void initMultiFetchReaderWithRelations(MultiFetchServerObjectReader reader) {204 for (OsmPrimitive primitive : toUpdate) {205 if (primitive instanceof Relation && !primitive.isNew()) {206 reader.append((Relation)primitive);207 }208 }209 }210 211 @Override212 protected void realRun() throws SAXException, IOException, OsmTransferException {213 progressMonitor.indeterminateSubTask("");214 this.ds = new DataSet();215 DataSet theirDataSet;216 try {217 reader = new MultiFetchServerObjectReader();218 initMultiFetchReaderWithNodes(reader);219 initMultiFetchReaderWithWays(reader);220 initMultiFetchReaderWithRelations(reader);221 theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));222 DataSetMerger merger = new DataSetMerger(ds, theirDataSet);223 merger.merge();224 // a way loaded with MultiFetch may be incomplete because at least one of its225 // nodes isn't present in the local data set. We therefore fully load all226 // incomplete ways.227 //228 for (Way w : ds.getWays()) {229 if (w.isIncomplete()) {230 OsmServerObjectReader reader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);231 theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));232 merger = new DataSetMerger(ds, theirDataSet);233 merger.merge();234 }235 }236 } catch(Exception e) {237 if (canceled)238 return;239 lastException = e;240 }241 }242 }243 129 } -
trunk/src/org/openstreetmap/josm/actions/UploadAction.java
r2569 r2598 7 7 import java.awt.event.ActionEvent; 8 8 import java.awt.event.KeyEvent; 9 import java.io.IOException;10 import java.net.HttpURLConnection;11 import java.text.SimpleDateFormat;12 import java.util.Collection;13 import java.util.Date;14 import java.util.HashSet;15 9 import java.util.LinkedList; 16 10 import java.util.logging.Logger; 17 import java.util.regex.Matcher;18 import java.util.regex.Pattern;19 11 20 12 import javax.swing.JOptionPane; … … 24 16 import org.openstreetmap.josm.actions.upload.RelationUploadOrderHook; 25 17 import org.openstreetmap.josm.actions.upload.UploadHook; 26 import org.openstreetmap.josm.actions.upload.UploadParameterHook;27 18 import org.openstreetmap.josm.data.APIDataSet; 28 19 import org.openstreetmap.josm.data.conflict.ConflictCollection; 29 import org.openstreetmap.josm.data.osm.Changeset;30 import org.openstreetmap.josm.data.osm.OsmPrimitive;31 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;32 import org.openstreetmap.josm.gui.DefaultNameFormatter;33 import org.openstreetmap.josm.gui.ExceptionDialogUtil;34 import org.openstreetmap.josm.gui.HelpAwareOptionPane;35 import org.openstreetmap.josm.gui.PleaseWaitRunnable;36 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;37 20 import org.openstreetmap.josm.gui.io.UploadDialog; 38 import org.openstreetmap.josm.gui.io.Upload StrategySpecification;21 import org.openstreetmap.josm.gui.io.UploadPrimitivesTask; 39 22 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 40 import org.openstreetmap.josm.gui.progress.ProgressMonitor;41 import org.openstreetmap.josm.io.ChangesetClosedException;42 import org.openstreetmap.josm.io.OsmApi;43 import org.openstreetmap.josm.io.OsmApiException;44 import org.openstreetmap.josm.io.OsmApiInitializationException;45 import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;46 import org.openstreetmap.josm.io.OsmServerWriter;47 import org.openstreetmap.josm.io.OsmTransferException;48 import org.openstreetmap.josm.tools.DateUtils;49 import org.openstreetmap.josm.tools.ImageProvider;50 23 import org.openstreetmap.josm.tools.Shortcut; 51 import org.xml.sax.SAXException;52 24 53 25 /** … … 84 56 */ 85 57 uploadHooks.add(new RelationUploadOrderHook()); 86 87 /**88 * Displays a screen where the actions that would be taken are displayed and89 * give the user the possibility to cancel the upload.90 */91 uploadHooks.add(new UploadParameterHook());92 58 } 93 59 … … 168 134 if (!checkPreUploadConditions(layer, apiData)) 169 135 return; 136 137 final UploadDialog dialog = UploadDialog.getUploadDialog(); 138 dialog.setUploadedPrimitives(apiData); 139 dialog.setVisible(true); 140 if (dialog.isCanceled()) 141 return; 142 dialog.rememberUserInput(); 143 170 144 Main.worker.execute( 171 145 new UploadPrimitivesTask( 172 146 UploadDialog.getUploadDialog().getUploadStrategySpecification(), 173 147 layer, 174 apiData.getPrimitives(), 175 UploadDialog.getUploadDialog().getChangeset(), 176 UploadDialog.getUploadDialog().isDoCloseAfterUpload() 148 apiData, 149 UploadDialog.getUploadDialog().getChangeset() 177 150 ) 178 151 ); … … 194 167 uploadData(Main.map.mapView.getEditLayer(), apiData); 195 168 } 196 197 /**198 * Synchronizes the local state of an {@see OsmPrimitive} with its state on the199 * server. The method uses an individual GET for the primitive.200 *201 * @param id the primitive ID202 */203 protected void synchronizePrimitive(final OsmPrimitiveType type, final long id) {204 Main.worker.execute(new UpdatePrimitiveTask(type, id));205 }206 207 /**208 * Synchronizes the local state of the dataset with the state on the server.209 *210 * Reuses the functionality of {@see UpdateDataAction}.211 *212 * @see UpdateDataAction#actionPerformed(ActionEvent)213 */214 protected void synchronizeDataSet() {215 UpdateDataAction act = new UpdateDataAction();216 act.actionPerformed(new ActionEvent(this,0,""));217 }218 219 /**220 * Handles the case that a conflict in a specific {@see OsmPrimitive} was detected while221 * uploading222 *223 * @param primitiveType the type of the primitive, either <code>node</code>, <code>way</code> or224 * <code>relation</code>225 * @param id the id of the primitive226 * @param serverVersion the version of the primitive on the server227 * @param myVersion the version of the primitive in the local dataset228 */229 protected void handleUploadConflictForKnownConflict(final OsmPrimitiveType primitiveType, final long id, String serverVersion, String myVersion) {230 String lbl = "";231 switch(primitiveType) {232 case NODE: lbl = tr("Synchronize node {0} only", id); break;233 case WAY: lbl = tr("Synchronize way {0} only", id); break;234 case RELATION: lbl = tr("Synchronize relation {0} only", id); break;235 }236 ButtonSpec[] spec = new ButtonSpec[] {237 new ButtonSpec(238 lbl,239 ImageProvider.get("updatedata"),240 null,241 null242 ),243 new ButtonSpec(244 tr("Synchronize entire dataset"),245 ImageProvider.get("updatedata"),246 null,247 null248 ),249 new ButtonSpec(250 tr("Cancel"),251 ImageProvider.get("cancel"),252 null,253 null254 )255 };256 String msg = tr("<html>Uploading <strong>failed</strong> because the server has a newer version of one<br>"257 + "of your nodes, ways, or relations.<br>"258 + "The conflict is caused by the <strong>{0}</strong> with id <strong>{1}</strong>,<br>"259 + "the server has version {2}, your version is {3}.<br>"260 + "<br>"261 + "Click <strong>{4}</strong> to synchronize the conflicting primitive only.<br>"262 + "Click <strong>{5}</strong> to synchronize the entire local dataset with the server.<br>"263 + "Click <strong>{6}</strong> to abort and continue editing.<br></html>",264 tr(primitiveType.getAPIName()), id, serverVersion, myVersion,265 spec[0].text, spec[1].text, spec[2].text266 );267 int ret = HelpAwareOptionPane.showOptionDialog(268 Main.parent,269 msg,270 tr("Conflicts detected"),271 JOptionPane.ERROR_MESSAGE,272 null,273 spec,274 spec[0],275 "/Concepts/Conflict"276 );277 switch(ret) {278 case 0: synchronizePrimitive(primitiveType, id); break;279 case 1: synchronizeDataSet(); break;280 default: return;281 }282 }283 284 /**285 * Handles the case that a conflict was detected while uploading where we don't286 * know what {@see OsmPrimitive} actually caused the conflict (for whatever reason)287 *288 */289 protected void handleUploadConflictForUnknownConflict() {290 ButtonSpec[] spec = new ButtonSpec[] {291 new ButtonSpec(292 tr("Synchronize entire dataset"),293 ImageProvider.get("updatedata"),294 null,295 null296 ),297 new ButtonSpec(298 tr("Cancel"),299 ImageProvider.get("cancel"),300 null,301 null302 )303 };304 String msg = tr("<html>Uploading <strong>failed</strong> because the server has a newer version of one<br>"305 + "of your nodes, ways, or relations.<br>"306 + "<br>"307 + "Click <strong>{0}</strong> to synchronize the entire local dataset with the server.<br>"308 + "Click <strong>{1}</strong> to abort and continue editing.<br></html>",309 spec[0].text, spec[1].text310 );311 int ret = HelpAwareOptionPane.showOptionDialog(312 Main.parent,313 msg,314 tr("Conflicts detected"),315 JOptionPane.ERROR_MESSAGE,316 null,317 spec,318 spec[0],319 "Concepts/Conflict"320 );321 if (ret == 0) {322 synchronizeDataSet();323 }324 }325 326 /**327 * Handles the case that a conflict was detected while uploading where we don't328 * know what {@see OsmPrimitive} actually caused the conflict (for whatever reason)329 *330 */331 protected void handleUploadConflictForClosedChangeset(long changsetId, Date d) {332 String msg = tr("<html>Uploading <strong>failed</strong> because you''ve been using<br>"333 + "changeset {0} which was already closed at {1}.<br>"334 + "Please upload again with a new or an existing open changeset.</html>",335 changsetId, new SimpleDateFormat().format(d)336 );337 JOptionPane.showMessageDialog(338 Main.parent,339 msg,340 tr("Changeset closed"),341 JOptionPane.ERROR_MESSAGE342 );343 }344 345 /**346 * Handles the case where deleting a node failed because it is still in use in347 * a non-deleted way on the server.348 */349 protected void handleUploadConflictForNodeStillInUse(long nodeId, long wayId) {350 ButtonSpec[] options = new ButtonSpec[] {351 new ButtonSpec(352 tr("Prepare conflict resolution"),353 ImageProvider.get("ok"),354 tr("Click to download all parent ways for node {0}", nodeId),355 null /* no specific help context */356 ),357 new ButtonSpec(358 tr("Cancel"),359 ImageProvider.get("cancel"),360 tr("Click to cancel and to resume editing the map", nodeId),361 null /* no specific help context */362 )363 };364 String msg = tr("<html>Uploading <strong>failed</strong> because you tried "365 + "to delete node {0} which is still in use in way {1}.<br><br>"366 + "Click <strong>{2}</strong> to download all parent ways of node {0}.<br>"367 + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog."368 + "</html>",369 nodeId, wayId, options[0].text370 );371 372 int ret = HelpAwareOptionPane.showOptionDialog(373 Main.parent,374 msg,375 tr("Node still in use"),376 JOptionPane.ERROR_MESSAGE,377 null,378 options,379 options[0],380 "/Action/Upload#NodeStillInUseInWay"381 );382 if (ret != 0) return;383 DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), nodeId, OsmPrimitiveType.NODE);384 }385 386 /**387 * handles an upload conflict, i.e. an error indicated by a HTTP return code 409.388 *389 * @param e the exception390 */391 protected void handleUploadConflict(OsmApiException e) {392 String pattern = "Version mismatch: Provided (\\d+), server had: (\\d+) of (\\S+) (\\d+)";393 Pattern p = Pattern.compile(pattern);394 Matcher m = p.matcher(e.getErrorHeader());395 if (m.matches()) {396 handleUploadConflictForKnownConflict(OsmPrimitiveType.from(m.group(3)), Long.parseLong(m.group(4)), m.group(2),m.group(1));397 return;398 }399 pattern ="The changeset (\\d+) was closed at (.*)";400 p = Pattern.compile(pattern);401 m = p.matcher(e.getErrorHeader());402 if (m.matches()) {403 handleUploadConflictForClosedChangeset(Long.parseLong(m.group(1)), DateUtils.fromString(m.group(2)));404 return;405 }406 pattern = "Node (\\d+) is still used by way (\\d+).";407 p = Pattern.compile(pattern);408 m = p.matcher(e.getErrorHeader());409 if (m.matches()) {410 handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));411 return;412 }413 logger.warning(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));414 handleUploadConflictForUnknownConflict();415 }416 417 /**418 * handles an precondition failed conflict, i.e. an error indicated by a HTTP return code 412.419 *420 * @param e the exception421 */422 protected void handlePreconditionFailed(OsmApiException e) {423 String pattern = "Precondition failed: Node (\\d+) is still used by way (\\d+).";424 Pattern p = Pattern.compile(pattern);425 Matcher m = p.matcher(e.getErrorHeader());426 if (m.matches()) {427 handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));428 return;429 }430 logger.warning(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));431 ExceptionDialogUtil.explainPreconditionFailed(e);432 }433 434 /**435 * Handles an error due to a delete request on an already deleted436 * {@see OsmPrimitive}, i.e. a HTTP response code 410, where we know what437 * {@see OsmPrimitive} is responsible for the error.438 *439 * Reuses functionality of the {@see UpdateSelectionAction} to resolve440 * conflicts due to mismatches in the deleted state.441 *442 * @param primitiveType the type of the primitive443 * @param id the id of the primitive444 *445 * @see UpdateSelectionAction#handlePrimitiveGoneException(long)446 */447 protected void handleGoneForKnownPrimitive(OsmPrimitiveType primitiveType, long id) {448 UpdateSelectionAction act = new UpdateSelectionAction();449 act.handlePrimitiveGoneException(id,primitiveType);450 }451 452 /**453 * Handles an error which is caused by a delete request for an already deleted454 * {@see OsmPrimitive} on the server, i.e. a HTTP response code of 410.455 * Note that an <strong>update</strong> on an already deleted object results456 * in a 409, not a 410.457 *458 * @param e the exception459 */460 protected void handleGone(OsmApiPrimitiveGoneException e) {461 if (e.isKnownPrimitive()) {462 handleGoneForKnownPrimitive(e.getPrimitiveType(), e.getPrimitiveId());463 } else {464 ExceptionDialogUtil.explainGoneForUnknownPrimitive(e);465 }466 }467 468 /**469 * error handler for any exception thrown during upload470 *471 * @param e the exception472 */473 protected void handleFailedUpload(Exception e) {474 // API initialization failed. Notify the user and return.475 //476 if (e instanceof OsmApiInitializationException) {477 ExceptionDialogUtil.explainOsmApiInitializationException((OsmApiInitializationException)e);478 return;479 }480 481 if (e instanceof OsmApiPrimitiveGoneException) {482 handleGone((OsmApiPrimitiveGoneException)e);483 return;484 }485 if (e instanceof OsmApiException) {486 OsmApiException ex = (OsmApiException)e;487 // There was an upload conflict. Let the user decide whether488 // and how to resolve it489 //490 if(ex.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {491 handleUploadConflict(ex);492 return;493 }494 // There was a precondition failed. Notify the user.495 //496 else if (ex.getResponseCode() == HttpURLConnection.HTTP_PRECON_FAILED) {497 handlePreconditionFailed(ex);498 return;499 }500 // Tried to update or delete a primitive which never existed on501 // the server?502 //503 else if (ex.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {504 ExceptionDialogUtil.explainNotFound(ex);505 return;506 }507 }508 509 ExceptionDialogUtil.explainException(e);510 }511 512 /**513 * The asynchronous task to update a specific id514 *515 */516 class UpdatePrimitiveTask extends PleaseWaitRunnable {517 518 private boolean uploadCancelled = false;519 private boolean uploadFailed = false;520 private Exception lastException = null;521 private long id;522 private OsmPrimitiveType type;523 524 public UpdatePrimitiveTask(OsmPrimitiveType type, long id) {525 super(tr("Updating primitive"),false /* don't ignore exceptions */);526 this.id = id;527 this.type = type;528 }529 530 @Override protected void realRun() throws SAXException, IOException {531 try {532 UpdateSelectionAction act = new UpdateSelectionAction();533 act.updatePrimitive(type, id);534 } catch (Exception sxe) {535 if (uploadCancelled) {536 System.out.println("Ignoring exception caught because upload is canceled. Exception is: " + sxe.toString());537 return;538 }539 uploadFailed = true;540 lastException = sxe;541 }542 }543 544 @Override protected void finish() {545 if (uploadFailed) {546 handleFailedUpload(lastException);547 }548 }549 550 @Override protected void cancel() {551 OsmApi.getOsmApi().cancel();552 uploadCancelled = true;553 }554 }555 556 /**557 * The task for uploading a collection of primitives558 *559 */560 public class UploadPrimitivesTask extends PleaseWaitRunnable {561 private boolean uploadCancelled = false;562 private Exception lastException = null;563 private Collection <OsmPrimitive> toUpload;564 private OsmServerWriter writer;565 private OsmDataLayer layer;566 private Changeset changeset;567 private boolean closeChangesetAfterUpload;568 private HashSet<OsmPrimitive> processedPrimitives;569 private UploadStrategySpecification strategy;570 571 /**572 * Creates the task573 * @param strategy the upload strategy574 * @param layer the OSM data layer for which data is uploaded575 * @param toUpload the collection of primitives to upload576 * @param changeset the changeset to use for uploading577 * @param closeChangesetAfterUpload true, if the changeset is to be closed after uploading578 */579 private UploadPrimitivesTask(UploadStrategySpecification strategy, OsmDataLayer layer, Collection <OsmPrimitive> toUpload, Changeset changeset, boolean closeChangesetAfterUpload) {580 super(tr("Uploading data for layer ''{0}''", layer.getName()),false /* don't ignore exceptions */);581 this.toUpload = toUpload;582 this.layer = layer;583 this.changeset = changeset;584 this.strategy = strategy;585 this.closeChangesetAfterUpload = closeChangesetAfterUpload;586 this.processedPrimitives = new HashSet<OsmPrimitive>();587 }588 589 protected OsmPrimitive getPrimitive(OsmPrimitiveType type, long id) {590 for (OsmPrimitive p: toUpload) {591 if (OsmPrimitiveType.from(p).equals(type) && p.getId() == id)592 return p;593 }594 return null;595 }596 597 /**598 * Retries to recover the upload operation from an exception which was thrown because599 * an uploaded primitive was already deleted on the server.600 *601 * @param e the exception throw by the API602 * @param monitor a progress monitor603 * @throws OsmTransferException thrown if we can't recover from the exception604 */605 protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor) throws OsmTransferException{606 if (!e.isKnownPrimitive()) throw e;607 OsmPrimitive p = getPrimitive(e.getPrimitiveType(), e.getPrimitiveId());608 if (p == null) throw e;609 if (p.isDeleted()) {610 // we tried to delete an already deleted primitive.611 //612 System.out.println(tr("Warning: object ''{0}'' is already deleted on the server. Skipping this object and retrying to upload.", p.getDisplayName(DefaultNameFormatter.getInstance())));613 monitor.appendLogMessage(tr("Object ''{0}'' is already deleted. Skipping object in upload.",p.getDisplayName(DefaultNameFormatter.getInstance())));614 processedPrimitives.addAll(writer.getProcessedPrimitives());615 processedPrimitives.add(p);616 toUpload.removeAll(processedPrimitives);617 return;618 }619 // exception was thrown because we tried to *update* an already deleted620 // primitive. We can't resolve this automatically. Re-throw exception,621 // a conflict is going to be created later.622 throw e;623 }624 625 @Override protected void realRun() throws SAXException, IOException {626 writer = new OsmServerWriter();627 try {628 while(true) {629 try {630 getProgressMonitor().subTask(tr("Uploading {0} objects ...", toUpload.size()));631 writer.uploadOsm(strategy, toUpload, changeset, getProgressMonitor().createSubTaskMonitor(1, false));632 processedPrimitives.addAll(writer.getProcessedPrimitives());633 // if we get here we've successfully uploaded the data. Exit the loop.634 //635 break;636 } catch(OsmApiPrimitiveGoneException e) {637 // try to recover from the 410 Gone638 recoverFromGoneOnServer(e, getProgressMonitor());639 }640 }641 // if required close the changeset642 //643 if (closeChangesetAfterUpload) {644 if (changeset != null && changeset.getId() > 0) {645 OsmApi.getOsmApi().closeChangeset(changeset, progressMonitor.createSubTaskMonitor(0,false));646 }647 }648 } catch (Exception e) {649 if (uploadCancelled) {650 System.out.println(tr("Ignoring caught exception because upload is canceled. Exception is: {0}", e.toString()));651 return;652 }653 lastException = e;654 }655 }656 657 @Override protected void finish() {658 if (uploadCancelled)659 return;660 661 // we always clean up the data, even in case of errors. It's possible the data was662 // partially uploaded663 //664 layer.cleanupAfterUpload(processedPrimitives);665 layer.fireDataChange();666 if (lastException != null) {667 handleFailedUpload(lastException);668 }669 layer.onPostUploadToServer();670 if (lastException != null && lastException instanceof ChangesetClosedException) {671 UploadDialog.getUploadDialog().removeChangeset(changeset);672 } else {673 UploadDialog.getUploadDialog().setOrUpdateChangeset(changeset);674 }675 }676 677 @Override protected void cancel() {678 uploadCancelled = true;679 if (writer != null) {680 writer.cancel();681 }682 }683 }684 169 } -
trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java
r2569 r2598 23 23 OsmApi api = OsmApi.getOsmApi(); 24 24 try { 25 // FIXME: this should run asynchronously and a progress monitor 26 // should be displayed. 25 27 api.initialize(NullProgressMonitor.INSTANCE); 26 28 long maxNodes = 0; … … 28 30 maxNodes = api.getCapabilities().getLong("waynodes","maximum"); 29 31 } 30 long maxElements = 0;31 if (api.getCapabilities().isDefined("changesets", "maximum_elements")) {32 maxElements = api.getCapabilities().getLong("changesets", "maximum_elements");33 }34 35 32 if (maxNodes > 0) { 36 33 if( !checkMaxNodes(apiData.getPrimitivesToAdd(), maxNodes)) … … 40 37 if( !checkMaxNodes(apiData.getPrimitivesToDelete(), maxNodes)) 41 38 return false; 42 }43 44 if (maxElements > 0) {45 int total = 0;46 total = apiData.getPrimitivesToAdd().size() + apiData.getPrimitivesToUpdate().size() + apiData.getPrimitivesToDelete().size();47 if(total > maxElements) {48 JOptionPane.showMessageDialog(49 Main.parent,50 tr("Current number of changes exceeds the max. number of changes, current is {0}, max is {1}",51 total,52 maxElements53 ),54 tr("API Capabilities Violation"),55 JOptionPane.ERROR_MESSAGE56 );57 return false;58 }59 39 } 60 40 } catch (OsmApiInitializationException e) { -
trunk/src/org/openstreetmap/josm/data/APIDataSet.java
r2512 r2598 14 14 import java.util.logging.Logger; 15 15 16 import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException; 16 17 import org.openstreetmap.josm.data.osm.DataSet; 17 18 import org.openstreetmap.josm.data.osm.Node; … … 21 22 import org.openstreetmap.josm.data.osm.Way; 22 23 23 import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;24 25 24 /** 26 25 * Represents a collection of {@see OsmPrimitive}s which should be uploaded to the 27 26 * API. 28 * The collection is derived from the modified primitives of an {@see DataSet}. 27 * The collection is derived from the modified primitives of an {@see DataSet} and it provides methods 28 * for sorting the objects in upload order. 29 29 * 30 30 */ … … 212 212 213 213 /** 214 * Replies the number of objects to upload 215 * 216 * @return the number of objects to upload 217 */ 218 public int getSize() { 219 return toAdd.size() + toUpdate.size() + toDelete.size(); 220 } 221 222 public void removeProcessed(Collection<OsmPrimitive> processed) { 223 if (processed == null) return; 224 toAdd.removeAll(processed); 225 toUpdate.removeAll(processed); 226 toDelete.removeAll(processed); 227 } 228 229 /** 214 230 * Adjusts the upload order for new relations. Child relations are uploaded first, 215 231 * parent relations second. -
trunk/src/org/openstreetmap/josm/data/osm/Changeset.java
r2512 r2598 1 1 // License: GPL. Copyright 2007 by Martijn van Oosterhout and others 2 2 package org.openstreetmap.josm.data.osm; 3 4 import static org.openstreetmap.josm.tools.I18n.tr;5 3 6 4 import java.util.Collection; … … 100 98 } 101 99 102 public String getLocalName(){103 return tr("Changeset {0}",getId());104 }105 106 100 public String getDisplayName(NameFormatter formatter) { 107 101 return formatter.format(this); … … 308 302 return tags.keySet(); 309 303 } 304 305 public boolean isNew() { 306 return id <= 0; 307 } 310 308 } -
trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java
r2512 r2598 173 173 } 174 174 175 public boolean isNew() { 176 return id <= 0; 177 } 175 178 } -
trunk/src/org/openstreetmap/josm/data/osm/PrimitiveId.java
r2399 r2598 5 5 6 6 long getUniqueId(); 7 8 7 OsmPrimitiveType getType(); 9 8 9 /** 10 * Replies true if this id represents a new primitive. 11 * 12 * @return true if this id represents a new primitive. 13 */ 14 boolean isNew(); 15 10 16 } -
trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java
r2399 r2598 171 171 return member.getUniqueId(); 172 172 } 173 174 public boolean isNew() { 175 return member.isNew(); 176 } 173 177 } -
trunk/src/org/openstreetmap/josm/data/osm/RelationMemberData.java
r2404 r2598 51 51 } 52 52 53 public boolean isNew() { 54 return memberId <= 0; 55 } 53 56 } -
trunk/src/org/openstreetmap/josm/data/osm/SimplePrimitiveId.java
r2448 r2598 18 18 public long getUniqueId() { 19 19 return id; 20 } 21 22 public boolean isNew() { 23 return id <= 0; 20 24 } 21 25 -
trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java
r2512 r2598 59 59 tr("Error"), 60 60 JOptionPane.ERROR_MESSAGE, 61 ht("/ ErrorMessages#ChangesetClosedException")61 ht("/Action/Upload#ChangesetClosed") 62 62 ); 63 63 }
Note:
See TracChangeset
for help on using the changeset viewer.