bb.util
Class StateMachine<E extends Enum<E>>

java.lang.Object
  extended by bb.util.StateMachine<E>

public class StateMachine<E extends Enum<E>>
extends Object

Simple implementation of a software state machine.

Currently, this class merely stores state transition rules, and offers the isTransitionAllowed method for users to verify transitions at runtime.

This class is multithread safe: it is immutable (both its immediate state, as well as the deep state of its fields).

Author:
Brent Boyer
See Also:
this forum discussion

Nested Class Summary
static class StateMachine.UnitTest
          See the Overview page of the project's javadocs for a general description of this unit test class.
 
Field Summary
private  EnumMap<E,EnumSet<E>> transitions
          Every key is an initial state, and its corresponding value is the transition rule for that state (i.e. the set of states that are allowed to be transitioned to).
 
Constructor Summary
StateMachine(Class<E> clazz, String... rules)
          Convenience constructor which parses the transition rules from a String.
StateMachine(EnumMap<E,EnumSet<E>> transitions)
          Fundamental constructor.
 
Method Summary
private  EnumMap<E,EnumSet<E>> checkTransitions(EnumMap<E,EnumSet<E>> transitions)
           
private  EnumMap<E,EnumSet<E>> cloneDeep(EnumMap<E,EnumSet<E>> transitions)
           
 boolean isTransitionAllowed(E stateInitial, E stateFinal)
           
private  E parseStateInitial(Class<E> clazz, String rule)
           
private  EnumSet<E> parseStatesFinal(Class<E> clazz, String rule)
           
private  EnumMap<E,EnumSet<E>> parseTransitions(Class<E> clazz, String... rules)
          Parses rules into an EnumMap.
 String toString()
          Returns a String representation of transitions.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

transitions

private final EnumMap<E extends Enum<E>,EnumSet<E extends Enum<E>>> transitions
Every key is an initial state, and its corresponding value is the transition rule for that state (i.e. the set of states that are allowed to be transitioned to).

Contract: is never null, defines a non-empty transition rule for every value of E, and must never be modified.

Constructor Detail

StateMachine

public StateMachine(EnumMap<E,EnumSet<E>> transitions)
             throws IllegalArgumentException
Fundamental constructor.

Throws:
IllegalArgumentException - if the transitions arg violates the contract of the transitions field.

StateMachine

public StateMachine(Class<E> clazz,
                    String... rules)
             throws IllegalArgumentException
Convenience constructor which parses the transition rules from a String.

Throws:
IllegalArgumentException - if the parsing fails, or its result violates the contract of the transitions field.
Method Detail

checkTransitions

private EnumMap<E,EnumSet<E>> checkTransitions(EnumMap<E,EnumSet<E>> transitions)
                                                                        throws IllegalArgumentException
Throws:
IllegalArgumentException

cloneDeep

private EnumMap<E,EnumSet<E>> cloneDeep(EnumMap<E,EnumSet<E>> transitions)

parseTransitions

private EnumMap<E,EnumSet<E>> parseTransitions(Class<E> clazz,
                                               String... rules)
                                                                        throws IllegalArgumentException
Parses rules into an EnumMap.

Each element of rules is a state transition rule. Its format is stateInitial followed by a "-->" followed by statesFinal, which must be a comma (',') delimited list of states. Optional whitespace may appear around any token in the above format. Every state in the enum referred to by clazz must have one and only one transition rule in rules.

Throws:
IllegalArgumentException - if rules is blank or some format error occurs

parseStateInitial

private E parseStateInitial(Class<E> clazz,
                            String rule)
                                     throws IllegalArgumentException
Throws:
IllegalArgumentException

parseStatesFinal

private EnumSet<E> parseStatesFinal(Class<E> clazz,
                                    String rule)
                                             throws IllegalArgumentException
Throws:
IllegalArgumentException

toString

public String toString()
Returns a String representation of transitions.

Contract: the result must be compatible with parseTransitions(java.lang.Class, java.lang.String...), that is, parseTransitions( stateMachine.toString() ) must always succeed.

Overrides:
toString in class Object

isTransitionAllowed

public boolean isTransitionAllowed(E stateInitial,
                                   E stateFinal)
                            throws IllegalArgumentException
Throws:
IllegalArgumentException