Ignore:
Timestamp:
2009-09-27T16:29:21+02:00 (15 years ago)
Author:
Gubaer
Message:

fixed #3249: Resolve conflicts between invisible and deleted primitives automatically

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/io/UploadLayerTask.java

    r2181 r2198  
    55
    66import java.util.Collection;
     7import java.util.HashSet;
    78
     9import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;
    810import org.openstreetmap.josm.data.APIDataSet;
    911import org.openstreetmap.josm.data.osm.Changeset;
    1012import org.openstreetmap.josm.data.osm.DataSet;
    1113import org.openstreetmap.josm.data.osm.OsmPrimitive;
     14import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     15import org.openstreetmap.josm.gui.DefaultNameFormatter;
    1216import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    1317import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    1418import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    15 import org.openstreetmap.josm.io.ChangesetProcessingType;
     19import org.openstreetmap.josm.io.OsmApi;
     20import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
    1621import org.openstreetmap.josm.io.OsmServerWriter;
     22import org.openstreetmap.josm.io.OsmTransferException;
    1723
    1824/**
     
    3743    private Changeset changeset;
    3844    private boolean closeChangesetAfterUpload;
     45    private Collection<OsmPrimitive> toUpload;
     46    private HashSet<OsmPrimitive> processedPrimitives;
    3947
    4048    /**
     
    4250     * @param layer the layer. Must not be null.
    4351     * @param monitor  a progress monitor. If monitor is null, uses {@see NullProgressMonitor#INSTANCE}
    44      * @param changeset the changeset to be used if <code>changesetProcessingType</code> indicates that a new
    45      *   changeset is to be used
     52     * @param changeset the changeset to be used
    4653     * @param closeChangesetAfterUpload true, if the changeset should be closed after the upload
    4754     * @throws IllegalArgumentException thrown, if layer is null
     
    5764        this.changeset = changeset;
    5865        this.closeChangesetAfterUpload = closeChangesetAfterUpload;
     66        processedPrimitives = new HashSet<OsmPrimitive>();
     67    }
     68
     69    protected OsmPrimitive getPrimitive(OsmPrimitiveType type, long id) {
     70        for (OsmPrimitive p: toUpload) {
     71            if (OsmPrimitiveType.from(p).equals(type) && p.getId() == id)
     72                return p;
     73        }
     74        return null;
     75    }
     76
     77    /**
     78     * Retries to recover the upload operation from an exception which was thrown because
     79     * an uploaded primitive was already deleted on the server.
     80     *
     81     * @param e the exception throw by the API
     82     * @param monitor a progress monitor
     83     * @throws OsmTransferException  thrown if we can't recover from the exception
     84     */
     85    protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor) throws OsmTransferException{
     86        if (!e.isKnownPrimitive()) throw e;
     87        OsmPrimitive p = getPrimitive(e.getPrimitiveType(), e.getPrimitiveId());
     88        if (p == null) throw e;
     89        if (p.isDeleted()) {
     90            // we tried to delete an already deleted primitive.
     91            //
     92            System.out.println(tr("Warning: primitive ''{0}'' is already deleted on the server. Skipping this primitive and retrying to upload.", p.getDisplayName(DefaultNameFormatter.getInstance())));
     93            processedPrimitives.addAll(writer.getProcessedPrimitives());
     94            processedPrimitives.add(p);
     95            toUpload.removeAll(processedPrimitives);
     96            return;
     97        }
     98        // exception was thrown because we tried to *update* an already deleted
     99        // primitive. We can't resolve this automatically. Re-throw exception,
     100        // a conflict is going to be created later.
     101        throw e;
    59102    }
    60103
     
    62105    public void run() {
    63106        monitor.subTask(tr("Preparing primitives to upload ..."));
    64         Collection<OsmPrimitive> toUpload = new APIDataSet(layer.data).getPrimitives();
     107        APIDataSet ds = new APIDataSet(layer.data);
     108        try {
     109            ds.adjustRelationUploadOrder();
     110        } catch(CyclicUploadDependencyException e) {
     111            setLastException(e);
     112            return;
     113        }
     114        toUpload = ds.getPrimitives();
    65115        if (toUpload.isEmpty())
    66116            return;
    67117        writer = new OsmServerWriter();
    68118        try {
    69             ProgressMonitor m = monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
    70             if (isCancelled()) return;
    71             writer.uploadOsm(layer.data.version, toUpload, changeset, closeChangesetAfterUpload, m);
     119            while(true) {
     120                try {
     121                    ProgressMonitor m = monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
     122                    if (isCancelled()) return;
     123                    writer.uploadOsm(layer.data.version, toUpload, changeset, m);
     124                    processedPrimitives.addAll(writer.getProcessedPrimitives());
     125                    break;
     126                } catch(OsmApiPrimitiveGoneException e) {
     127                    recoverFromGoneOnServer(e, monitor);
     128                }
     129            }
     130            if (closeChangesetAfterUpload) {
     131                if (changeset != null && changeset.getId() > 0) {
     132                    OsmApi.getOsmApi().closeChangeset(changeset, monitor.createSubTaskMonitor(0, false));
     133                }
     134            }
    72135        } catch (Exception sxe) {
    73136            if (isCancelled()) {
     
    80143        if (isCancelled())
    81144            return;
    82         layer.cleanupAfterUpload(writer.getProcessedPrimitives());
     145        layer.cleanupAfterUpload(processedPrimitives);
    83146        DataSet.fireSelectionChanged(layer.data.getSelected());
    84147        layer.fireDataChange();
    85148        layer.onPostUploadToServer();
     149
     150        // don't process exceptions remembered with setLastException().
     151        // Caller is supposed to deal with them.
    86152    }
    87153
    88154    @Override
    89155    public void cancel() {
    90         // make sure the the softCancel operation is serialized with
    91         // blocks which can be interrupted.
    92156        setCancelled(true);
    93157        if (writer != null) {
Note: See TracChangeset for help on using the changeset viewer.