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

Last change on this file since 14397 was 14283, checked in by Don-vip, 6 years ago

see #12726 - add new getters in {Change,Sequence}Command

  • Property svn:eol-style set to native
File size: 5.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;
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.DataSet;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
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 ds The target data set. Must not be {@code null}
36 * @param name The description text
37 * @param sequenz The sequence that should be executed
38 * @param continueOnError Determines if the sequence execution should continue after one of its commands fails
39 * @since 12726
40 */
41 public SequenceCommand(DataSet ds, String name, Collection<Command> sequenz, boolean continueOnError) {
42 super(ds);
43 this.name = name;
44 this.sequence = sequenz.toArray(new Command[0]);
45 this.continueOnError = continueOnError;
46 }
47
48 /**
49 * Create the command by specifying the list of commands to execute.
50 * @param name The description text
51 * @param sequenz The sequence that should be executed. Must not be null or empty
52 * @param continueOnError Determines if the sequence execution should continue after one of its commands fails
53 * @since 11874
54 */
55 public SequenceCommand(String name, Collection<Command> sequenz, boolean continueOnError) {
56 this(sequenz.iterator().next().getAffectedDataSet(), name, sequenz, continueOnError);
57 }
58
59 /**
60 * Create the command by specifying the list of commands to execute.
61 * @param name The description text
62 * @param sequenz The sequence that should be executed.
63 */
64 public SequenceCommand(String name, Collection<Command> sequenz) {
65 this(name, sequenz, false);
66 }
67
68 /**
69 * Convenient constructor, if the commands are known at compile time.
70 * @param name The description text
71 * @param sequenz The sequence that should be executed.
72 */
73 public SequenceCommand(String name, Command... sequenz) {
74 this(name, Arrays.asList(sequenz));
75 }
76
77 @Override public boolean executeCommand() {
78 for (int i = 0; i < sequence.length; i++) {
79 boolean result = sequence[i].executeCommand();
80 if (!result && !continueOnError) {
81 undoCommands(i-1);
82 return false;
83 }
84 }
85 sequenceComplete = true;
86 return true;
87 }
88
89 /**
90 * Returns the last command.
91 * @return The last command, or {@code null} if the sequence is empty.
92 */
93 public Command getLastCommand() {
94 if (sequence.length == 0)
95 return null;
96 return sequence[sequence.length-1];
97 }
98
99 protected final void undoCommands(int start) {
100 for (int i = start; i >= 0; --i) {
101 sequence[i].undoCommand();
102 }
103 }
104
105 @Override
106 public void undoCommand() {
107 // We probably aborted this halfway though the execution sequence because of a sub-command error.
108 // We already undid the sub-commands.
109 if (!sequenceComplete)
110 return;
111 undoCommands(sequence.length-1);
112 }
113
114 @Override
115 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
116 for (Command c : sequence) {
117 c.fillModifiedData(modified, deleted, added);
118 }
119 }
120
121 @Override
122 public String getDescriptionText() {
123 return tr("Sequence: {0}", name);
124 }
125
126 /**
127 * Returns the command name used in description text.
128 * @return the command name
129 * @since 14283
130 */
131 public final String getName() {
132 return name;
133 }
134
135 @Override
136 public Icon getDescriptionIcon() {
137 return ImageProvider.get("data", "sequence");
138 }
139
140 @Override
141 public Collection<PseudoCommand> getChildren() {
142 return Arrays.<PseudoCommand>asList(sequence);
143 }
144
145 @Override
146 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
147 Collection<OsmPrimitive> prims = new HashSet<>();
148 for (Command c : sequence) {
149 prims.addAll(c.getParticipatingPrimitives());
150 }
151 return prims;
152 }
153
154 protected final void setSequence(Command... sequence) {
155 this.sequence = Utils.copyArray(sequence);
156 }
157
158 protected final void setSequenceComplete(boolean sequenceComplete) {
159 this.sequenceComplete = sequenceComplete;
160 }
161
162 @Override
163 public int hashCode() {
164 return Objects.hash(super.hashCode(), Arrays.hashCode(sequence), sequenceComplete, name, continueOnError);
165 }
166
167 @Override
168 public boolean equals(Object obj) {
169 if (this == obj) return true;
170 if (obj == null || getClass() != obj.getClass()) return false;
171 if (!super.equals(obj)) return false;
172 SequenceCommand that = (SequenceCommand) obj;
173 return sequenceComplete == that.sequenceComplete &&
174 continueOnError == that.continueOnError &&
175 Arrays.equals(sequence, that.sequence) &&
176 Objects.equals(name, that.name);
177 }
178}
Note: See TracBrowser for help on using the repository browser.