Add complex showcase sm sample
This commit is contained in:
@@ -115,6 +115,10 @@ configure(sampleProjects()) {
|
||||
apply plugin: 'spring-boot'
|
||||
dependencies {
|
||||
compile project(":spring-statemachine-samples-common")
|
||||
testCompile "org.springframework:spring-test:$springVersion"
|
||||
testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
|
||||
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||
testCompile "junit:junit:$junitVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +180,7 @@ configure(rootProject) {
|
||||
from 'spring-statemachine-core/src/test/java/org/springframework/statemachine/docs'
|
||||
from 'spring-statemachine-samples/src/main/java/'
|
||||
from 'spring-statemachine-samples/turnstile/src/main/java/'
|
||||
from 'spring-statemachine-samples/showcase/src/main/java/'
|
||||
include '**/*.java'
|
||||
into 'docs/src/reference/asciidoc/samples'
|
||||
}
|
||||
|
||||
BIN
docs/src/reference/asciidoc/images/statechart2.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -75,3 +75,39 @@ State changed to LOCKED
|
||||
Event PUSH send
|
||||
----
|
||||
|
||||
== Showcase
|
||||
|
||||
Showcase is a complex state machine showing all possible transition
|
||||
topologies up to four levels of state nesting.
|
||||
|
||||
image::images/statechart2.png[]
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetB]
|
||||
----
|
||||
|
||||
.Events
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetA]
|
||||
----
|
||||
|
||||
.Guard
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetD]
|
||||
----
|
||||
|
||||
.Action
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetE]
|
||||
----
|
||||
|
||||
@@ -4,6 +4,7 @@ include 'spring-statemachine-core'
|
||||
|
||||
include 'spring-statemachine-samples'
|
||||
include 'spring-statemachine-samples:turnstile'
|
||||
include 'spring-statemachine-samples:showcase'
|
||||
|
||||
rootProject.children.find {
|
||||
if (it.name == 'spring-statemachine-samples') {
|
||||
|
||||
@@ -4,3 +4,6 @@ project('spring-statemachine-samples-turnstile') {
|
||||
description = 'Spring State Machine Turnstile Sample'
|
||||
}
|
||||
|
||||
project('spring-statemachine-samples-showcase') {
|
||||
description = 'Spring State Machine Showcase Sample'
|
||||
}
|
||||
|
||||
19
spring-statemachine-samples/showcase/.gitignore
vendored
Normal file
19
spring-statemachine-samples/showcase/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
.gradle
|
||||
bin
|
||||
build
|
||||
.settings
|
||||
.classpath
|
||||
.springBeans
|
||||
.project
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
metastore_db
|
||||
/samples/pig-scripting/src/main/resources/ml-100k.zip
|
||||
/samples/pig-scripting/src/main/resources/ml-100k/u.data
|
||||
/src/test/resources/s3.properties
|
||||
/.idea/
|
||||
.DS_Store
|
||||
/out/
|
||||
target
|
||||
*.log
|
||||
@@ -0,0 +1,154 @@
|
||||
package demo.showcase;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.shell.Bootstrap;
|
||||
import org.springframework.statemachine.StateContext;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
|
||||
@Configuration
|
||||
public class Application {
|
||||
|
||||
//tag::snippetA[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class StateMachineConfig
|
||||
extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.S0)
|
||||
.state(States.S0)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S0)
|
||||
.initial(States.S1)
|
||||
.state(States.S1)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S1)
|
||||
.initial(States.S11)
|
||||
.state(States.S11)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S0)
|
||||
.state(States.S2)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S2)
|
||||
.initial(States.S21)
|
||||
.state(States.S21)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S21)
|
||||
.initial(States.S211)
|
||||
.state(States.S211);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
|
||||
throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S1).event(Events.A)
|
||||
.action(fooAction())
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S11).event(Events.B)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S21).target(States.S211).event(Events.B)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S2).event(Events.C)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S2).target(States.S1).event(Events.C)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S0).event(Events.D)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S211).target(States.S21).event(Events.D)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S0).target(States.S211).event(Events.E)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S211).event(Events.F)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S2).target(States.S11).event(Events.F)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S11).target(States.S211).event(Events.G)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S211).target(States.S0).event(Events.G)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S21).target(States.S21).event(Events.H)
|
||||
.guard(fooGuard());
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooGuard fooGuard() {
|
||||
return new FooGuard();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooAction fooAction() {
|
||||
return new FooAction();
|
||||
}
|
||||
|
||||
}
|
||||
//end::snippetA[]
|
||||
|
||||
//tag::snippetB[]
|
||||
public static enum States {
|
||||
S0, S1, S11, S2, S21, S211
|
||||
}
|
||||
//end::snippetB[]
|
||||
|
||||
//tag::snippetC[]
|
||||
public static enum Events {
|
||||
A, B, C, D, E, F, G, H
|
||||
}
|
||||
//end::snippetC[]
|
||||
|
||||
// tag::snippetD[]
|
||||
private static class FooAction implements Action<States, Events> {
|
||||
|
||||
@Override
|
||||
public void execute(StateContext<States, Events> context) {
|
||||
context.getExtendedState().getVariables().put("foo", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// end::snippetD[]
|
||||
|
||||
// tag::snippetE[]
|
||||
private static class FooGuard implements Guard<States, Events> {
|
||||
|
||||
@Override
|
||||
public boolean evaluate(StateContext<States, Events> context) {
|
||||
Object foo = context.getExtendedState().getVariables().get("foo");
|
||||
return !(foo == null || !foo.equals(1));
|
||||
}
|
||||
}
|
||||
// end::snippetE[]
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Bootstrap.main(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package demo.showcase;
|
||||
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import demo.AbstractStateMachineCommands;
|
||||
import demo.showcase.Application.Events;
|
||||
import demo.showcase.Application.States;
|
||||
|
||||
@Component
|
||||
public class StateMachineCommands extends AbstractStateMachineCommands<States, Events> {
|
||||
|
||||
@CliCommand(value = "sm event", help = "Sends an event to a state machine")
|
||||
public String event(@CliOption(key = { "", "event" }, mandatory = true, help = "The event") final Events event) {
|
||||
getStateMachine().sendEvent(event);
|
||||
return "Event " + event + " send";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
<context:component-scan base-package="demo" />
|
||||
</beans>
|
||||
@@ -0,0 +1,33 @@
|
||||
+---------------------------------------------------------------------------------------------+
|
||||
| S0 |
|
||||
+---------------------------------------------------------------------------------------------+
|
||||
| entry/ |
|
||||
| exit/ |
|
||||
| +-------------------------+ +--------------------------------------------+ |
|
||||
| *-->| S1 | | S2 | |
|
||||
| +-------------------------+ C +--------------------------------------------+ |
|
||||
| | entry/ | | entry/ H | |
|
||||
| D | exit/ |----->| exit/ +-------------------+ | |
|
||||
|<<---------| | | | H[foo.equals(1)]; | | |
|
||||
| | +---------------+ | C | +------------------------------+ | | |
|
||||
| | *-->| S11 | |<-----| *-->| S21 |<--+ | |
|
||||
| | +---------------+ | | +------------------------------+ | |
|
||||
| +--| | entry/ | | F | | entry/ | | |
|
||||
| A| | | exit/ |<---------| | exit/ | | |
|
||||
| +->| | | | | | +--------------+ | | |
|
||||
| A[foo 1]; | B | | | | | *-->| s211 | | | |
|
||||
| |---->| | | | F | +--------------+ | | |
|
||||
| | | | |-------------------->| entry/ | | G | |
|
||||
| | | | | | G | | exit/ |----------------->|
|
||||
| | | |------------------------>| | | | |
|
||||
| | | | | | | B | | | E | |
|
||||
| | | | | | |------>| |<-----------------|
|
||||
| | | | | | | | | | | |
|
||||
| | | | | | | D | | | | |
|
||||
| | | | | | |<------| | | | |
|
||||
| | | | | | | +--------------+ | | |
|
||||
| | +---------------+ | | +------------------------------+ | |
|
||||
| | | | | |
|
||||
| +-------------------------+ +--------------------------------------------+ |
|
||||
| |
|
||||
+---------------------------------------------------------------------------------------------+
|
||||
@@ -0,0 +1,41 @@
|
||||
package demo.showcase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.statemachine.EnumStateMachine;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineSystemConstants;
|
||||
|
||||
import demo.CommonConfiguration;
|
||||
import demo.showcase.Application.Events;
|
||||
import demo.showcase.Application.States;
|
||||
|
||||
public class ShowcaseTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Test
|
||||
public void testApplication() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(CommonConfiguration.class, Application.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachine<States,Events> machine = context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, EnumStateMachine.class);
|
||||
|
||||
machine.start();
|
||||
|
||||
machine.sendEvent(Events.A);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void clean() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
context = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user