Changeset 2198 in josm for trunk/src/org/openstreetmap/josm/command
- Timestamp:
- 2009-09-27T16:29:21+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/command
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/command/ConflictResolveCommand.java
r2163 r2198 12 12 13 13 /** 14 * This is the common bas se class for {@see Command}s which manipulate {@see Conflict}s in14 * This is the common base class for {@see Command}s which manipulate {@see Conflict}s in 15 15 * addition to {@see OsmPrimitive}s. 16 16 * 17 17 * A ConflictResolverCommand can remember a collection of conflicts it resolves. Upon undoing 18 * it reconstitutes the se conflicts.18 * it reconstitutes them. 19 19 * 20 20 */ … … 30 30 } 31 31 32 public ConflictResolveCommand(OsmDataLayer layer) { 33 super(layer); 34 resolvedConflicts = new ConflictCollection(); 35 } 36 32 37 /** 33 38 * remembers a conflict in the internal list of remembered conflicts … … 35 40 * @param c the remembered conflict 36 41 */ 37 protected void rememberConflict(Conflict c) {42 protected void rememberConflict(Conflict<?> c) { 38 43 if (! resolvedConflicts.hasConflictForMy(c.getMy())) { 39 44 resolvedConflicts.add(c); … … 48 53 protected void reconstituteConflicts() { 49 54 OsmDataLayer editLayer = getLayer(); 50 for(Conflict c : resolvedConflicts) {55 for(Conflict<?> c : resolvedConflicts) { 51 56 if (!editLayer.getConflicts().hasConflictForMy(c.getMy())) { 52 57 editLayer.getConflicts().add(c); … … 60 65 61 66 if (! Main.map.mapView.hasLayer(getLayer())) { 62 logger.warning(tr("Can' t undo command ''{0}'' because layer ''{1}'' is not present any more",67 logger.warning(tr("Can''t undo command ''{0}'' because layer ''{1}'' is not present any more", 63 68 this.toString(), 64 69 getLayer().toString() … … 70 75 reconstituteConflicts(); 71 76 } 72 73 74 75 77 } -
trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java
r2163 r2198 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.util.ArrayList;7 6 import java.util.Collection; 7 import java.util.Collections; 8 import java.util.HashSet; 8 9 import java.util.List; 10 import java.util.Set; 9 11 import java.util.logging.Logger; 10 12 … … 15 17 import org.openstreetmap.josm.Main; 16 18 import org.openstreetmap.josm.data.conflict.ConflictCollection; 17 import org.openstreetmap.josm.data.osm. DataSet;19 import org.openstreetmap.josm.data.osm.BackreferencedDataSet; 18 20 import org.openstreetmap.josm.data.osm.Node; 19 21 import org.openstreetmap.josm.data.osm.OsmPrimitive; 20 22 import org.openstreetmap.josm.data.osm.Relation; 21 import org.openstreetmap.josm.data.osm.RelationMember;22 23 import org.openstreetmap.josm.data.osm.Way; 24 import org.openstreetmap.josm.gui.DefaultNameFormatter; 25 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 23 26 import org.openstreetmap.josm.tools.ImageProvider; 24 27 … … 38 41 static private final Logger logger = Logger.getLogger(PurgePrimitivesCommand.class.getName()); 39 42 40 /** 41 * Represents a pair of {@see OsmPrimitive} where the parent referrs to 42 * the child, either because a {@see Way} includes a {@see Node} or 43 * because a {@see Relation} refers to any other {@see OsmPrimitive} 44 * via a relation member. 45 * 46 */ 47 static class OsmParentChildPair { 48 private OsmPrimitive parent; 49 private OsmPrimitive child; 50 51 52 public OsmParentChildPair(OsmPrimitive parent, OsmPrimitive child) { 53 this.parent = parent; 54 this.child = child; 55 } 56 57 public OsmPrimitive getParent() { 58 return parent; 59 } 60 61 public OsmPrimitive getChild() { 62 return child; 63 } 64 65 @Override 66 public int hashCode() { 67 final int prime = 31; 68 int result = 1; 69 result = prime * result + ((child == null) ? 0 : child.hashCode()); 70 result = prime * result + ((parent == null) ? 0 : parent.hashCode()); 71 return result; 72 } 73 74 @Override 75 public boolean equals(Object obj) { 76 if (this == obj) 77 return true; 78 if (obj == null) 79 return false; 80 if (getClass() != obj.getClass()) 81 return false; 82 OsmParentChildPair other = (OsmParentChildPair) obj; 83 if (child == null) { 84 if (other.child != null) 85 return false; 86 } else if (child != other.child) 87 return false; 88 if (parent == null) { 89 if (other.parent != null) 90 return false; 91 } else if (parent != other.parent) 92 return false; 93 return true; 94 } 95 } 96 97 /** 98 * creates a list of all {@see OsmParentChildPair}s for a given {@see OsmPrimitive} 99 * as child and given set of parents. We don't use {@see CollectBackReferencesVisitor} 100 * because it seems quite inefficient. 101 * 102 * @param parents the set of potential parents 103 * @param child the child 104 * @return the list of {@see OsmParentChildPair} 105 */ 106 protected List<OsmParentChildPair> getParentChildPairs(List<OsmPrimitive> parents, OsmPrimitive child) { 107 ArrayList<OsmParentChildPair> pairs = new ArrayList<OsmParentChildPair>(); 108 for (OsmPrimitive parent : parents) { 109 if (parent instanceof Way) { 110 Way w = (Way)parent; 111 for (OsmPrimitive node : w.getNodes()) { 112 if (node == child) { 113 OsmParentChildPair pair = new OsmParentChildPair(parent, node); 114 if (! pairs.contains(pair)) { 115 pairs.add(pair); 116 } 117 } 118 } 119 } else if (parent instanceof Relation) { 120 Relation r = (Relation)parent; 121 for (RelationMember member : r.getMembers()) { 122 if (member.getMember() == child) { 123 OsmParentChildPair pair = new OsmParentChildPair(parent, member.getMember()); 124 if (! pairs.contains(pair)) { 125 pairs.add(pair); 126 } 127 } 128 } 129 } 130 } 131 return pairs; 132 } 133 134 /** the primitive to purge */ 135 private OsmPrimitive primitive; 43 /** the primitives to purge */ 44 private Collection<OsmPrimitive> toPurge; 136 45 137 46 /** the set of primitives to purge as consequence of purging 138 47 * {@see #primitive}, including {@see #primitive} 139 48 */ 140 private ArrayList<OsmPrimitive> purgedPrimitives; 141 142 /** the set of {@see OsmParentChildPair}. We keep a reference 143 * to this set for the {@see #fillModifiedData(Collection, Collection, Collection)} operation 144 */ 145 private ArrayList<OsmParentChildPair> pairs; 146 49 private Set<OsmPrimitive> purgedPrimitives; 50 51 private Set<OsmPrimitive> origVersionsOfTouchedPrimitives; 52 53 /** 54 * the data structure with child->parent references 55 */ 56 private BackreferencedDataSet backreferenceDataSet; 57 58 protected void init(Collection<OsmPrimitive> toPurge) { 59 this.toPurge = toPurge; 60 this.purgedPrimitives = new HashSet<OsmPrimitive>(); 61 this.origVersionsOfTouchedPrimitives = new HashSet<OsmPrimitive>(); 62 } 147 63 148 64 /** 149 65 * constructor 150 * @param node the node to undelete 66 * @param primitive the primitive to purge 67 * 151 68 */ 152 69 public PurgePrimitivesCommand(OsmPrimitive primitive) { 153 this.primitive = primitive; 154 purgedPrimitives = new ArrayList<OsmPrimitive>(); 155 pairs = new ArrayList<OsmParentChildPair>(); 156 } 157 158 @Override 159 public MutableTreeNode description() { 70 init(Collections.singleton(primitive)); 71 } 72 73 /** 74 * constructor 75 * @param layer the OSM data layer 76 * @param primitive the primitive to purge 77 * 78 */ 79 public PurgePrimitivesCommand(OsmDataLayer layer, OsmPrimitive primitive) { 80 super(layer); 81 init(Collections.singleton(primitive)); 82 } 83 84 /** 85 * constructor 86 * @param layer the OSM data layer 87 * @param primitives the primitives to purge 88 * 89 */ 90 public PurgePrimitivesCommand(OsmDataLayer layer, Collection<OsmPrimitive> primitives) { 91 super(layer); 92 init(primitives); 93 } 94 95 /** 96 * Replies a collection with the purged primitives 97 * 98 * @return a collection with the purged primitives 99 */ 100 public Collection<OsmPrimitive> getPurgedPrimitives() { 101 return purgedPrimitives; 102 } 103 104 protected MutableTreeNode getDescription(OsmPrimitive primitive) { 160 105 return new DefaultMutableTreeNode( 161 106 new JLabel( 162 tr("Purg ing 1 primitive"),107 tr("Purged object ''{0}''", primitive.getDisplayName(DefaultNameFormatter.getInstance())), 163 108 ImageProvider.get("data", "object"), 164 109 JLabel.HORIZONTAL … … 167 112 } 168 113 169 /** 170 * Purges an {@see OsmPrimitive} <code>toPurge</code> from a {@see DataSet}. 114 protected MutableTreeNode getDescription(Collection<OsmPrimitive> primitives) { 115 116 DefaultMutableTreeNode root = new DefaultMutableTreeNode( 117 tr("Purged {0} objects", primitives.size()) 118 ); 119 for (OsmPrimitive p : primitives) { 120 root.add(getDescription(p)); 121 } 122 return root; 123 } 124 125 @Override 126 public MutableTreeNode description() { 127 if (purgedPrimitives.size() == 1) 128 return getDescription(purgedPrimitives.iterator().next()); 129 else 130 return getDescription(purgedPrimitives); 131 } 132 133 /** 134 * Purges an {@see OsmPrimitive} <code>child</code> from a {@see DataSet}. 171 135 * 172 * @param toPurge the primitive to purge 173 * @param ds the dataset to purge from 136 * @param child the primitive to purge 174 137 * @param hive the hive of {@see OsmPrimitive}s we remember other {@see OsmPrimitive} 175 * we have to purge because we purge <code> toPurge</code>.138 * we have to purge because we purge <code>child</code>. 176 139 * 177 140 */ 178 protected void purge(OsmPrimitive toPurge, DataSet ds, ArrayList<OsmPrimitive> hive) { 179 ArrayList<OsmPrimitive> parents = new ArrayList<OsmPrimitive>(); 180 parents.addAll(getLayer().data.ways); 181 parents.addAll(getLayer().data.relations); 182 List<OsmParentChildPair> pairs = getParentChildPairs(parents, primitive); 183 hive.remove(toPurge); 184 for (OsmParentChildPair pair: pairs) { 185 if (pair.getParent() instanceof Way) { 186 Way w = (Way)pair.getParent(); 187 System.out.println(tr("removing reference from way {0}",w.getId())); 141 protected void removeReferecesToPrimitive(OsmPrimitive child, Set<OsmPrimitive> hive) { 142 hive.remove(child); 143 for (OsmPrimitive parent: this.backreferenceDataSet.getParents(child)) { 144 if (toPurge.contains(parent)) 145 // parent itself is to be purged. This method is going to be 146 // invoked for parent later 147 return; 148 if (parent instanceof Way) { 149 Way w = (Way)parent; 150 if (!origVersionsOfTouchedPrimitives.contains(w)) { 151 origVersionsOfTouchedPrimitives.add(w); 152 } 188 153 List<Node> wayNodes = w.getNodes(); 189 wayNodes.remove( primitive);154 wayNodes.remove(child); 190 155 w.setNodes(wayNodes); 191 // if a way ends up with less than two node we156 // if a way ends up with less than two nodes we 192 157 // remember it on the "hive" 193 158 // … … 195 160 System.out.println(tr("Warning: Purging way {0} because number of nodes dropped below 2. Current is {1}", 196 161 w.getId(),w.getNodesCount())); 197 if (!hive.contains(w)) { 198 hive.add(w); 199 } 162 hive.add(w); 200 163 } 201 } else if (pair.getParent() instanceof Relation) { 202 Relation r = (Relation)pair.getParent(); 203 System.out.println(tr("removing reference from relation {0}",r.getId())); 204 r.removeMembersFor(primitive); 164 } else if (parent instanceof Relation) { 165 Relation r = (Relation)parent; 166 if (!origVersionsOfTouchedPrimitives.contains(r)) { 167 origVersionsOfTouchedPrimitives.add(r); 168 } 169 System.out.println(tr("Removing reference from relation {0}",r.getId())); 170 r.removeMembersFor(child); 171 } else { 172 // should not happen. parent can't be a node 205 173 } 206 174 } … … 209 177 @Override 210 178 public boolean executeCommand() { 211 ArrayList<OsmPrimitive> hive = new ArrayList<OsmPrimitive>(); 179 if (backreferenceDataSet == null) { 180 backreferenceDataSet = new BackreferencedDataSet(getLayer().data); 181 backreferenceDataSet.build(); 182 } 183 HashSet<OsmPrimitive> hive = new HashSet<OsmPrimitive>(); 212 184 213 185 // iteratively purge the primitive and all primitives 214 // which violate invariants after they lo ose a reference to186 // which violate invariants after they lose a reference to 215 187 // the primitive (i.e. ways which end up with less than two 216 188 // nodes) 217 hive.add (primitive);189 hive.addAll(toPurge); 218 190 while(! hive.isEmpty()) { 219 OsmPrimitive toPurge = hive.get(0);220 purge(toPurge, getLayer().data, hive);221 if (toPurge instanceof Node) {222 getLayer().data.nodes.remove(toPurge);223 } else if (primitive instanceof Way) {224 getLayer().data.ways.remove(toPurge);225 } else if (primitive instanceof Relation) {226 getLayer().data.relations.remove(toPurge);191 OsmPrimitive p = hive.iterator().next(); 192 removeReferecesToPrimitive(p, hive); 193 getLayer().data.removePrimitive(p); 194 purgedPrimitives.add(p); 195 ConflictCollection conflicts = getLayer().getConflicts(); 196 if (conflicts.hasConflictForMy(p)) { 197 rememberConflict(conflicts.getConflictForMy(p)); 198 conflicts.remove(p); 227 199 } 228 purgedPrimitives.add(toPurge); 229 ConflictCollection conflicts = getLayer().getConflicts(); 230 if (conflicts.hasConflictForMy(toPurge)) { 231 rememberConflict(conflicts.getConflictForMy(toPurge)); 232 conflicts.remove(toPurge); 233 } 234 } 200 } 201 // we don't need this any more 202 backreferenceDataSet = null; 235 203 return super.executeCommand(); 236 204 } … … 239 207 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, 240 208 Collection<OsmPrimitive> added) { 241 for (OsmParentChildPair pair : pairs) { 242 modified.add(pair.getParent()); 243 } 244 // we don't need pairs anymore 245 pairs = null; 209 modified.addAll(origVersionsOfTouchedPrimitives); 246 210 } 247 211 … … 249 213 public void undoCommand() { 250 214 if (! Main.map.mapView.hasLayer(getLayer())) { 251 logger.warning(tr("Can' t undo command ''{0}'' because layer ''{1}'' is not present any more",215 logger.warning(tr("Can''t undo command ''{0}'' because layer ''{1}'' is not present any more", 252 216 this.toString(), 253 217 getLayer().toString() … … 263 227 } 264 228 reconstituteConflicts(); 265 // will restore the former references to the purged nodes 266 // 229 230 // will restore the primitives referring to one 231 // of the purged primitives 267 232 super.undoCommand(); 268 233 } 234 235 /** 236 * Use to inject a backreference data set used when the command 237 * is executed. 238 * 239 * @param ds the backreference data set 240 */ 241 public void setBackreferenceDataSet(BackreferencedDataSet ds) { 242 this.backreferenceDataSet = ds; 243 } 269 244 }
Note:
See TracChangeset
for help on using the changeset viewer.