Fix state exit

- Fix case where linked pseudostates may cause
  substate not exited properly.
- Tests coming in other commit.
- Fixes #208
This commit is contained in:
Janne Valkealahti
2016-04-24 17:38:20 +01:00
parent debc50cb56
commit 347e1d7095
2 changed files with 36 additions and 0 deletions

View File

@@ -754,10 +754,18 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
} else if (kind == PseudoStateKind.ENTRY) {
StateContext<S, E> stateContext = buildStateContext(Stage.STATE_CHANGED, message, transition, stateMachine);
State<S, E> toState = state.getPseudoState().entry(stateContext);
while (toState != null && toState.getPseudoState() != null
&& toState.getPseudoState().getKind() != PseudoStateKind.INITIAL) {
toState = toState.getPseudoState().entry(stateContext);
}
setCurrentState(toState, message, transition, true, stateMachine);
} else if (kind == PseudoStateKind.EXIT) {
StateContext<S, E> stateContext = buildStateContext(Stage.STATE_CHANGED, message, transition, stateMachine);
State<S, E> toState = state.getPseudoState().entry(stateContext);
while (toState != null && toState.getPseudoState() != null
&& toState.getPseudoState().getKind() != PseudoStateKind.INITIAL) {
toState = toState.getPseudoState().entry(stateContext);
}
setCurrentState(toState, message, transition, true, stateMachine);
} else if (kind == PseudoStateKind.FORK) {
ForkPseudoState<S, E> fps = (ForkPseudoState<S, E>) state.getPseudoState();
@@ -982,6 +990,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
} else if (isTargetSubOfOtherState) {
} else if (!isSubOfSource && !isSubOfTarget && findDeep == null) {
} else if (!isSubOfSource && !isSubOfTarget && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) {
} else if (StateMachineUtils.isNormalPseudoState(transition.getTarget())) {
} else if (!isSubOfSource && !isSubOfTarget) {
return;
}

View File

@@ -18,6 +18,8 @@ package org.springframework.statemachine.support;
import java.util.ArrayList;
import java.util.Collection;
import org.springframework.statemachine.state.PseudoState;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.statemachine.state.State;
import org.springframework.util.ObjectUtils;
@@ -68,6 +70,31 @@ public abstract class StateMachineUtils {
return false;
}
/**
* Checks if state is a normal pseudo state, meaning it is a pseudostate
* and its kind is not initial or end.
*
* @param <S> the type of state
* @param <E> the type of event
* @param state the state
* @return true, if is normal pseudo state
*/
public static <S, E> boolean isNormalPseudoState(State<S, E> state) {
if (state == null) {
return false;
}
PseudoState<S, E> pseudoState = state.getPseudoState();
if (pseudoState == null) {
return false;
}
PseudoStateKind kind = pseudoState.getKind();
if (kind == PseudoStateKind.INITIAL || kind == PseudoStateKind.END) {
return false;
} else {
return true;
}
}
public static <S> Collection<String> toStringCollection(Collection<S> collection) {
Collection<String> c = new ArrayList<String>();
for (S item : collection) {