/*
* Strongback
* Copyright 2015, Strongback and individual contributors by the @authors tag.
* See the COPYRIGHT.txt in the distribution for a full listing of individual
* contributors.
*
* Licensed under the MIT License; you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.strongback.command;
import org.strongback.annotation.NotThreadSafe;
/**
* A {@link CommandGroup} is a series of {@link Command}s executed in sequence or in parallel. A command group is created by
* extending {@link CommandGroup}, and then specifying in the constructor of the subclass whether the {@link Command}s should be
* executed {@link #sequentially(Command...) sequential} or {@link #simultaneously(Command...) simultaneously}. The commands
* passed into these methods can be any {@link Command} subclass, {@link CommandGroup} subclass, or a group of sequential,
* simultaneous, or forked commands.
* <p>
* Commands executed one after the other are <em>sequential</em>, and are defined with a call to
* {@link #sequentially(Command...)} and the list of {@link Command} instances, in order. The whole block finishes only when the
* last {@link Command} is done.
*
* <p>Commands executed at the same time (in parallel) are <em>simultaneous</em>, and are defined with a call to
* {@link #simultaneously(Command...)} and a list of the {@link Command} instances. Order is not important, as they are all are
* executed at the same time. The whole block finishes only when all {@link Command}s have completed.
*
* <p>When a command is to be executed completely independently of the command group, then that command (or group of commands)
* can be <em>forked</em>. A command (or group) is forked by calling {@link #fork(Command)} with the one {@link Command}, a
* {@link CommandGroup} subclass, or a group created with {@link #sequentially(Command...)} or
* {@link #simultaneously(Command...)}. For the purposes of {@link #sequentially(Command...)} the block finishes instantly.
*
* <h2>Sequential example</h2>
* <p>
* The following code shows a complete CommandGroup subclass that, when executed, first executes a {@code CommandA}, then a
* {@code CommandB}, and then finally a {@code CommandC}:
*
* <pre>
* public class MySequentialCommands extends CommandGroup {
* public MySequentialCommands() {
* sequentially(new CommandA(), new CommandB(), new CommandC());
* }
* }
* </pre>
*
* The {@code MySequentialCommands} will complete when {@code CommandC} instance completes.
*
* <h2>Simultaneous example</h2>
* <p>
* The following code shows a complete CommandGroup subclass that, when executed, executes three commands (a {@code CommandA}, a
* {@code CommandB}, and a {@code CommandC}) all at the same time:
*
* <pre>
* public class MySimultaneousCommands extends CommandGroup {
* public MySimultaneousCommands() {
* simultaneously(new CommandA(), new CommandB(), new CommandC());
* }
* }
* </pre>
*
* The {@code MySimultaneousCommands} will complete when the last of the three commands completes.
*
* <h2>Mixture of sequential and simultaneous</h2>
* <p>
* The following code shows a complete CommandGroup subclass that, when executed, executes two commands (a {@code CommandA} and
* a {@code CommandB}) at the same time and after both are finished a third command, {@code CommandC}:
*
* <pre>
* public class MyMixedCommands extends CommandGroup {
* public MyMixedCommands() {
* sequentially(simultaneously(new CommandA(), new CommandB()), new CommandC());
* }
* }
* </pre>
*
* The {@code MyMixedCommands} will complete when the last of the three commands ({@code CommandC}) completes.
*
* <h2>Complex example</h2>
* <p>
* The following code shows a complete but more complex CommandGroup subclass that, when executed, first executes
* {@code CommandA}, then executes {@code CommandB}, then forks off {@code CommandC} and immediately executes {@code CommandD},
* and finally executes both {@code CommandE} and {@code CommandF} in parallel:
*
* <pre>
* public class MyForkCommands extends CommandGroup {
* public MyForkCommands() {
* sequentially(new CommandA(),
* new CommandB(),
* fork(new Command C()),
* new CommandD());
* new sequentially( new CommandE(), new CommandF()));
* }
* }
* </pre>
*
* The {@code MyForkCommands} will complete when the last of the two final commands ({@code CommandE} or {@code CommandF})
* completes. Note that this is true even if {@code CommandC} is still running.
*/
@NotThreadSafe
public class CommandGroup extends Command {
/**
* Creates a single {@link CommandGroup} that executes several {@link Command}s in sequential order.
*
* @param commands the {@link Command}s to be executed
* @return the {@link CommandGroup} wrapping the {@link Command}s
*/
public static CommandGroup runSequentially( Command ... commands ) {
return new CommandGroup(commands,Type.SEQUENTIAL);
}
/**
* Creates a single {@link CommandGroup} that executes several {@link Command}s simultaneously.
*
* @param commands the {@link Command}s to be executed
* @return the {@link CommandGroup} wrapping the {@link Command}s
*/
public static CommandGroup runSimultaneously( Command ... commands ) {
return new CommandGroup(commands,Type.PARRALLEL);
}
static enum Type {
SEQUENTIAL, PARRALLEL, FORK;
}
private Command root;
private final Command[] commands;
private final Type type;
/**
* Create a new command group. Typically, subclass constructors call this constructor (perhaps implicitly) and then add one
* or more commands using {@link #fork(Command)}, {@link #sequentially(Command...)}, and {@link #simultaneously(Command...)}
* .
*/
protected CommandGroup() {
commands = null;
type = Type.SEQUENTIAL;
}
private CommandGroup(Command[] commands, Type type) {
this.commands = commands;
this.type = type;
}
Type getType() {
return type;
}
Command[] getCommands() {
return commands;
}
Command getRoot() {
return root;
}
/**
* Wraps several {@link Commands}s in a single {@link CommandGroup} that executes them simultaneously.
*
* @param commands the {@link CommandRunner}s to wrap
* @return the {@link CommandGroup} wrapping the {@link Command}s
*/
public CommandGroup simultaneously(Command... commands) {
CommandGroup cg = new CommandGroup(commands, Type.PARRALLEL);
root = cg;
return cg;
}
/**
* Creates a single {@link CommandGroup} that executes several {@link Command}s in sequential order.
*
* @param commands the {@link Command}s to be executed
* @return the {@link CommandGroup} wrapping the {@link Command}s
*/
public CommandGroup sequentially(Command... commands) {
CommandGroup cg = new CommandGroup(commands, Type.SEQUENTIAL);
root = cg;
return cg;
}
/**
* Add a {@link Command} that executes independently of any other {@link Command}s in this group.
*
* @param forked the {@link Command} to fork
* @return the forked {@link CommandGroup}
*/
public CommandGroup fork(Command forked) {
CommandGroup cg = new CommandGroup(new Command[] { forked }, Type.FORK);
root = cg;
return cg;
}
@Override
public final boolean execute() {
return false;
}
}