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

Last change on this file since 2876 was 2844, checked in by mjulius, 14 years ago

fix messages for commands

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