/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.statemachine;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
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.state.DefaultPseudoState;
import org.springframework.statemachine.state.EnumState;
import org.springframework.statemachine.state.PseudoState;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.state.StateMachineState;
import org.springframework.statemachine.transition.DefaultExternalTransition;
import org.springframework.statemachine.transition.DefaultLocalTransition;
import org.springframework.statemachine.transition.Transition;
import org.springframework.statemachine.trigger.EventTrigger;
public class SubStateMachineTests extends AbstractStateMachineTests {
@Override
protected AnnotationConfigApplicationContext buildContext() {
return new AnnotationConfigApplicationContext();
}
@Test
public void testExternalTransition() throws Exception {
/**
* +-------------------------------------------+
* *-init->| S1 |
* +-------------------------------------------+
* | entry/ |
* | exit/ |
* | +--------------------------+ |
* | *-->| S11 | |
* | +--------------------------+ |
* | | entry/ | |
* | | exit/ | |
* | | +-----------+ | |
* | | *-->| S111 | | |
* | | +-----------+ | |
* | | | entry/ | | |
* |<----E1-----------| exit/ | | |
* | | | | | |
* | | +-----------+ | |
* | | | |
* | +--------------------------+ |
* | |
* +-------------------------------------------+
*/
PseudoState<TestStates,TestEvents> pseudoState = new DefaultPseudoState<TestStates,TestEvents>(PseudoStateKind.INITIAL);
TestEntryAction entryActionS111 = new TestEntryAction("S111");
TestExitAction exitActionS111 = new TestExitAction("S111");
Collection<Action<TestStates, TestEvents>> entryActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS111.add(entryActionS111);
Collection<Action<TestStates, TestEvents>> exitActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS111.add(exitActionS111);
State<TestStates,TestEvents> stateS111 = new EnumState<TestStates,TestEvents>(TestStates.S111, null, entryActionsS111, exitActionsS111, pseudoState);
// submachine 11
Collection<State<TestStates,TestEvents>> substates111 = new ArrayList<State<TestStates,TestEvents>>();
substates111.add(stateS111);
Collection<Transition<TestStates,TestEvents>> subtransitions111 = new ArrayList<Transition<TestStates,TestEvents>>();
ObjectStateMachine<TestStates, TestEvents> submachine11 = new ObjectStateMachine<TestStates, TestEvents>(substates111, subtransitions111, stateS111);
// submachine 1
TestEntryAction entryActionS11 = new TestEntryAction("S11");
TestExitAction exitActionS11 = new TestExitAction("S11");
Collection<Action<TestStates, TestEvents>> entryActionsS11 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS11.add(entryActionS11);
Collection<Action<TestStates, TestEvents>> exitActionsS11 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS11.add(exitActionS11);
StateMachineState<TestStates,TestEvents> stateS11 = new StateMachineState<TestStates,TestEvents>(TestStates.S11, submachine11, null, entryActionsS11, exitActionsS11, pseudoState);
Collection<State<TestStates,TestEvents>> substates11 = new ArrayList<State<TestStates,TestEvents>>();
substates11.add(stateS11);
Collection<Transition<TestStates,TestEvents>> subtransitions11 = new ArrayList<Transition<TestStates,TestEvents>>();
ObjectStateMachine<TestStates, TestEvents> submachine1 = new ObjectStateMachine<TestStates, TestEvents>(substates11, subtransitions11, stateS11);
// machine
TestEntryAction entryActionS1 = new TestEntryAction("S1");
TestExitAction exitActionS1 = new TestExitAction("S1");
Collection<Action<TestStates, TestEvents>> entryActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS1.add(entryActionS1);
Collection<Action<TestStates, TestEvents>> exitActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS1.add(exitActionS1);
StateMachineState<TestStates,TestEvents> stateS1 = new StateMachineState<TestStates,TestEvents>(TestStates.S1, submachine1, null, entryActionsS1, exitActionsS1, pseudoState);
Collection<State<TestStates,TestEvents>> states = new ArrayList<State<TestStates,TestEvents>>();
states.add(stateS1);
Collection<Transition<TestStates,TestEvents>> transitions = new ArrayList<Transition<TestStates,TestEvents>>();
DefaultExternalTransition<TestStates,TestEvents> transitionFromS111ToS1 =
new DefaultExternalTransition<TestStates,TestEvents>(stateS111, stateS1, null, TestEvents.E1, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E1));
transitions.add(transitionFromS111ToS1);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateS1);
SyncTaskExecutor taskExecutor = new SyncTaskExecutor();
BeanFactory beanFactory = new DefaultListableBeanFactory();
machine.setTaskExecutor(taskExecutor);
machine.setBeanFactory(beanFactory);
machine.afterPropertiesSet();
submachine1.setTaskExecutor(taskExecutor);
submachine1.setBeanFactory(beanFactory);
submachine1.afterPropertiesSet();
submachine11.setTaskExecutor(taskExecutor);
submachine11.setBeanFactory(beanFactory);
submachine11.afterPropertiesSet();
machine.start();
machine.sendEvent(TestEvents.E1);
assertThat(entryActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS111.stateContexts.size(), is(2));
assertThat(exitActionS111.stateContexts.size(), is(1));
assertThat(entryActionS11.stateContexts.size(), is(2));
assertThat(exitActionS11.stateContexts.size(), is(1));
assertThat(entryActionS1.stateContexts.size(), is(1));
assertThat(exitActionS1.stateContexts.size(), is(1));
}
@Test
public void testExternalTransition2() throws Exception {
/**
* +---------------------------------------------------+
* *-init->| S1 |
* +---------------------------------------------------+
* | entry/ |
* | exit/ |
* | +-----------+ +-----------+ |
* | *-->| S111 | | S112 | |
* | +-----------+ +-----------+ |
* | | entry/ | | entry/ | |
* | | exit/ |----E1--->| exit/ | |
* | | | | | |
* | | |<---E2----| | |
* | | | | | |
* | +-----------+ +-----------+ |
* | |
* +---------------------------------------------------+
*/
PseudoState<TestStates,TestEvents> pseudoState = new DefaultPseudoState<TestStates,TestEvents>(PseudoStateKind.INITIAL);
TestEntryAction entryActionS111 = new TestEntryAction("S111");
TestExitAction exitActionS111 = new TestExitAction("S111");
Collection<Action<TestStates, TestEvents>> entryActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS111.add(entryActionS111);
Collection<Action<TestStates, TestEvents>> exitActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS111.add(exitActionS111);
State<TestStates,TestEvents> stateS111 = new EnumState<TestStates,TestEvents>(TestStates.S111, null, entryActionsS111, exitActionsS111, pseudoState);
TestEntryAction entryActionS112 = new TestEntryAction("S112");
TestExitAction exitActionS112 = new TestExitAction("S112");
Collection<Action<TestStates, TestEvents>> entryActionsS112 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS112.add(entryActionS112);
Collection<Action<TestStates, TestEvents>> exitActionsS112 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS112.add(exitActionS112);
State<TestStates,TestEvents> stateS112 = new EnumState<TestStates,TestEvents>(TestStates.S112, null, entryActionsS112, exitActionsS112, null);
// submachine 1
Collection<State<TestStates,TestEvents>> substates11 = new ArrayList<State<TestStates,TestEvents>>();
substates11.add(stateS111);
substates11.add(stateS112);
Collection<Transition<TestStates,TestEvents>> subtransitions11 = new ArrayList<Transition<TestStates,TestEvents>>();
ObjectStateMachine<TestStates, TestEvents> submachine11 = new ObjectStateMachine<TestStates, TestEvents>(substates11, subtransitions11, stateS111);
// machine
TestEntryAction entryActionS1 = new TestEntryAction("S1");
TestExitAction exitActionS1 = new TestExitAction("S1");
Collection<Action<TestStates, TestEvents>> entryActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS1.add(entryActionS1);
Collection<Action<TestStates, TestEvents>> exitActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS1.add(exitActionS1);
StateMachineState<TestStates,TestEvents> stateS1 = new StateMachineState<TestStates,TestEvents>(TestStates.S1, submachine11, null, entryActionsS1, exitActionsS1, pseudoState);
Collection<State<TestStates,TestEvents>> states = new ArrayList<State<TestStates,TestEvents>>();
states.add(stateS1);
Collection<Transition<TestStates,TestEvents>> transitions = new ArrayList<Transition<TestStates,TestEvents>>();
DefaultExternalTransition<TestStates,TestEvents> transitionFromS111ToS112 =
new DefaultExternalTransition<TestStates,TestEvents>(stateS111, stateS112, null, TestEvents.E1, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E1));
transitions.add(transitionFromS111ToS112);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateS1);
SyncTaskExecutor taskExecutor = new SyncTaskExecutor();
BeanFactory beanFactory = new DefaultListableBeanFactory();
machine.setTaskExecutor(taskExecutor);
machine.setBeanFactory(beanFactory);
machine.afterPropertiesSet();
submachine11.setTaskExecutor(taskExecutor);
submachine11.setBeanFactory(beanFactory);
submachine11.afterPropertiesSet();
machine.start();
machine.sendEvent(TestEvents.E1);
assertThat(entryActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS112.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS112.onExecuteLatch.await(1, TimeUnit.SECONDS), is(false));
assertThat(entryActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(false));
assertThat(entryActionS111.stateContexts.size(), is(1));
assertThat(exitActionS111.stateContexts.size(), is(1));
assertThat(entryActionS112.stateContexts.size(), is(1));
assertThat(exitActionS112.stateContexts.size(), is(0));
assertThat(entryActionS1.stateContexts.size(), is(1));
assertThat(exitActionS1.stateContexts.size(), is(0));
}
@Test
public void testLocalTransition() throws Exception {
/**
* +-------------------------------------------+
* *-init->| S1 |
* +-------------------------------------------+
* | entry/ |
* | exit/ |
* | +--------------------------+ |
* | *-->| S11 | |
* | +--------------------------+ |
* | | entry/ | |
* | | exit/ | |
* | | +-----------+ | |
* | | *-->| S111 | | |
* | | +-----------+ | |
* | | | entry/ | | |
* |<----E1-----------| exit/ | | |
* | | | | | |
* | | +-----------+ | |
* | | | |
* | +--------------------------+ |
* | |
* +-------------------------------------------+
*/
PseudoState<TestStates,TestEvents> pseudoState = new DefaultPseudoState<TestStates,TestEvents>(PseudoStateKind.INITIAL);
TestEntryAction entryActionS111 = new TestEntryAction("S111");
TestExitAction exitActionS111 = new TestExitAction("S111");
Collection<Action<TestStates, TestEvents>> entryActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS111.add(entryActionS111);
Collection<Action<TestStates, TestEvents>> exitActionsS111 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS111.add(exitActionS111);
State<TestStates,TestEvents> stateS111 = new EnumState<TestStates,TestEvents>(TestStates.S111, null, entryActionsS111, exitActionsS111, pseudoState);
// submachine 11
Collection<State<TestStates,TestEvents>> substates111 = new ArrayList<State<TestStates,TestEvents>>();
substates111.add(stateS111);
Collection<Transition<TestStates,TestEvents>> subtransitions111 = new ArrayList<Transition<TestStates,TestEvents>>();
ObjectStateMachine<TestStates, TestEvents> submachine11 = new ObjectStateMachine<TestStates, TestEvents>(substates111, subtransitions111, stateS111);
// submachine 1
TestEntryAction entryActionS11 = new TestEntryAction("S11");
TestExitAction exitActionS11 = new TestExitAction("S11");
Collection<Action<TestStates, TestEvents>> entryActionsS11 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS11.add(entryActionS11);
Collection<Action<TestStates, TestEvents>> exitActionsS11 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS11.add(exitActionS11);
StateMachineState<TestStates,TestEvents> stateS11 = new StateMachineState<TestStates,TestEvents>(TestStates.S11, submachine11, null, entryActionsS11, exitActionsS11, pseudoState);
Collection<State<TestStates,TestEvents>> substates11 = new ArrayList<State<TestStates,TestEvents>>();
substates11.add(stateS11);
Collection<Transition<TestStates,TestEvents>> subtransitions11 = new ArrayList<Transition<TestStates,TestEvents>>();
ObjectStateMachine<TestStates, TestEvents> submachine1 = new ObjectStateMachine<TestStates, TestEvents>(substates11, subtransitions11, stateS11);
// machine
TestEntryAction entryActionS1 = new TestEntryAction("S1");
TestExitAction exitActionS1 = new TestExitAction("S1");
Collection<Action<TestStates, TestEvents>> entryActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
entryActionsS1.add(entryActionS1);
Collection<Action<TestStates, TestEvents>> exitActionsS1 = new ArrayList<Action<TestStates, TestEvents>>();
exitActionsS1.add(exitActionS1);
StateMachineState<TestStates,TestEvents> stateS1 = new StateMachineState<TestStates,TestEvents>(TestStates.S1, submachine1, null, entryActionsS1, exitActionsS1, pseudoState);
Collection<State<TestStates,TestEvents>> states = new ArrayList<State<TestStates,TestEvents>>();
states.add(stateS1);
Collection<Transition<TestStates,TestEvents>> transitions = new ArrayList<Transition<TestStates,TestEvents>>();
DefaultLocalTransition<TestStates,TestEvents> transitionFromS11ToS1 =
new DefaultLocalTransition<TestStates,TestEvents>(stateS111, stateS1, null, TestEvents.E1, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E1));
transitions.add(transitionFromS11ToS1);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateS1);
SyncTaskExecutor taskExecutor = new SyncTaskExecutor();
BeanFactory beanFactory = new DefaultListableBeanFactory();
machine.setTaskExecutor(taskExecutor);
machine.setBeanFactory(beanFactory);
machine.afterPropertiesSet();
submachine1.setTaskExecutor(taskExecutor);
submachine1.setBeanFactory(beanFactory);
submachine1.afterPropertiesSet();
submachine11.setTaskExecutor(taskExecutor);
submachine11.setBeanFactory(beanFactory);
submachine11.afterPropertiesSet();
machine.start();
machine.sendEvent(TestEvents.E1);
assertThat(entryActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(false));
assertThat(entryActionS111.stateContexts.size(), is(2));
assertThat(exitActionS111.stateContexts.size(), is(1));
assertThat(entryActionS11.stateContexts.size(), is(1));
assertThat(exitActionS11.stateContexts.size(), is(1));
assertThat(entryActionS1.stateContexts.size(), is(1));
assertThat(exitActionS1.stateContexts.size(), is(0));
}
@Test
public void testExternalTransition3() throws Exception {
context.register(BaseConfig.class, Config1.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
@SuppressWarnings("unchecked")
ObjectStateMachine<TestStates,TestEvents> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
machine.start();
machine.sendEvent(TestEvents.E1);
TestEntryAction entryActionS111 = context.getBean("entryActionS111", TestEntryAction.class);
TestExitAction exitActionS111 = context.getBean("exitActionS111", TestExitAction.class);
TestEntryAction entryActionS11 = context.getBean("entryActionS11", TestEntryAction.class);
TestExitAction exitActionS11 = context.getBean("exitActionS11", TestExitAction.class);
TestEntryAction entryActionS1 = context.getBean("entryActionS1", TestEntryAction.class);
TestExitAction exitActionS1 = context.getBean("exitActionS1", TestExitAction.class);
assertThat(entryActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS111.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS11.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(exitActionS1.onExecuteLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(entryActionS111.stateContexts.size(), is(2));
assertThat(exitActionS111.stateContexts.size(), is(1));
assertThat(entryActionS11.stateContexts.size(), is(2));
assertThat(exitActionS11.stateContexts.size(), is(1));
assertThat(entryActionS1.stateContexts.size(), is(1));
assertThat(exitActionS1.stateContexts.size(), is(1));
}
@Test
public void testMixedStates() throws Exception {
context.register(BaseConfig.class, Config2.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
@SuppressWarnings("unchecked")
ObjectStateMachine<TestStates,TestEvents> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
machine.start();
assertThat(machine, notNullValue());
assertThat(machine.getState().getIds(), contains(TestStates.S1, TestStates.S10));
}
@Test
public void testStateChangeWithinMachine() {
context.register(BaseConfig.class, Config3.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
@SuppressWarnings("unchecked")
ObjectStateMachine<TestStates2,TestEvents2> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
machine.start();
assertThat(machine, notNullValue());
assertThat(machine.getState().getIds(), contains(TestStates2.IDLE, TestStates2.CLOSED));
machine.sendEvent(TestEvents2.EJECT);
assertThat(machine.getState().getIds(), contains(TestStates2.IDLE, TestStates2.OPEN));
}
@Configuration
@EnableStateMachine
public static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.S1)
.state(TestStates.S1, Arrays.asList(entryActionS1()), Arrays.asList(exitActionS1()))
.and()
.withStates()
.parent(TestStates.S1)
.initial(TestStates.S11)
.state(TestStates.S11, Arrays.asList(entryActionS11()), Arrays.asList(exitActionS11()))
.and()
.withStates()
.parent(TestStates.S11)
.initial(TestStates.S111)
.state(TestStates.S111, Arrays.asList(entryActionS111()), Arrays.asList(exitActionS111()));
}
@Override
public void configure(StateMachineTransitionConfigurer<TestStates, TestEvents> transitions) throws Exception {
transitions
.withExternal()
.source(TestStates.S111)
.target(TestStates.S1)
.event(TestEvents.E1);
}
@Bean(name = "entryActionS111")
public Action<TestStates, TestEvents> entryActionS111() {
return new TestEntryAction("S111");
}
@Bean(name = "exitActionS111")
public Action<TestStates, TestEvents> exitActionS111() {
return new TestExitAction("S111");
}
@Bean(name = "entryActionS11")
public Action<TestStates, TestEvents> entryActionS11() {
return new TestEntryAction("S11");
}
@Bean(name = "exitActionS11")
public Action<TestStates, TestEvents> exitActionS11() {
return new TestExitAction("S11");
}
@Bean(name = "entryActionS1")
public Action<TestStates, TestEvents> entryActionS1() {
return new TestEntryAction("S1");
}
@Bean(name = "exitActionS1")
public Action<TestStates, TestEvents> exitActionS1() {
return new TestExitAction("S1");
}
}
@Configuration
@EnableStateMachine
static class Config2 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineConfigurationConfigurer<TestStates, TestEvents> config) throws Exception {
config
.withVerifier()
.enabled(false);
}
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.S1)
.state(TestStates.S1)
.state(TestStates.S2)
.and()
.withStates()
.parent(TestStates.S1)
.initial(TestStates.S10)
.state(TestStates.S10);
}
}
@Configuration
@EnableStateMachine
static class Config3 extends EnumStateMachineConfigurerAdapter<TestStates2, TestEvents2> {
@Override
public void configure(StateMachineStateConfigurer<TestStates2, TestEvents2> states) throws Exception {
states
.withStates()
.initial(TestStates2.IDLE)
.state(TestStates2.IDLE)
.and()
.withStates()
.parent(TestStates2.IDLE)
.initial(TestStates2.CLOSED)
.state(TestStates2.CLOSED)
.state(TestStates2.OPEN)
.and()
.withStates()
.state(TestStates2.BUSY)
.and()
.withStates()
.parent(TestStates2.BUSY)
.initial(TestStates2.PLAYING)
.state(TestStates2.PLAYING)
.state(TestStates2.PAUSED);
}
@Override
public void configure(StateMachineTransitionConfigurer<TestStates2, TestEvents2> transitions) throws Exception {
transitions
.withExternal()
.source(TestStates2.CLOSED)
.target(TestStates2.OPEN)
.event(TestEvents2.EJECT)
.and()
.withExternal()
.source(TestStates2.OPEN)
.target(TestStates2.CLOSED)
.event(TestEvents2.EJECT);
}
}
}