Changeset 3055 in josm


Ignore:
Timestamp:
27.02.2010 16:31:10 (2 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.