Pieter van den Hombergh (homberghp) <p.vandenhombergh@fontys.nl> Version 1.0

StateWalker will simplify the coding of your (complex) state machines.

Statewalker implements a hierarchical state pattern variant by using a stack of states. The child-most state is on top, it super state (if any) below it and so on. To change a state the code typically uses one method: changeFromeToState(String message, State from, State…​ to).

The source code and the separate statewalkertest project can be found on github at the url https://github.com/sebivenlo/statewalker.

Apply it to your project:

To make it work in your project, you have to some work yourselves. . Implement a Context that extends BaseContext like this . Extend a State interface with default method handlers for ALL events (methods) relevant to your state machine. . Have a StateEnum implement this State interface. Since the interface has default methods only, a state only has to overwrite any method that is relevant to this state. . You will also need a Device that can be asked from the context and can be manipulated (as in: call methods on it) in the states. What the 'device' is and what it can do is up to you. For a coffee machine it would be the boiler and the lights. For an elevator the door motor and elevator motor. === The Context

class Context extends ContextBase<Context, Dev, State> {

  public Context( Class<?> stateClass ) {
          super( stateClass );
  }

  void e2() {
        getTopState().e2( this );
  } //etc
}

State interface

statewalkertest State interface
package nl.fontys.sebivenlo.statewalkertest;

import nl.fontys.sebivenlo.statewalker.StateBase;

/**
 *
 * @author Pieter van den Hombergh {@code <p.vandenhombergh@fontys.nl>}
 */
public interface State extends StateBase<Context, Dev, State> {
    // <editor-fold formatter-rule="keep-off">
    default void  e1( Context ctx ) { ctx.superState( this ).e1( ctx ); }
    default void  e2( Context ctx ) { ctx.superState( this ).e2( ctx ); }
    default void  e3( Context ctx ) { ctx.superState( this ).e3( ctx ); }
    default void  e4( Context ctx ) { ctx.superState( this ).e4( ctx ); }
    default void  e5( Context ctx ) { ctx.superState( this ).e5( ctx ); }
    default void  e6( Context ctx ) { ctx.superState( this ).e6( ctx ); }
    default void  e7( Context ctx ) { ctx.superState( this ).e7( ctx ); }
    default void  e8( Context ctx ) { ctx.superState( this ).e8( ctx ); }
    default void  e9( Context ctx ) { ctx.superState( this ).e9( ctx ); }
    default void e10( Context ctx ) { ctx.superState( this ).e10( ctx ); }
    default void e11( Context ctx ) { ctx.superState( this ).e11( ctx ); }
    default void e12( Context ctx ) { ctx.superState( this ).e12( ctx ); }
    default void e13( Context ctx ) { ctx.superState( this ).e13( ctx ); }

    @Override
    default void exit( Context ctx ) {}

    @Override
    default void enter( Context ctx ) {}
    // </editor-fold>
}

As you can see all but the pseudo events reach the event down to the next state on the state stack.

Then have an enum implement this interface and give it at least a NULL value.

MyState enum template
enum MyStates extends State {
    S1{
        ...
    },
    S2{
        ...
    },
    S33{

        @Override
        public void enter(Context ctx) {
            ctx.getDevice().heater(true); (1)
        }

        @Override
        public void exit(Context ctx) {
            ctx.getDevice().heater(false); (2)
        }

        @Override
        public void e10(Context ctx) {
            ctx.changeFromToState("e10", this, S31);(3)
        }
    }
    NULL{// handlers for all events with empty bodies
        void e1(Context ctx){}
        ...

            };
}

Explanation:

1 Turns the heater on on entry.
2 Turns the heater off on exit.
3 Changes state to S31, implicitly leaving this state which should automagically call exit on this state, which is S33 and thus turns off the heater.
the device class header
public class Dev implements Device<Context, Dev, State> {

For an example see the maven project statewalkertest in the repository, which implements the state bahavior in the [StateDiagram] below:

Test state machine

State Walker test state machine.

The Java statewalker API doc is also available at API Docs. The maven generated site can be found at StateWalker Maven site.