diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java index 93d75e80..b31fd89d 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java @@ -345,9 +345,7 @@ public abstract class AbstractStateMachine extends LifecycleObjectSupport return null; } - void setCurrentState(State statex, Message event, Transition transition, boolean exit) { - - State state = statex; + void setCurrentState(State state, Message event, Transition transition, boolean exit) { State findDeep = findDeepParent(state); boolean isTargetSubOf = false; if (transition != null) { @@ -418,11 +416,15 @@ public abstract class AbstractStateMachine extends LifecycleObjectSupport new HashMap()); StateContext stateContext = new DefaultStateContext(messageHeaders, extendedState, transition, this); + State findDeep = findDeepParent(transition.getTarget()); + boolean isTargetSubOfOtherState = findDeep != null && findDeep != currentState; + boolean isSubOfSource = isSubstate(transition.getSource(), currentState); boolean isSubOfTarget = isSubstate(transition.getTarget(), currentState); if (currentState == transition.getSource() && currentState == transition.getTarget()) { } else if (!isSubOfSource && !isSubOfTarget && currentState == transition.getSource()) { } else if (!isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) { + } else if (isTargetSubOfOtherState) { } else if (!isSubOfSource && !isSubOfTarget) { return; } @@ -445,10 +447,15 @@ public abstract class AbstractStateMachine extends LifecycleObjectSupport StateContext stateContext = new DefaultStateContext(messageHeaders, extendedState, transition, this); if (transition != null) { + State findDeep1 = findDeepParent(transition.getTarget()); + State findDeep2 = findDeepParent(transition.getSource()); + boolean isComingFromOtherSubmachine = findDeep1 != null && findDeep2 != null && findDeep2 != currentState; + boolean isSubOfSource = isSubstate(transition.getSource(), currentState); boolean isSubOfTarget = isSubstate(transition.getTarget(), currentState); if (currentState == transition.getSource() && currentState == transition.getTarget()) { } else if (!isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) { + } else if (isComingFromOtherSubmachine) { } else if (isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) { return; } else if (!isSubOfSource && !isSubOfTarget) { diff --git a/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java b/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java index 7a3a3caf..a6dd0941 100644 --- a/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java +++ b/spring-statemachine-samples/showcase/src/test/java/demo/showcase/ShowcaseTests.java @@ -177,6 +177,26 @@ public class ShowcaseTests { assertThat(listener.statesEntered.size(), is(3)); } + @Test + public void testF() throws Exception { + listener.reset(1, 4, 2, 0); + machine.sendEvent(Events.F); + listener.stateChangedLatch.await(1, TimeUnit.SECONDS); + assertThat(machine.getState().getIds(), contains(States.S0, States.S2, States.S21, States.S211)); + assertThat(listener.statesExited.size(), is(2)); + assertThat(listener.statesEntered.size(), is(4)); + } + + @Test + public void testG() throws Exception { + listener.reset(1, 4, 2, 0); + machine.sendEvent(Events.G); + listener.stateChangedLatch.await(1, TimeUnit.SECONDS); + assertThat(machine.getState().getIds(), contains(States.S0, States.S2, States.S21, States.S211)); + assertThat(listener.statesExited.size(), is(2)); + assertThat(listener.statesEntered.size(), is(4)); + } + static class Config { @Autowired