source: josm/trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java@ 2702

Last change on this file since 2702 was 2565, checked in by Gubaer, 14 years ago

Removed BackReferenceDataSet and CollectBackReferenceVisitor because we now have referrer support in OsmPrimitive.
This could cause some problems in the next few days. I'm sure I didn't test every possibly affected feature.

File size: 7.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.command;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.Collection;
7import java.util.Collections;
8import java.util.HashSet;
9import java.util.List;
10import java.util.Set;
11import java.util.logging.Logger;
12
13import javax.swing.JLabel;
14import javax.swing.tree.DefaultMutableTreeNode;
15import javax.swing.tree.MutableTreeNode;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.data.conflict.ConflictCollection;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.Relation;
22import org.openstreetmap.josm.data.osm.Way;
23import org.openstreetmap.josm.gui.DefaultNameFormatter;
24import org.openstreetmap.josm.gui.layer.OsmDataLayer;
25import org.openstreetmap.josm.tools.ImageProvider;
26
27/**
28 * Physically removes an {@see OsmPrimitive} from the dataset of the edit
29 * layer and disconnects any references from {@see Way}s or {@see Relation}s
30 * to this primitive.
31 *
32 * This command is necessary if a local {@see OsmPrimitive} has been deleted on
33 * the server by another user and if the local user decides to delete his version
34 * too. If he only deleted it "logically" JOSM would try to delete it on the server
35 * which would result in an non resolvable conflict.
36 *
37 */
38public class PurgePrimitivesCommand extends ConflictResolveCommand{
39
40 static private final Logger logger = Logger.getLogger(PurgePrimitivesCommand.class.getName());
41
42 /** the primitives to purge */
43 private Collection<OsmPrimitive> toPurge;
44
45 /** the set of primitives to purge as consequence of purging
46 * {@see #primitive}, including {@see #primitive}
47 */
48 private Set<OsmPrimitive> purgedPrimitives;
49
50 private Set<OsmPrimitive> origVersionsOfTouchedPrimitives;
51
52 protected void init(Collection<OsmPrimitive> toPurge) {
53 this.toPurge = toPurge;
54 this.purgedPrimitives = new HashSet<OsmPrimitive>();
55 this.origVersionsOfTouchedPrimitives = new HashSet<OsmPrimitive>();
56 }
57
58 /**
59 * constructor
60 * @param primitive the primitive to purge
61 *
62 */
63 public PurgePrimitivesCommand(OsmPrimitive primitive) {
64 init(Collections.singleton(primitive));
65 }
66
67 /**
68 * constructor
69 * @param layer the OSM data layer
70 * @param primitive the primitive to purge
71 *
72 */
73 public PurgePrimitivesCommand(OsmDataLayer layer, OsmPrimitive primitive) {
74 super(layer);
75 init(Collections.singleton(primitive));
76 }
77
78 /**
79 * constructor
80 * @param layer the OSM data layer
81 * @param primitives the primitives to purge
82 *
83 */
84 public PurgePrimitivesCommand(OsmDataLayer layer, Collection<OsmPrimitive> primitives) {
85 super(layer);
86 init(primitives);
87 }
88
89 /**
90 * Replies a collection with the purged primitives
91 *
92 * @return a collection with the purged primitives
93 */
94 public Collection<OsmPrimitive> getPurgedPrimitives() {
95 return purgedPrimitives;
96 }
97
98 protected MutableTreeNode getDescription(OsmPrimitive primitive) {
99 return new DefaultMutableTreeNode(
100 new JLabel(
101 tr("Purged object ''{0}''", primitive.getDisplayName(DefaultNameFormatter.getInstance())),
102 ImageProvider.get("data", "object"),
103 JLabel.HORIZONTAL
104 )
105 );
106 }
107
108 protected MutableTreeNode getDescription(Collection<OsmPrimitive> primitives) {
109
110 DefaultMutableTreeNode root = new DefaultMutableTreeNode(
111 tr("Purged {0} objects", primitives.size())
112 );
113 for (OsmPrimitive p : primitives) {
114 root.add(getDescription(p));
115 }
116 return root;
117 }
118
119 @Override
120 public MutableTreeNode description() {
121 if (purgedPrimitives.size() == 1)
122 return getDescription(purgedPrimitives.iterator().next());
123 else
124 return getDescription(purgedPrimitives);
125 }
126
127 /**
128 * Purges an {@see OsmPrimitive} <code>child</code> from a {@see DataSet}.
129 *
130 * @param child the primitive to purge
131 * @param hive the hive of {@see OsmPrimitive}s we remember other {@see OsmPrimitive}
132 * we have to purge because we purge <code>child</code>.
133 *
134 */
135 protected void removeReferecesToPrimitive(OsmPrimitive child, Set<OsmPrimitive> hive) {
136 hive.remove(child);
137 for (OsmPrimitive parent: child.getReferrers()) {
138 if (toPurge.contains(parent))
139 // parent itself is to be purged. This method is going to be
140 // invoked for parent later
141 return;
142 if (parent instanceof Way) {
143 Way w = (Way)parent;
144 if (!origVersionsOfTouchedPrimitives.contains(w)) {
145 origVersionsOfTouchedPrimitives.add(w);
146 }
147 List<Node> wayNodes = w.getNodes();
148 wayNodes.remove(child);
149 w.setNodes(wayNodes);
150 // if a way ends up with less than two nodes we
151 // remember it on the "hive"
152 //
153 if (w.getNodesCount() < 2) {
154 System.out.println(tr("Warning: Purging way {0} because number of nodes dropped below 2. Current is {1}",
155 w.getId(),w.getNodesCount()));
156 hive.add(w);
157 }
158 } else if (parent instanceof Relation) {
159 Relation r = (Relation)parent;
160 if (!origVersionsOfTouchedPrimitives.contains(r)) {
161 origVersionsOfTouchedPrimitives.add(r);
162 }
163 System.out.println(tr("Removing reference from relation {0}",r.getId()));
164 r.removeMembersFor(child);
165 } else {
166 // should not happen. parent can't be a node
167 }
168 }
169 }
170
171 @Override
172 public boolean executeCommand() {
173 HashSet<OsmPrimitive> hive = new HashSet<OsmPrimitive>();
174
175 // iteratively purge the primitive and all primitives
176 // which violate invariants after they lose a reference to
177 // the primitive (i.e. ways which end up with less than two
178 // nodes)
179 hive.addAll(toPurge);
180 while(! hive.isEmpty()) {
181 OsmPrimitive p = hive.iterator().next();
182 removeReferecesToPrimitive(p, hive);
183 getLayer().data.removePrimitive(p);
184 purgedPrimitives.add(p);
185 ConflictCollection conflicts = getLayer().getConflicts();
186 if (conflicts.hasConflictForMy(p)) {
187 rememberConflict(conflicts.getConflictForMy(p));
188 conflicts.remove(p);
189 }
190 }
191 return super.executeCommand();
192 }
193
194 @Override
195 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
196 Collection<OsmPrimitive> added) {
197 modified.addAll(origVersionsOfTouchedPrimitives);
198 }
199
200 @Override
201 public void undoCommand() {
202 if (! Main.map.mapView.hasLayer(getLayer())) {
203 logger.warning(tr("Can''t undo command ''{0}'' because layer ''{1}'' is not present any more",
204 this.toString(),
205 getLayer().toString()
206 ));
207 return;
208 }
209 Main.map.mapView.setActiveLayer(getLayer());
210
211 // restore purged primitives
212 //
213 for (OsmPrimitive purged : purgedPrimitives) {
214 getLayer().data.addPrimitive(purged);
215 }
216 reconstituteConflicts();
217
218 // will restore the primitives referring to one
219 // of the purged primitives
220 super.undoCommand();
221 }
222}
Note: See TracBrowser for help on using the repository browser.