|
|
|
|
@@ -0,0 +1,159 @@
|
|
|
|
|
package click.kamil.examples.statemachine.complex;
|
|
|
|
|
|
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
|
import org.springframework.statemachine.action.Action;
|
|
|
|
|
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
|
|
|
|
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
|
|
|
|
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
|
|
|
|
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
|
|
|
|
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
|
|
|
|
import org.springframework.statemachine.guard.Guard;
|
|
|
|
|
|
|
|
|
|
import java.util.EnumSet;
|
|
|
|
|
@Configuration
|
|
|
|
|
@EnableStateMachineFactory(name = "complexStateMachineFactory")
|
|
|
|
|
public class ComplexStateMachineConfig extends StateMachineConfigurerAdapter<ComplexStateMachineConfig.States, ComplexStateMachineConfig.Events> {
|
|
|
|
|
|
|
|
|
|
public enum States {
|
|
|
|
|
STATE1, STATE2, STATE3, STATE4, STATE5,
|
|
|
|
|
STATE6, STATE7, STATE8, STATE9, STATE10,
|
|
|
|
|
STATE11, STATE12, STATE13, STATE14, STATE15,
|
|
|
|
|
STATE16, STATE17, STATE18, STATE19, STATE20
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum Events {
|
|
|
|
|
EVENT1, EVENT2, EVENT3, EVENT4, EVENT5,
|
|
|
|
|
EVENT6, EVENT7, EVENT8, EVENT9, EVENT10,
|
|
|
|
|
EVENT11, EVENT12, EVENT13, EVENT14, EVENT15
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
|
|
|
|
|
config
|
|
|
|
|
.withConfiguration()
|
|
|
|
|
.autoStartup(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
|
|
|
|
|
states
|
|
|
|
|
.withStates()
|
|
|
|
|
.initial(States.STATE1)
|
|
|
|
|
.states(EnumSet.allOf(States.class))
|
|
|
|
|
.stateEntry(States.STATE5, logEntryAction("Entered STATE5"))
|
|
|
|
|
.stateExit(States.STATE10, logExitAction("Exited STATE10"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
|
|
|
|
|
|
|
|
|
|
// External transitions
|
|
|
|
|
transitions
|
|
|
|
|
.withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT1)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE2).target(States.STATE3).event(Events.EVENT2)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE3).target(States.STATE4).event(Events.EVENT3)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE4).target(States.STATE5).event(Events.EVENT4)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE5).target(States.STATE6).event(Events.EVENT5)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE6).target(States.STATE7).event(Events.EVENT6)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE7).target(States.STATE8).event(Events.EVENT7)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE8).target(States.STATE9).event(Events.EVENT8)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE9).target(States.STATE10).event(Events.EVENT9)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE10).target(States.STATE11).event(Events.EVENT10)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE11).target(States.STATE12).event(Events.EVENT11)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE12).target(States.STATE13).event(Events.EVENT12)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE13).target(States.STATE14).event(Events.EVENT13)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE14).target(States.STATE15).event(Events.EVENT14)
|
|
|
|
|
.and()
|
|
|
|
|
.withExternal().source(States.STATE15).target(States.STATE16).event(Events.EVENT15);
|
|
|
|
|
|
|
|
|
|
// Choice transitions (at least 10)
|
|
|
|
|
transitions
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE16)
|
|
|
|
|
.first(States.STATE17, guardVarEquals("value1"))
|
|
|
|
|
.then(States.STATE18, guardVarEquals("value2"))
|
|
|
|
|
.last(States.STATE19)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE17)
|
|
|
|
|
.first(States.STATE20, guardEventHeaderEquals("header1", "foo"))
|
|
|
|
|
.last(States.STATE16)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE18)
|
|
|
|
|
.first(States.STATE19, guardVarEquals("value3"))
|
|
|
|
|
.last(States.STATE20)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE19)
|
|
|
|
|
.first(States.STATE1, guardVarEquals("reset"))
|
|
|
|
|
.last(States.STATE20)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE20)
|
|
|
|
|
.first(States.STATE5, guardEventHeaderEquals("header2", "bar"))
|
|
|
|
|
.last(States.STATE1)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE11)
|
|
|
|
|
.first(States.STATE13, guardVarEquals("goTo13"))
|
|
|
|
|
.then(States.STATE14, guardVarEquals("goTo14"))
|
|
|
|
|
.last(States.STATE15)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE12)
|
|
|
|
|
.first(States.STATE10, guardVarEquals("goBack10"))
|
|
|
|
|
.last(States.STATE11)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE14)
|
|
|
|
|
.first(States.STATE12, guardVarEquals("loop12"))
|
|
|
|
|
.last(States.STATE16)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE9)
|
|
|
|
|
.first(States.STATE8, guardVarEquals("stepBack"))
|
|
|
|
|
.then(States.STATE7, guardVarEquals("stepBackMore"))
|
|
|
|
|
.last(States.STATE6)
|
|
|
|
|
.and()
|
|
|
|
|
.withChoice()
|
|
|
|
|
.source(States.STATE8)
|
|
|
|
|
.first(States.STATE9, guardVarEquals("forward9"))
|
|
|
|
|
.last(States.STATE10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Guard<States, Events> guardVarEquals(String expected) {
|
|
|
|
|
return context -> {
|
|
|
|
|
Object var = context.getExtendedState().getVariables().get("var");
|
|
|
|
|
return expected.equals(var);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Guard<States, Events> guardEventHeaderEquals(String headerName, String expected) {
|
|
|
|
|
return context -> {
|
|
|
|
|
Object header = context.getMessageHeader(headerName);
|
|
|
|
|
return expected.equals(header);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Action<States, Events> logEntryAction(String msg) {
|
|
|
|
|
return context -> System.out.println(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Action<States, Events> logExitAction(String msg) {
|
|
|
|
|
return context -> System.out.println(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|