001 // License: GPL. Copyright 2007 by Immanuel Scholz and others 002 package org.openstreetmap.josm.command; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.util.Arrays; 007 import java.util.Collection; 008 import java.util.HashSet; 009 import java.util.List; 010 import javax.swing.Icon; 011 012 import javax.swing.JLabel; 013 014 import org.openstreetmap.josm.Main; 015 import org.openstreetmap.josm.data.osm.OsmPrimitive; 016 import org.openstreetmap.josm.tools.ImageProvider; 017 018 /** 019 * A command consisting of a sequence of other commands. Executes the other commands 020 * and undo them in reverse order. 021 * @author imi 022 */ 023 public class SequenceCommand extends Command { 024 025 /** 026 * The command sequenz to be executed. 027 */ 028 private Command[] sequence; 029 private boolean sequence_complete; 030 private final String name; 031 public boolean continueOnError = false; 032 033 /** 034 * Create the command by specifying the list of commands to execute. 035 * @param sequenz The sequence that should be executed. 036 */ 037 public SequenceCommand(String name, Collection<Command> sequenz) { 038 super(); 039 this.name = name; 040 this.sequence = new Command[sequenz.size()]; 041 this.sequence = sequenz.toArray(this.sequence); 042 } 043 044 /** 045 * Convenient constructor, if the commands are known at compile time. 046 */ 047 public SequenceCommand(String name, Command... sequenz) { 048 this(name, Arrays.asList(sequenz)); 049 } 050 051 @Override public boolean executeCommand() { 052 for (int i=0; i < sequence.length; i++) { 053 Command c = sequence[i]; 054 boolean result = c.executeCommand(); 055 if (!result && !continueOnError) { 056 this.undoCommands(i-1); 057 return false; 058 } 059 } 060 sequence_complete = true; 061 return true; 062 } 063 064 public Command getLastCommand() { 065 if(sequence.length == 0) 066 return null; 067 return sequence[sequence.length-1]; 068 } 069 private void undoCommands(int start) { 070 // We probably aborted this halfway though the 071 // execution sequence because of a sub-command 072 // error. We already undid the sub-commands. 073 if (!sequence_complete) 074 return; 075 for (int i = start; i >= 0; --i) { 076 sequence[i].undoCommand(); 077 } 078 } 079 080 @Override public void undoCommand() { 081 this.undoCommands(sequence.length-1); 082 } 083 084 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { 085 for (Command c : sequence) { 086 c.fillModifiedData(modified, deleted, added); 087 } 088 } 089 090 @Override 091 public String getDescriptionText() { 092 return tr("Sequence: {0}", name); 093 } 094 095 @Override 096 public Icon getDescriptionIcon() { 097 return ImageProvider.get("data", "sequence"); 098 } 099 100 @Override 101 @SuppressWarnings("unchecked") 102 public Collection<PseudoCommand> getChildren() { 103 return (List) Arrays.asList(sequence); 104 } 105 106 @Override 107 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() { 108 Collection<OsmPrimitive> prims = new HashSet<OsmPrimitive>(); 109 for (Command c : sequence) { 110 prims.addAll(c.getParticipatingPrimitives()); 111 } 112 return prims; 113 } 114 }