Fix state entry called too many times

- Fix double entry in a case that target is initial state
  and source is target's direct parent.
- Fixes #191
This commit is contained in:
Janne Valkealahti
2016-03-27 16:54:57 +01:00
parent c61507cae6
commit 89d183f91c
2 changed files with 15 additions and 0 deletions

View File

@@ -988,6 +988,9 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
} else if (isComingFromOtherSubmachine) {
} else if (!isSubOfSource && !isSubOfTarget && findDeep2 == null) {
} else if (isSubOfSource && !isSubOfTarget && currentState == transition.getTarget()) {
if (isDirectSubstate(transition.getSource(), transition.getTarget())) {
return;
}
} else if (!isSubOfSource && !isSubOfTarget && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) {
} else if (!isSubOfSource && !isSubOfTarget) {
return;
@@ -999,4 +1002,14 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
state.entry(stateContext);
}
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()) {
StateMachine<S, E> submachine = ((AbstractState<S, E>)left).getSubmachine();
return submachine.getStates().contains(right);
} else {
return false;
}
}
}

View File

@@ -82,6 +82,8 @@ public class ShowcaseTests {
assertThat(listener.stateChangedLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(listener.stateEnteredLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(listener.stateExitedLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(listener.statesExited.size(), is(2));
assertThat(listener.statesEntered.size(), is(2));
assertThat(machine.getState().getIds(), contains(States.S0, States.S1, States.S11));
}