task("drinkCoffee").dependsOn("make_coffee", "wash");
(ごちゃごちゃ言うより、コードを見たほうが早いかも)
public class BasicStateMachine extends StateMachineBuilder { Events doorClosed, drawOpened, lightOn, panelClosed; Commands unlockPanel, lockPanel, lockDoor, unlockDoor; States idle, active, waitingForLight, waitingForDraw, unlockedPanel; ResetEvents doorOpened; protected void defineStateMachine() { doorClosed. code("D1CL"); drawOpened. code("D2OP"); lightOn. code("L1ON"); panelClosed.code("PNCL"); doorOpened. code("D1OP"); unlockPanel.code("PNUL"); lockPanel. code("PNLK"); lockDoor. code("D1LK"); unlockDoor. code("D1UL"); idle .actions(unlockDoor, lockPanel) .transition(doorClosed).to(active) ; active .transition(drawOpened).to(waitingForLight) .transition(lightOn). to(waitingForDraw) ; waitingForLight .transition(lightOn).to(unlockedPanel) ; waitingForDraw .transition(drawOpened).to(unlockedPanel) ; unlockedPanel .actions(unlockPanel, lockDoor) .transition(panelClosed).to(idle) ; } } class StateMachineBuilder... public StateMachine build() { initializeIdentifiers(Events.class, Commands.class, States.class, ResetEvents.class); defineStateMachine(); return produceStateMachine(); } abstract protected void defineStateMachine(); private void initializeIdentifiers(Class... identifierClasses) { List<Class> identifierList = Arrays.asList(identifierClasses); for (Field f : this.getClass().getDeclaredFields()) { try { if (identifierList.contains(f.getType())) { f.setAccessible(true); f.set(this, Identifier.create(f.getType(), f.getName(), this)); } } catch (Exception e) { throw new RuntimeException(e); } } } protected void definingState(States identifier) { if (null == start) start = identifier.getState(); } private StateMachine produceStateMachine() { assert null != start; StateMachine result = new StateMachine(start); for (States s : getStateIdentifers()) s.produce(); produceResetEvents(result); return result; } private List<States> getStateIdentifers() { return getIdentifiers(States.class); } private <T extends Identifier> List<T> getIdentifiers(Class<T> klass) { List<T> result = new ArrayList<T>(); for (Field f : this.getClass().getDeclaredFields()) { if (f.getType().equals(klass)) try { f.setAccessible(true); result.add(((T) f.get(this))); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } return result; } private void produceResetEvents(StateMachine result) { result.addResetEvents(getResetEvents()); } private Event[] getResetEvents() { List<Event> result = new ArrayList<Event>(); for (Events identifier : getIdentifiers(ResetEvents.class)) result.add(identifier.getEvent()); return result.toArray(new Event[result.size()]); } } class Identifier... private String name; protected StateMachineBuilder builder; public Identifier(String name, StateMachineBuilder builder) { this.name = name; this.builder = builder; } public String getName() { return name; } static Identifier create(Class type, String name, StateMachineBuilder builder) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Constructor ctor = type.getConstructor(String.class, StateMachineBuilder.class); return (Identifier) ctor.newInstance(name, builder); } public class Events extends Identifier { private Event event; public Events(String name, StateMachineBuilder builder) { super(name, builder); } Event getEvent() { return event; } class Events... public void code(String code) { event = new Event(getName(), code); } } class States... private State content; private List<TransitionBuilder> transitions = new ArrayList<TransitionBuilder>(); private List<Commands> commands = new ArrayList<Commands>(); public States(String name, StateMachineBuilder builder) { super(name, builder); content = new State(name); } public States actions(Commands... identifiers) { builder.definingState(this); commands.addAll(Arrays.asList(identifiers)); return this; } public TransitionBuilder transition(Events identifier) { builder.definingState(this); return new TransitionBuilder(this, identifier); } void produce() { for (Commands c : commands) content.addAction(c.getCommand()); for (TransitionBuilder t : transitions) t.produce(); } class TransitionBuilder... private Events trigger; private States targetState; private States source; TransitionBuilder(States state, Events trigger) { this.trigger = trigger; this.source = state; } public States to(States targetState) { this.targetState = targetState; source.addTransition(this); return source; } void produce() { source.getState().addTransition(trigger.getEvent(), getTargetState().getState()); }
(うーん、でも、結構、ややこしい。)