Java tutorial
/* * 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.Matchers.is; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.messaging.support.MessageBuilder; import org.springframework.statemachine.action.Action; 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.transition.DefaultExternalTransition; import org.springframework.statemachine.transition.DefaultInternalTransition; import org.springframework.statemachine.transition.Transition; import org.springframework.statemachine.trigger.EventTrigger; public class EnumStateMachineTests extends AbstractStateMachineTests { @Test public void testSimpleStateSwitch() { PseudoState<TestStates, TestEvents> pseudoState = new DefaultPseudoState<TestStates, TestEvents>( PseudoStateKind.INITIAL); State<TestStates, TestEvents> stateSI = new EnumState<TestStates, TestEvents>(TestStates.SI, pseudoState); State<TestStates, TestEvents> stateS1 = new EnumState<TestStates, TestEvents>(TestStates.S1); State<TestStates, TestEvents> stateS2 = new EnumState<TestStates, TestEvents>(TestStates.S2); State<TestStates, TestEvents> stateS3 = new EnumState<TestStates, TestEvents>(TestStates.S3); Collection<State<TestStates, TestEvents>> states = new ArrayList<State<TestStates, TestEvents>>(); states.add(stateSI); states.add(stateS1); states.add(stateS2); states.add(stateS3); Collection<Transition<TestStates, TestEvents>> transitions = new ArrayList<Transition<TestStates, TestEvents>>(); Collection<Action<TestStates, TestEvents>> actionsFromSIToS1 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromSIToS1.add(new LoggingAction("actionsFromSIToS1")); DefaultExternalTransition<TestStates, TestEvents> transitionFromSIToS1 = new DefaultExternalTransition<TestStates, TestEvents>( stateSI, stateS1, actionsFromSIToS1, TestEvents.E1, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E1)); Collection<Action<TestStates, TestEvents>> actionsFromS1ToS2 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromS1ToS2.add(new LoggingAction("actionsFromS1ToS2")); DefaultExternalTransition<TestStates, TestEvents> transitionFromS1ToS2 = new DefaultExternalTransition<TestStates, TestEvents>( stateS1, stateS2, actionsFromS1ToS2, TestEvents.E2, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E2)); Collection<Action<TestStates, TestEvents>> actionsFromS2ToS3 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromS1ToS2.add(new LoggingAction("actionsFromS2ToS3")); DefaultExternalTransition<TestStates, TestEvents> transitionFromS2ToS3 = new DefaultExternalTransition<TestStates, TestEvents>( stateS2, stateS3, actionsFromS2ToS3, TestEvents.E3, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E3)); transitions.add(transitionFromSIToS1); transitions.add(transitionFromS1ToS2); transitions.add(transitionFromS2ToS3); SyncTaskExecutor taskExecutor = new SyncTaskExecutor(); BeanFactory beanFactory = new DefaultListableBeanFactory(); ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateSI); machine.setTaskExecutor(taskExecutor); machine.setBeanFactory(beanFactory); machine.afterPropertiesSet(); machine.start(); State<TestStates, TestEvents> initialState = machine.getInitialState(); assertThat(initialState, is(stateSI)); State<TestStates, TestEvents> state = machine.getState(); assertThat(state, is(stateSI)); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build()); state = machine.getState(); assertThat(state, is(stateS1)); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E2).build()); state = machine.getState(); assertThat(state, is(stateS2)); // not processed machine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build()); state = machine.getState(); assertThat(state, is(stateS2)); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E3).build()); state = machine.getState(); assertThat(state, is(stateS3)); } @Test public void testDeferredEvents() { PseudoState<TestStates, TestEvents> pseudoState = new DefaultPseudoState<TestStates, TestEvents>( PseudoStateKind.INITIAL); Collection<TestEvents> deferred = new ArrayList<TestEvents>(); deferred.add(TestEvents.E2); deferred.add(TestEvents.E3); // states State<TestStates, TestEvents> stateSI = new EnumState<TestStates, TestEvents>(TestStates.SI, deferred, null, null, pseudoState); State<TestStates, TestEvents> stateS1 = new EnumState<TestStates, TestEvents>(TestStates.S1); State<TestStates, TestEvents> stateS2 = new EnumState<TestStates, TestEvents>(TestStates.S2); State<TestStates, TestEvents> stateS3 = new EnumState<TestStates, TestEvents>(TestStates.S3); Collection<State<TestStates, TestEvents>> states = new ArrayList<State<TestStates, TestEvents>>(); states.add(stateSI); states.add(stateS1); states.add(stateS2); states.add(stateS3); // transitions Collection<Transition<TestStates, TestEvents>> transitions = new ArrayList<Transition<TestStates, TestEvents>>(); Collection<Action<TestStates, TestEvents>> actionsFromSIToS1 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromSIToS1.add(new LoggingAction("actionsFromSIToS1")); DefaultExternalTransition<TestStates, TestEvents> transitionFromSIToS1 = new DefaultExternalTransition<TestStates, TestEvents>( stateSI, stateS1, actionsFromSIToS1, TestEvents.E1, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E1)); Collection<Action<TestStates, TestEvents>> actionsFromS1ToS2 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromS1ToS2.add(new LoggingAction("actionsFromS1ToS2")); DefaultExternalTransition<TestStates, TestEvents> transitionFromS1ToS2 = new DefaultExternalTransition<TestStates, TestEvents>( stateS1, stateS2, actionsFromS1ToS2, TestEvents.E2, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E2)); Collection<Action<TestStates, TestEvents>> actionsFromS2ToS3 = new ArrayList<Action<TestStates, TestEvents>>(); actionsFromS1ToS2.add(new LoggingAction("actionsFromS2ToS3")); DefaultExternalTransition<TestStates, TestEvents> transitionFromS2ToS3 = new DefaultExternalTransition<TestStates, TestEvents>( stateS2, stateS3, actionsFromS2ToS3, TestEvents.E3, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E3)); transitions.add(transitionFromSIToS1); transitions.add(transitionFromS1ToS2); transitions.add(transitionFromS2ToS3); // create machine SyncTaskExecutor taskExecutor = new SyncTaskExecutor(); BeanFactory beanFactory = new DefaultListableBeanFactory(); ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateSI); machine.setTaskExecutor(taskExecutor); machine.setBeanFactory(beanFactory); machine.afterPropertiesSet(); machine.start(); State<TestStates, TestEvents> initialState = machine.getInitialState(); assertThat(initialState, is(stateSI)); State<TestStates, TestEvents> state = machine.getState(); assertThat(state, is(stateSI)); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E2).build()); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E3).build()); state = machine.getState(); assertThat(state, is(stateSI)); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build()); state = machine.getState(); assertThat(state, is(stateS3)); } @Test public void testInternalTransitions() { PseudoState<TestStates, TestEvents> pseudoState = new DefaultPseudoState<TestStates, TestEvents>( PseudoStateKind.INITIAL); State<TestStates, TestEvents> stateSI = new EnumState<TestStates, TestEvents>(TestStates.SI, pseudoState); Collection<State<TestStates, TestEvents>> states = new ArrayList<State<TestStates, TestEvents>>(); states.add(stateSI); Collection<Action<TestStates, TestEvents>> actionsInSI = new ArrayList<Action<TestStates, TestEvents>>(); actionsInSI.add(new LoggingAction("actionsInSI")); DefaultInternalTransition<TestStates, TestEvents> transitionInternalSI = new DefaultInternalTransition<TestStates, TestEvents>( stateSI, actionsInSI, TestEvents.E1, null, new EventTrigger<TestStates, TestEvents>(TestEvents.E1)); // transitions Collection<Transition<TestStates, TestEvents>> transitions = new ArrayList<Transition<TestStates, TestEvents>>(); transitions.add(transitionInternalSI); SyncTaskExecutor taskExecutor = new SyncTaskExecutor(); BeanFactory beanFactory = new DefaultListableBeanFactory(); ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateSI); machine.setTaskExecutor(taskExecutor); machine.setBeanFactory(beanFactory); machine.afterPropertiesSet(); machine.start(); machine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build()); } private static class LoggingAction implements Action<TestStates, TestEvents> { private static final Log log = LogFactory.getLog(LoggingAction.class); private String message; public LoggingAction(String message) { this.message = message; } @Override public void execute(StateContext<TestStates, TestEvents> context) { log.info("Hello from LoggingAction " + message); } } }