one more example

This commit is contained in:
2026-06-07 09:58:39 +02:00
parent b268639074
commit 2ecc8e08de
13 changed files with 423 additions and 15 deletions

View File

@@ -0,0 +1,27 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer;
import java.util.function.Consumer;
import java.util.stream.Stream;
class AbstractStateMachineConfiguration<S,E> extends StateMachineConfigurerAdapter<S,E> {
protected void addTransitionForMultipleEvents(
StateMachineTransitionConfigurer<S, E> transitions,
S source,
S target,
Consumer<ExternalTransitionConfigurer<S,E>> transitionCustomizer,
E... events) {
Stream.of(events).forEach(event -> {
try {
ExternalTransitionConfigurer<S, E> transitionConfigurer =
transitions.withExternal().event(event).source(source).target(target);
transitionCustomizer.accept(transitionConfigurer);
} catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
}

View File

@@ -0,0 +1,203 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2;
import org.springframework.statemachine.action.Action;
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.config.configurers.ExternalTransitionConfigurer;
import org.springframework.statemachine.config.configurers.StateConfigurer;
import org.springframework.statemachine.guard.Guard;
abstract class AbstractThreeStateMachineConfiguration extends AbstractStateMachineConfiguration<States, Events> {
protected abstract void addAdditionalStates(StateConfigurer<States, Events> states);
protected abstract void addAdditionalCancellationTransitions(StateMachineTransitionConfigurer<States, Events> transitions);
protected abstract void addAdditionalTransitions(ExternalTransitionConfigurer<States, Events> transitions) throws Exception;
protected void addAllCancellationTransitionsForSource(StateMachineTransitionConfigurer<States, Events> transitions, States source) {
addCancellationTransitionForCancelEvents(transitions, source, Events.EVENT_CANCEL_2);
}
private void addCancellationTransitionForCancelEvents(
StateMachineTransitionConfigurer<States, Events> transitions,
States source,
Events... cancelEvents) {
addTransitionForMultipleEvents(
transitions,
source,
States.CANCEL,
transitionConfigurer -> transitionConfigurer.action((context) -> System.out.println(context.getEvent().toString() + " " + context.getTransition().toString())),
cancelEvents
);
}
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
config
.withConfiguration()
.autoStartup(true);
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
StateConfigurer<States, Events> end = states
.withStates()
.initial(States.STATE1)
.state(States.STATE2)
.state(States.STATE3)
.state(States.STATE4)
.state(States.STATE5)
.state(States.STATE6)
.state(States.STATE7)
.state(States.STATE8)
.state(States.STATE9)
.state(States.STATE10)
.state(States.STATE11)
.state(States.STATE12)
.state(States.STATE13)
.state(States.STATE14)
.state(States.STATE15)
.state(States.STATE16)
.state(States.STATE17)
.state(States.STATE18)
.state(States.STATE19)
.state(States.STATE20)
.state(States.STATEX)
.choice(States.STATEY)
.end(States.STATEZ);
addAdditionalStates(end);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
// External transitions
ExternalTransitionConfigurer<States, Events> t1 = 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);
transitions.withExternal().source(States.STATE1).target(States.CANCEL).event(Events.EVENT_CANCEL)
.and()
.withExternal().source(States.STATE2).target(States.CANCEL).event(Events.EVENT_CANCEL)
.and()
.withExternal().source(States.STATE3).target(States.CANCEL).event(Events.EVENT_CANCEL)
.and()
.withExternal().source(States.STATE4).target(States.CANCEL).event(Events.EVENT_CANCEL)
.and()
.withExternal().source(States.STATE5).target(States.CANCEL).event(Events.EVENT_CANCEL);
// EXTRA CHOICE
transitions.withExternal().source(States.STATE4).target(States.STATEY).event(Events.EVENTY);
transitions.withChoice().source(States.STATEY).first(States.STATEX, guardVarEquals("value1")).last(States.STATEZ);
// 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);
addAdditionalTransitions(t1);
addAdditionalCancellationTransitions(transitions);
}
protected Guard<States, Events> guardVarEquals(String expected) {
return context -> {
Object var = context.getExtendedState().getVariables().get("var");
return expected.equals(var);
};
}
protected 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);
}
}

View File

@@ -0,0 +1,8 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2;
public enum Events {
EVENT1, EVENT2, EVENT3, EVENT4, EVENT5,
EVENT6, EVENT7, EVENT8, EVENT9, EVENT10,
EVENT11, EVENT12, EVENT13, EVENT14, EVENT15,
EVENTX, EVENTY, EVENTZ, EVENT_CANCEL, EVENT_CANCEL_2
}

View File

@@ -0,0 +1,9 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2;
public enum States {
STATE1, STATE2, STATE3, STATE4, STATE5,
STATE6, STATE7, STATE8, STATE9, STATE10,
STATE11, STATE12, STATE13, STATE14, STATE15,
STATE16, STATE17, STATE18, STATE19, STATE20,
STATEX, STATEY, STATEZ, STATE_EXTRA_1, STATE_EXTRA_2, STATE_EXTRA_3, CANCEL
}

View File

@@ -0,0 +1,40 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer;
import org.springframework.statemachine.config.configurers.StateConfigurer;
class ThreeStateMachineConfiguration extends AbstractThreeStateMachineConfiguration {
@Override
protected void addAdditionalStates(StateConfigurer<States, Events> states) {
states.state(States.STATE_EXTRA_1);
states.state(States.STATE_EXTRA_2);
states.state(States.STATE_EXTRA_3);
}
@Override
protected void addAdditionalCancellationTransitions(StateMachineTransitionConfigurer<States, Events> transitions) {
addAllCancellationTransitionsForSource(transitions, States.STATE_EXTRA_1);
addAllCancellationTransitionsForSource(transitions, States.STATE_EXTRA_2);
}
@Override
protected void addAdditionalTransitions(ExternalTransitionConfigurer<States, Events> transitions) throws Exception {
transitions
.and()
.withExternal().event(Events.EVENTX)
.source(States.STATE2)
.target(States.STATE_EXTRA_1)
.and()
.withChoice()
.source(States.STATE2)
.first(States.STATE1, guardEventHeaderEquals("header1", "foo"))
.last(States.STATE_EXTRA_1)
.and()
.withExternal()
.source(States.STATE_EXTRA_1)
.event(Events.EVENTY)
.target(States.STATE_EXTRA_3);
}
}

View File

@@ -0,0 +1,11 @@
package click.kamil.examples.statemachine.inheritanceextrafunctionsstate2.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
class StateMachineApplication {
public static void main(String[] args) {
SpringApplication.run(StateMachineApplication.class, args);
}
}

View File

@@ -0,0 +1 @@
spring.application.name=statemachinedemo

View File

@@ -0,0 +1,11 @@
package click.kamil.examples.statemachine;
import org.junit.jupiter.api.Test;
class MyTest {
@Test
void contextLoads() {
}
}