Fix local transition logic
- Add missing creating of a local transition - Fix logic how entry/exit is not called with local - Add tests comparing functionality with external - Fixes #248 - Fixes #249
This commit is contained in:
@@ -78,6 +78,7 @@ import org.springframework.statemachine.support.tree.TreeTraverser;
|
||||
import org.springframework.statemachine.support.tree.Tree.Node;
|
||||
import org.springframework.statemachine.transition.DefaultExternalTransition;
|
||||
import org.springframework.statemachine.transition.DefaultInternalTransition;
|
||||
import org.springframework.statemachine.transition.DefaultLocalTransition;
|
||||
import org.springframework.statemachine.transition.InitialTransition;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
import org.springframework.statemachine.transition.TransitionKind;
|
||||
@@ -716,6 +717,15 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
transitionData.getSecurityRule(), transitionData.getErrorAction());
|
||||
transitions.add(transition);
|
||||
|
||||
} else if (transitionData.getKind() == TransitionKind.LOCAL) {
|
||||
// TODO can we do this?
|
||||
if (stateMap.get(source) == null || stateMap.get(target) == null) {
|
||||
continue;
|
||||
}
|
||||
DefaultLocalTransition<S, E> transition = new DefaultLocalTransition<S, E>(stateMap.get(source),
|
||||
stateMap.get(target), transitionData.getActions(), event, transitionData.getGuard(), trigger,
|
||||
transitionData.getSecurityRule(), transitionData.getErrorAction());
|
||||
transitions.add(transition);
|
||||
} else if (transitionData.getKind() == TransitionKind.INTERNAL) {
|
||||
DefaultInternalTransition<S, E> transition = new DefaultInternalTransition<S, E>(stateMap.get(source),
|
||||
transitionData.getActions(), event, transitionData.getGuard(), trigger,
|
||||
|
||||
@@ -207,6 +207,17 @@ public class StateMachineState<S, E> extends AbstractState<S, E> {
|
||||
((StateMachineState<S, E>) immediateDeepParent).getSubmachine().getStateMachineAccessor()
|
||||
.doWithRegion(new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
|
||||
@Override
|
||||
public void apply(StateMachineAccess<S, E> function) {
|
||||
function.setInitialEnabled(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (immediateDeepParent == null && getSubmachine().getStates().contains(target) && !isInitial(target)
|
||||
&& StateMachineUtils.isSubstate(context.getTransition().getSource(), context.getTransition().getTarget())) {
|
||||
getSubmachine().getStateMachineAccessor().doWithRegion(
|
||||
new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
|
||||
@Override
|
||||
public void apply(StateMachineAccess<S, E> function) {
|
||||
function.setInitialEnabled(false);
|
||||
|
||||
@@ -867,7 +867,6 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
|
||||
synchronized void setCurrentState(State<S, E> state, Message<E> message, Transition<S, E> transition, boolean exit,
|
||||
StateMachine<S, E> stateMachine, Collection<State<S, E>> sources, Collection<State<S, E>> targets) {
|
||||
|
||||
State<S, E> findDeep = findDeepParent(state);
|
||||
boolean isTargetSubOf = false;
|
||||
if (transition != null) {
|
||||
@@ -1026,6 +1025,12 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
boolean isSubOfSource = StateMachineUtils.isSubstate(transition.getSource(), currentState);
|
||||
boolean isSubOfTarget = StateMachineUtils.isSubstate(transition.getTarget(), currentState);
|
||||
|
||||
if (transition.getKind() == TransitionKind.LOCAL && StateMachineUtils.isSubstate(transition.getSource(), transition.getTarget()) && transition.getSource() == currentState) {
|
||||
return;
|
||||
} else if (transition.getKind() == TransitionKind.LOCAL && StateMachineUtils.isSubstate(transition.getTarget(), transition.getSource()) && transition.getTarget() == currentState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: this and entry below should be done via a separate
|
||||
// voter of some sort which would reveal transition path
|
||||
// we could make a choice on.
|
||||
@@ -1083,15 +1088,26 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
|
||||
boolean isSubOfSource = StateMachineUtils.isSubstate(transition.getSource(), currentState);
|
||||
boolean isSubOfTarget = StateMachineUtils.isSubstate(transition.getTarget(), currentState);
|
||||
|
||||
if (transition.getKind() == TransitionKind.LOCAL && StateMachineUtils.isSubstate(transition.getSource(), transition.getTarget())
|
||||
&& transition.getSource() == currentState) {
|
||||
return;
|
||||
} else if (transition.getKind() == TransitionKind.LOCAL && StateMachineUtils.isSubstate(transition.getTarget(), transition.getSource())
|
||||
&& transition.getTarget() == currentState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentState == transition.getSource() && currentState == transition.getTarget()) {
|
||||
} else if (!isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) {
|
||||
} else if (isComingFromOtherSubmachine) {
|
||||
} else if (!isSubOfSource && !isSubOfTarget && findDeep2 == null) {
|
||||
} else if (isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) {
|
||||
if (isDirectSubstate(transition.getSource(), transition.getTarget())) {
|
||||
if (isDirectSubstate(transition.getSource(), transition.getTarget()) && transition.getKind() != TransitionKind.LOCAL
|
||||
&& isInitial(transition.getTarget())) {
|
||||
return;
|
||||
}
|
||||
} else if (!isSubOfSource && !isSubOfTarget && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) {
|
||||
} else if (!isSubOfSource && !isSubOfTarget
|
||||
&& (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) {
|
||||
} else if (!isSubOfSource && !isSubOfTarget) {
|
||||
return;
|
||||
}
|
||||
@@ -1102,6 +1118,10 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
state.entry(stateContext);
|
||||
}
|
||||
|
||||
private static <S, E> boolean isInitial(State<S, E> state) {
|
||||
return state.getPseudoState() != null && state.getPseudoState().getKind() == PseudoStateKind.INITIAL;
|
||||
}
|
||||
|
||||
private static <S, E> boolean isDirectSubstate(State<S, E> left, State<S, E> right) {
|
||||
// Checks if right hand side is a direct substate of a left hand side.
|
||||
if (left != null && left.isSubmachineState()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -19,15 +19,22 @@ import java.util.Collection;
|
||||
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
import org.springframework.statemachine.security.SecurityRule;
|
||||
import org.springframework.statemachine.state.State;
|
||||
import org.springframework.statemachine.trigger.Trigger;
|
||||
|
||||
public class DefaultLocalTransition<S, E> extends AbstractLocalTransition<S, E> {
|
||||
|
||||
public DefaultLocalTransition(State<S,E> source, State<S,E> target, Collection<Action<S, E>> actions, E event, Guard<S, E> guard, Trigger<S, E> trigger) {
|
||||
public DefaultLocalTransition(State<S, E> source, State<S, E> target, Collection<Action<S, E>> actions, E event, Guard<S, E> guard,
|
||||
Trigger<S, E> trigger) {
|
||||
super(source, target, actions, event, guard, trigger);
|
||||
}
|
||||
|
||||
public DefaultLocalTransition(State<S, E> source, State<S, E> target, Collection<Action<S, E>> actions, E event,
|
||||
Guard<S, E> guard, Trigger<S, E> trigger, SecurityRule securityRule, Action<S, E> errorAction) {
|
||||
super(source, target, actions, event, guard, trigger, securityRule, errorAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultLocalTransition [getSource()=" + getSource() + ", getTarget()=" + getTarget() + "]";
|
||||
|
||||
@@ -351,7 +351,7 @@ public class SubStateMachineTests extends AbstractStateMachineTests {
|
||||
|
||||
assertThat(entryActionS111.stateContexts.size(), is(2));
|
||||
assertThat(exitActionS111.stateContexts.size(), is(1));
|
||||
assertThat(entryActionS11.stateContexts.size(), is(2));
|
||||
assertThat(entryActionS11.stateContexts.size(), is(1));
|
||||
assertThat(exitActionS11.stateContexts.size(), is(1));
|
||||
assertThat(entryActionS1.stateContexts.size(), is(1));
|
||||
assertThat(exitActionS1.stateContexts.size(), is(0));
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2016 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.transition;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.statemachine.AbstractStateMachineTests;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineSystemConstants;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import org.springframework.statemachine.state.State;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class LocalTransitionTests extends AbstractStateMachineTests {
|
||||
|
||||
@Test
|
||||
public void testExternalSuperDoesEntryExitToSub() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E20");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.exited.size(), is(2));
|
||||
assertThat(listener.entered.size(), is(2));
|
||||
assertThat(listener.exited, containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S2", "S21"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalSuperDoesNotEntryExitToSub() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E30");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.exited.size(), is(1));
|
||||
assertThat(listener.entered.size(), is(1));
|
||||
assertThat(listener.exited, containsInAnyOrder("S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S21"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExternalToNonInitialSuperDoesEntryExitToSub() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E21");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(2));
|
||||
assertThat(listener.entered.size(), is(2));
|
||||
assertThat(listener.exited, containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S2", "S22"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalToNonInitialSuperDoesNotEntryExitToSub() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E31");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(1));
|
||||
assertThat(listener.entered.size(), is(1));
|
||||
assertThat(listener.exited, containsInAnyOrder("S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S22"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExternalSuperDoesEntryExitToParent() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E22");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.exited.size(), is(2));
|
||||
assertThat(listener.entered.size(), is(2));
|
||||
assertThat(listener.exited, containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S2", "S21"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalSuperDoesNotEntryExitToParent() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E32");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.exited.size(), is(1));
|
||||
assertThat(listener.entered.size(), is(1));
|
||||
assertThat(listener.exited, containsInAnyOrder("S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S21"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExternalToNonInitialSuperDoesEntryExitToParent() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E21");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(2));
|
||||
assertThat(listener.entered.size(), is(2));
|
||||
assertThat(listener.exited, containsInAnyOrder("S2", "S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S2", "S22"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E23");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(2));
|
||||
assertThat(listener.entered.size(), is(2));
|
||||
assertThat(listener.exited, containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S2", "S22"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalToNonInitialSuperDoesNotEntryExitToParent() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
|
||||
StateMachine<String, String> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S21"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E31");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(1));
|
||||
assertThat(listener.entered.size(), is(1));
|
||||
assertThat(listener.exited, containsInAnyOrder("S21"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S22"));
|
||||
|
||||
listener.reset();
|
||||
machine.sendEvent("E33");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
assertThat(listener.exited.size(), is(1));
|
||||
assertThat(listener.entered.size(), is(1));
|
||||
assertThat(listener.exited, containsInAnyOrder("S22"));
|
||||
assertThat(listener.entered, containsInAnyOrder("S22"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class Config1 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1")
|
||||
.state("S2")
|
||||
.and()
|
||||
.withStates()
|
||||
.parent("S2")
|
||||
.initial("S21")
|
||||
.state("S22");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1")
|
||||
.target("S2")
|
||||
.event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2")
|
||||
.target("S21")
|
||||
.event("E20")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2")
|
||||
.target("S22")
|
||||
.event("E21")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S21")
|
||||
.target("S2")
|
||||
.event("E22")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S22")
|
||||
.target("S2")
|
||||
.event("E23")
|
||||
.and()
|
||||
.withLocal()
|
||||
.source("S2")
|
||||
.target("S21")
|
||||
.event("E30")
|
||||
.and()
|
||||
.withLocal()
|
||||
.source("S2")
|
||||
.target("S22")
|
||||
.event("E31")
|
||||
.and()
|
||||
.withLocal()
|
||||
.source("S21")
|
||||
.target("S2")
|
||||
.event("E32")
|
||||
.and()
|
||||
.withLocal()
|
||||
.source("S22")
|
||||
.target("S2")
|
||||
.event("E33");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestListener extends StateMachineListenerAdapter<String, String> {
|
||||
|
||||
final ArrayList<String> entered = new ArrayList<>();
|
||||
final ArrayList<String> exited = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void stateEntered(State<String, String> state) {
|
||||
entered.add(state.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateExited(State<String, String> state) {
|
||||
exited.add(state.getId());
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
entered.clear();
|
||||
exited.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext buildContext() {
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user