source: josm/trunk/src/org/openstreetmap/josm/command/SequenceCommand.java@ 12718

Last change on this file since 12718 was 12718, checked in by Don-vip, 7 years ago

see #13036 - see #15229 - see #15182 - make Commands depends only on a DataSet, not a Layer. This removes a lot of GUI dependencies

  • Property svn:eol-style set to native
File size: 5.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;
5
6import java.util.Arrays;
7import java.util.Collection;
8import java.util.HashSet;
9import java.util.Objects;
10
11import javax.swing.Icon;
12
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.gui.layer.Layer;
15import org.openstreetmap.josm.tools.ImageProvider;
16import org.openstreetmap.josm.tools.Utils;
17
18/**
19 * A command consisting of a sequence of other commands. Executes the other commands
20 * and undo them in reverse order.
21 * @author imi
22 * @since 31
23 */
24public class SequenceCommand extends Command {
25
26 /** The command sequence to be executed. */
27 private Command[] sequence;
28 private boolean sequenceComplete;
29 private final String name;
30 /** Determines if the sequence execution should continue after one of its commands fails. */
31 protected final boolean continueOnError;
32
33 /**
34 * Create the command by specifying the list of commands to execute.
35 * @param name The description text
36 * @param sequenz The sequence that should be executed
37 * @param continueOnError Determines if the sequence execution should continue after one of its commands fails
38 * @since 11874
39 */
40 public SequenceCommand(String name, Collection<Command> sequenz, boolean continueOnError) {
41 this.name = name;
42 this.sequence = sequenz.toArray(new Command[sequenz.size()]);
43 this.continueOnError = continueOnError;
44 }
45
46 /**
47 * Create the command by specifying the list of commands to execute.
48 * @param name The description text
49 * @param sequenz The sequence that should be executed.
50 */
51 public SequenceCommand(String name, Collection<Command> sequenz) {
52 this(name, sequenz, false);
53 }
54
55 /**
56 * Convenient constructor, if the commands are known at compile time.
57 * @param name The description text
58 * @param sequenz The sequence that should be executed.
59 */
60 public SequenceCommand(String name, Command... sequenz) {
61 this(name, Arrays.asList(sequenz));
62 }
63
64 @Override public boolean executeCommand() {
65 for (int i = 0; i < sequence.length; i++) {
66 boolean result = sequence[i].executeCommand();
67 if (!result && !continueOnError) {
68 undoCommands(i-1);
69 return false;
70 }
71 }
72 sequenceComplete = true;
73 return true;
74 }
75
76 /**
77 * Returns the last command.
78 * @return The last command, or {@code null} if the sequence is empty.
79 */
80 public Command getLastCommand() {
81 if (sequence.length == 0)
82 return null;
83 return sequence[sequence.length-1];
84 }
85
86 protected final void undoCommands(int start) {
87 for (int i = start; i >= 0; --i) {
88 sequence[i].undoCommand();
89 }
90 }
91
92 @Override public void undoCommand() {
93 // We probably aborted this halfway though the
94 // execution sequence because of a sub-command
95 // error. We already undid the sub-commands.
96 if (!sequenceComplete)
97 return;
98 undoCommands(sequence.length-1);
99 }
100
101 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
102 for (Command c : sequence) {
103 c.fillModifiedData(modified, deleted, added);
104 }
105 }
106
107 @Override
108 public String getDescriptionText() {
109 return tr("Sequence: {0}", name);
110 }
111
112 @Override
113 public Icon getDescriptionIcon() {
114 return ImageProvider.get("data", "sequence");
115 }
116
117 @Override
118 public Collection<PseudoCommand> getChildren() {
119 return Arrays.<PseudoCommand>asList(sequence);
120 }
121
122 @Override
123 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
124 Collection<OsmPrimitive> prims = new HashSet<>();
125 for (Command c : sequence) {
126 prims.addAll(c.getParticipatingPrimitives());
127 }
128 return prims;
129 }
130
131 protected final void setSequence(Command... sequence) {
132 this.sequence = Utils.copyArray(sequence);
133 }
134
135 protected final void setSequenceComplete(boolean sequenceComplete) {
136 this.sequenceComplete = sequenceComplete;
137 }
138
139 /**
140 * Invalidate all layers that were affected by this command.
141 * @see Layer#invalidate()
142 * @deprecated to be removed end of 2017.
143 */
144 @Override
145 @Deprecated
146 public void invalidateAffectedLayers() {
147 super.invalidateAffectedLayers();
148 for (Command c : sequence) {
149 c.invalidateAffectedLayers();
150 }
151 }
152
153 @Override
154 public int hashCode() {
155 return Objects.hash(super.hashCode(), Arrays.hashCode(sequence), sequenceComplete, name, continueOnError);
156 }
157
158 @Override
159 public boolean equals(Object obj) {
160 if (this == obj) return true;
161 if (obj == null || getClass() != obj.getClass()) return false;
162 if (!super.equals(obj)) return false;
163 SequenceCommand that = (SequenceCommand) obj;
164 return sequenceComplete == that.sequenceComplete &&
165 continueOnError == that.continueOnError &&
166 Arrays.equals(sequence, that.sequence) &&
167 Objects.equals(name, that.name);
168 }
169}
Note: See TracBrowser for help on using the repository browser.