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

Last change on this file since 3747 was 3362, checked in by stoecker, 14 years ago

fix #5182 - Conflict system simplification - patch by Upliner

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