source: josm/trunk/src/org/openstreetmap/josm/command/Command.java@ 2284

Last change on this file since 2284 was 2284, checked in by jttt, 15 years ago

Added PrimitiveData classes. Uses PrimitiveData as storage for Command's undo function

  • Property svn:eol-style set to native
File size: 4.6 KB
RevLine 
[304]1//License: GPL. Copyright 2007 by Immanuel Scholz and others
[21]2package org.openstreetmap.josm.command;
3
[22]4import java.util.Collection;
[146]5import java.util.HashMap;
[86]6import java.util.HashSet;
[146]7import java.util.Map;
[86]8import java.util.Map.Entry;
[21]9
[94]10import javax.swing.tree.MutableTreeNode;
11
[630]12import org.openstreetmap.josm.Main;
[146]13import org.openstreetmap.josm.data.osm.Node;
[22]14import org.openstreetmap.josm.data.osm.OsmPrimitive;
[2284]15import org.openstreetmap.josm.data.osm.PrimitiveData;
[1523]16import org.openstreetmap.josm.data.osm.Relation;
[146]17import org.openstreetmap.josm.data.osm.Way;
[1523]18import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
[304]19import org.openstreetmap.josm.gui.layer.Layer;
20import org.openstreetmap.josm.gui.layer.OsmDataLayer;
[21]21
[22]22
[21]23/**
24 * Classes implementing Command modify a dataset in a specific way. A command is
[22]25 * one atomic action on a specific dataset, such as move or delete.
[21]26 *
[1750]27 * The command remembers the {@see OsmDataLayer} it is operating on.
[2284]28 *
[21]29 * @author imi
30 */
[86]31abstract public class Command {
[21]32
[1750]33 private static final class CloneVisitor extends AbstractVisitor {
[2284]34 public Map<OsmPrimitive, PrimitiveData> orig = new HashMap<OsmPrimitive, PrimitiveData>();
[304]35
[1750]36 public void visit(Node n) {
[2284]37 orig.put(n, n.save());
[1750]38 }
39 public void visit(Way w) {
[2284]40 orig.put(w, w.save());
[1750]41 }
42 public void visit(Relation e) {
[2284]43 orig.put(e, e.save());
[1750]44 }
45 }
[304]46
[1750]47 /** the map of OsmPrimitives in the original state to OsmPrimitives in cloned state */
[2284]48 private Map<OsmPrimitive, PrimitiveData> cloneMap = new HashMap<OsmPrimitive, PrimitiveData>();
[304]49
[1750]50 /** the layer which this command is applied to */
51 private OsmDataLayer layer;
[22]52
[1750]53 public Command() {
[1814]54 this.layer = Main.map.mapView.getEditLayer();
[1750]55 }
[1856]56
[1750]57 /**
[1856]58 * Creates a new command in the context of a specific data layer
[2284]59 *
[1856]60 * @param layer the data layer
61 */
62 public Command(OsmDataLayer layer) {
63 this.layer = layer;
64 }
65
66 /**
[1750]67 * Executes the command on the dataset. This implementation will remember all
68 * primitives returned by fillModifiedData for restoring them on undo.
69 */
70 public boolean executeCommand() {
71 CloneVisitor visitor = new CloneVisitor();
72 Collection<OsmPrimitive> all = new HashSet<OsmPrimitive>();
73 fillModifiedData(all, all, all);
74 for (OsmPrimitive osm : all) {
75 osm.visit(visitor);
76 }
77 cloneMap = visitor.orig;
78 return true;
79 }
[86]80
[1750]81 /**
82 * Undoes the command.
83 * It can be assumed that all objects are in the same state they were before.
84 * It can also be assumed that executeCommand was called exactly once before.
85 *
86 * This implementation undoes all objects stored by a former call to executeCommand.
87 */
88 public void undoCommand() {
[2284]89 for (Entry<OsmPrimitive, PrimitiveData> e : cloneMap.entrySet()) {
90 e.getKey().load(e.getValue(), layer.data);
[1750]91 }
92 }
[304]93
[1750]94 /**
95 * Called when a layer has been removed to have the command remove itself from
96 * any buffer if it is not longer applicable to the dataset (e.g. it was part of
97 * the removed layer)
[2284]98 *
[1750]99 * @param oldLayer the old layer
100 * @return true if this command
101 */
102 public boolean invalidBecauselayerRemoved(Layer oldLayer) {
103 if (!(oldLayer instanceof OsmDataLayer))
104 return false;
105 return layer == oldLayer;
106 }
[304]107
[630]108 /**
109 * Lets other commands access the original version
110 * of the object. Usually for undoing.
111 */
[2284]112 public PrimitiveData getOrig(OsmPrimitive osm) {
113 PrimitiveData o = cloneMap.get(osm);
[630]114 if (o != null)
[1750]115 return o;
[2025]116 Main.debug("unable to find osm with id: " + osm.getId() + " hashCode: " + osm.hashCode());
[1750]117 for (OsmPrimitive t : cloneMap.keySet()) {
[2284]118 PrimitiveData to = cloneMap.get(t);
[2025]119 Main.debug("now: " + t.getId() + " hashCode: " + t.hashCode());
120 Main.debug("orig: " + to.getId() + " hashCode: " + to.hashCode());
[630]121 }
122 return o;
123 }
[94]124
[1750]125 /**
126 * Replies the layer this command is (or was) applied to.
[2284]127 *
[1750]128 * @return
129 */
130 protected OsmDataLayer getLayer() {
131 return layer;
132 }
[630]133
[1750]134 /**
135 * Fill in the changed data this command operates on.
136 * Add to the lists, don't clear them.
137 *
138 * @param modified The modified primitives
139 * @param deleted The deleted primitives
140 * @param added The added primitives
141 */
142 abstract public void fillModifiedData(Collection<OsmPrimitive> modified,
143 Collection<OsmPrimitive> deleted,
144 Collection<OsmPrimitive> added);
145
146 abstract public MutableTreeNode description();
147
148
149
[21]150}
Note: See TracBrowser for help on using the repository browser.