Changeset 3055 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2010-02-27T16:31:10+01:00 (15 years ago)
Author:
jttt
Message:

In DeleteCommand remove references first and then do the deleting (to prevent delete referenced inconsistency problem while command is being executed)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r2844 r3055  
    22package org.openstreetmap.josm.command;
    33
     4import static org.openstreetmap.josm.tools.I18n.marktr;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    56import static org.openstreetmap.josm.tools.I18n.trn;
    6 import static org.openstreetmap.josm.tools.I18n.marktr;
    77
    88import java.awt.GridBagLayout;
     
    1111import java.util.Collection;
    1212import java.util.Collections;
     13import java.util.HashMap;
    1314import java.util.HashSet;
    1415import java.util.Iterator;
    1516import java.util.LinkedList;
    1617import java.util.List;
     18import java.util.Map;
    1719import java.util.Set;
     20import java.util.Map.Entry;
    1821
    1922import javax.swing.JLabel;
     
    2831import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2932import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     33import org.openstreetmap.josm.data.osm.PrimitiveData;
    3034import org.openstreetmap.josm.data.osm.Relation;
    3135import org.openstreetmap.josm.data.osm.RelationToChildReference;
     
    4852     */
    4953    private final Collection<? extends OsmPrimitive> toDelete;
     54    private final Map<OsmPrimitive, PrimitiveData> clonedPrimitives = new HashMap<OsmPrimitive, PrimitiveData>();
    5055
    5156    /**
     
    107112    }
    108113
    109     protected void removeNewNodesFromDeletedWay(Way w) {
    110         // #2707: ways to be deleted can include new nodes (with node.id == 0).
    111         // Remove them from the way before the way is deleted. Otherwise the
    112         // deleted way is saved (or sent to the API) with a dangling reference to a node
    113         // Example:
    114         // <node id='2' action='delete' visible='true' version='1' ... />
    115         // <node id='1' action='delete' visible='true' version='1' ... />
    116         // <!-- missing node with id -1 because new deleted nodes are not persisted -->
    117         // <way id='3' action='delete' visible='true' version='1'>
    118         // <nd ref='1' />
    119         // <nd ref='-1' /> <!-- here's the problem -->
    120         // <nd ref='2' />
    121         // </way>
    122         if (w.isNew())
    123             return; // process existing ways only
    124         List<Node> nodesToKeep = new ArrayList<Node>();
    125         // lookup new nodes which have been added to the set of deleted
    126         // nodes ...
    127         Iterator<Node> it = nodesToKeep.iterator();
    128         while(it.hasNext()) {
    129             Node n = it.next();
    130             if (n.isNew()) {
    131                 it.remove();
    132             }
    133         }
    134         w.setNodes(nodesToKeep);
    135     }
    136 
    137114    @Override
    138115    public boolean executeCommand() {
    139         super.executeCommand();
    140         for (OsmPrimitive osm : toDelete) {
     116        // Make copy and remove all references (to prevent inconsistent dataset (delete referenced) while command is executed)
     117        for (OsmPrimitive osm: toDelete) {
     118            if (osm.isDeleted())
     119                throw new IllegalArgumentException(osm.toString() + " is already deleted");
     120            clonedPrimitives.put(osm, osm.save());
     121
     122            if (osm instanceof Way) {
     123                ((Way) osm).setNodes(null);
     124            } else if (osm instanceof Relation) {
     125                ((Relation) osm).setMembers(null);
     126            }
     127        }
     128
     129        for (OsmPrimitive osm: toDelete) {
    141130            osm.setDeleted(true);
    142             if (osm instanceof Way) {
    143                 removeNewNodesFromDeletedWay((Way)osm);
    144             }
    145         }
     131        }
     132
    146133        return true;
     134    }
     135
     136    @Override
     137    public void undoCommand() {
     138        for (OsmPrimitive osm: toDelete) {
     139            osm.setDeleted(false);
     140        }
     141
     142        for (Entry<OsmPrimitive, PrimitiveData> entry: clonedPrimitives.entrySet()) {
     143            entry.getKey().load(entry.getValue());
     144        }
    147145    }
    148146
Note: See TracChangeset for help on using the changeset viewer.