List of usage examples for org.springframework.statemachine.transition Transition getTarget
State<S, E> getTarget();
From source file:org.springframework.statemachine.support.AbstractStateMachine.java
@Override protected void onInit() throws Exception { super.onInit(); Assert.notNull(initialState, "Initial state must be set"); Assert.state(/* w w w . j a v a2 s.co m*/ initialState.getPseudoState() != null && initialState.getPseudoState().getKind() == PseudoStateKind.INITIAL, "Initial state's pseudostate kind must be INITIAL"); lastState = null; extendedState.setExtendedStateChangeListener(new ExtendedStateChangeListener() { @Override public void changed(Object key, Object value) { notifyExtendedStateChanged(key, value, buildStateContext(Stage.EXTENDED_STATE_CHANGED, null, null, getRelayStateMachine())); } }); // process given transitions for (Transition<S, E> transition : transitions) { Trigger<S, E> trigger = transition.getTrigger(); if (trigger != null) { // we have same triggers with different transitions triggerToTransitionMap.put(trigger, transition); } else { triggerlessTransitions.add(transition); } } for (State<S, E> state : states) { if (state.isSubmachineState()) { StateMachine<S, E> submachine = ((AbstractState<S, E>) state).getSubmachine(); submachine.addStateListener(new StateMachineListenerRelay()); } else if (state.isOrthogonal()) { Collection<Region<S, E>> regions = ((AbstractState<S, E>) state).getRegions(); for (Region<S, E> region : regions) { region.addStateListener(new StateMachineListenerRelay()); } } if (state.getPseudoState() != null && (state.getPseudoState().getKind() == PseudoStateKind.HISTORY_DEEP || state.getPseudoState().getKind() == PseudoStateKind.HISTORY_DEEP)) { history = state.getPseudoState(); } } DefaultStateMachineExecutor<S, E> executor = new DefaultStateMachineExecutor<S, E>(this, getRelayStateMachine(), transitions, triggerToTransitionMap, triggerlessTransitions, initialTransition, initialEvent); if (getBeanFactory() != null) { executor.setBeanFactory(getBeanFactory()); } if (getTaskExecutor() != null) { executor.setTaskExecutor(getTaskExecutor()); } executor.afterPropertiesSet(); executor.setStateMachineExecutorTransit(new StateMachineExecutorTransit<S, E>() { @Override public void transit(Transition<S, E> t, StateContext<S, E> ctx, Message<E> message) { long now = System.currentTimeMillis(); // TODO: fix above stateContext as it's not used notifyTransitionStart( buildStateContext(Stage.TRANSITION_START, message, t, getRelayStateMachine())); notifyTransition(buildStateContext(Stage.TRANSITION, message, t, getRelayStateMachine())); if (t.getTarget().getPseudoState() != null && t.getTarget().getPseudoState().getKind() == PseudoStateKind.JOIN) { exitFromState(t.getSource(), message, t, getRelayStateMachine()); } else { if (t.getKind() == TransitionKind.INITIAL) { switchToState(t.getTarget(), message, t, getRelayStateMachine()); notifyStateMachineStarted( buildStateContext(Stage.STATEMACHINE_START, message, t, getRelayStateMachine())); } else if (t.getKind() != TransitionKind.INTERNAL) { switchToState(t.getTarget(), message, t, getRelayStateMachine()); } } // TODO: looks like events should be called here and anno processing earlier notifyTransitionEnd(buildStateContext(Stage.TRANSITION_END, message, t, getRelayStateMachine())); notifyTransitionMonitor(getRelayStateMachine(), t, System.currentTimeMillis() - now); } }); stateMachineExecutor = executor; for (Transition<S, E> t : getTransitions()) { t.addActionListener(new ActionListener<S, E>() { @Override public void onExecute(StateMachine<S, E> stateMachine, Action<S, E> action, long duration) { notifyActionMonitor(stateMachine, action, duration); } }); } for (State<S, E> s : getStates()) { s.addActionListener(new ActionListener<S, E>() { @Override public void onExecute(StateMachine<S, E> stateMachine, Action<S, E> action, long duration) { notifyActionMonitor(stateMachine, action, duration); } }); } }
From source file:org.springframework.statemachine.support.AbstractStateMachine.java
private Transition<S, E> findTransition(State<S, E> from, State<S, E> to) { for (Transition<S, E> transition : transitions) { if (transition.getSource() == from && transition.getTarget() == to) { return transition; }/*from w w w .ja v a2 s.c o m*/ } return null; }
From source file:org.springframework.statemachine.support.AbstractStateMachine.java
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) { isTargetSubOf = StateMachineUtils.isSubstate(state, transition.getSource()); if (isTargetSubOf && currentState == transition.getTarget()) { state = transition.getSource(); }//w ww.j ava 2 s .c om } boolean nonDeepStatePresent = false; if (states.contains(state)) { if (exit) { exitCurrentState(state, message, transition, stateMachine, sources, targets); } State<S, E> notifyFrom = currentState; currentState = state; if (!isRunning()) { start(); } entryToState(state, message, transition, stateMachine); notifyStateChanged(buildStateContext(Stage.STATE_CHANGED, message, null, getRelayStateMachine(), notifyFrom, state)); nonDeepStatePresent = true; } else if (currentState == null && StateMachineUtils.isSubstate(findDeep, state)) { if (exit) { exitCurrentState(findDeep, message, transition, stateMachine, sources, targets); } State<S, E> notifyFrom = currentState; currentState = findDeep; if (!isRunning()) { start(); } entryToState(findDeep, message, transition, stateMachine); notifyStateChanged(buildStateContext(Stage.STATE_CHANGED, message, null, getRelayStateMachine(), notifyFrom, findDeep)); } if (currentState != null && !nonDeepStatePresent) { if (findDeep != null) { if (exit) { exitCurrentState(state, message, transition, stateMachine, sources, targets); } if (currentState == findDeep) { if (currentState.isSubmachineState()) { StateMachine<S, E> submachine = ((AbstractState<S, E>) currentState).getSubmachine(); // need to check complete as submachine may now return non null if (!submachine.isComplete() && submachine.getState() == state) { if (currentState == findDeep) { if (isTargetSubOf) { entryToState(currentState, message, transition, stateMachine); } currentState = findDeep; ((AbstractStateMachine<S, E>) submachine).setCurrentState(state, message, transition, false, stateMachine); return; } } } else if (currentState.isOrthogonal()) { Collection<Region<S, E>> regions = ((AbstractState<S, E>) currentState).getRegions(); for (Region<S, E> region : regions) { if (region.getState() == state) { if (currentState == findDeep) { if (isTargetSubOf) { entryToState(currentState, message, transition, stateMachine); } currentState = findDeep; ((AbstractStateMachine<S, E>) region).setCurrentState(state, message, transition, false, stateMachine); return; } } } } } boolean shouldTryEntry = findDeep != currentState; if (!shouldTryEntry && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) { shouldTryEntry = true; } currentState = findDeep; if (shouldTryEntry) { entryToState(currentState, message, transition, stateMachine, sources, targets); } if (currentState.isSubmachineState()) { StateMachine<S, E> submachine = ((AbstractState<S, E>) currentState).getSubmachine(); ((AbstractStateMachine<S, E>) submachine).setCurrentState(state, message, transition, false, stateMachine); } else if (currentState.isOrthogonal()) { Collection<Region<S, E>> regions = ((AbstractState<S, E>) currentState).getRegions(); for (Region<S, E> region : regions) { ((AbstractStateMachine<S, E>) region).setCurrentState(state, message, transition, false, stateMachine); } } } } if (history != null && transition.getKind() != TransitionKind.INITIAL) { // do not set history if this is initial transition as // it would break history state set via reset as // we get here i.e. when machine is started in reset. // and it really doesn't make sense to set initial state for history // if we get here via initial transition if (history.getKind() == PseudoStateKind.HISTORY_SHALLOW) { ((HistoryPseudoState<S, E>) history).setState(findDeep); } else if (history.getKind() == PseudoStateKind.HISTORY_DEEP) { ((HistoryPseudoState<S, E>) history).setState(state); } } // if state was set from parent and we're now complete // also initiate stop if (stateMachine != this && isComplete()) { stop(); } }
From source file:org.springframework.statemachine.support.AbstractStateMachine.java
private void exitFromState(State<S, E> state, Message<E> message, Transition<S, E> transition, StateMachine<S, E> stateMachine, Collection<State<S, E>> sources, Collection<State<S, E>> targets) { if (state == null) { return;/*from w ww . ja v a2 s.c o m*/ } log.trace("Trying Exit state=[" + state + "]"); StateContext<S, E> stateContext = buildStateContext(Stage.STATE_EXIT, message, transition, stateMachine); if (transition != null) { State<S, E> findDeep = findDeepParent(transition.getTarget()); boolean isTargetSubOfOtherState = findDeep != null && findDeep != currentState; 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. 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 && findDeep == null) { } else if (!isSubOfSource && !isSubOfTarget && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) { } else if (StateMachineUtils.isNormalPseudoState(transition.getTarget())) { if (isPseudoStateSubstate(findDeep, targets)) { return; } } else if (findDeep != null && findDeep != state && findDeep.getStates().contains(state)) { } else if (!isSubOfSource && !isSubOfTarget) { return; } } log.debug("Exit state=[" + state + "]"); state.exit(stateContext); notifyStateExited(buildStateContext(Stage.STATE_EXIT, message, null, getRelayStateMachine(), state, null)); }
From source file:org.springframework.statemachine.support.AbstractStateMachine.java
private void entryToState(State<S, E> state, Message<E> message, Transition<S, E> transition, StateMachine<S, E> stateMachine, Collection<State<S, E>> sources, Collection<State<S, E>> targets) { if (state == null) { return;//w ww.j a v a2s . co m } log.trace("Trying Enter state=[" + state + "]"); StateContext<S, E> stateContext = buildStateContext(Stage.STATE_ENTRY, message, transition, stateMachine, sources, targets); if (transition != null) { State<S, E> findDeep1 = findDeepParent(transition.getTarget()); State<S, E> findDeep2 = findDeepParent(transition.getSource()); boolean isComingFromOtherSubmachine = findDeep1 != null && findDeep2 != null && findDeep2 != currentState; 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()) && transition.getKind() != TransitionKind.LOCAL && isInitial(transition.getTarget())) { return; } } else if (!isSubOfSource && !isSubOfTarget && (transition.getSource() == currentState && StateMachineUtils.isSubstate(currentState, transition.getTarget()))) { } else if (!isSubOfSource && !isSubOfTarget) { if (!StateMachineUtils.isTransientPseudoState(transition.getTarget())) { return; } } } // with linked joins, we need to enter state but should not notify. // state entries are needed to track join logic. if (!StateMachineUtils.isPseudoState(state, PseudoStateKind.JOIN)) { notifyStateEntered( buildStateContext(Stage.STATE_ENTRY, message, transition, getRelayStateMachine(), null, state)); } log.debug("Enter state=[" + state + "]"); state.entry(stateContext); }
From source file:org.springframework.statemachine.support.DefaultStateMachineExecutor.java
private boolean handleTriggerTrans(List<Transition<S, E>> trans, Message<E> queuedMessage) { boolean transit = false; for (Transition<S, E> t : trans) { if (t == null) { continue; }/*from ww w.j a va 2 s . co m*/ State<S, E> source = t.getSource(); if (source == null) { continue; } State<S, E> currentState = stateMachine.getState(); if (currentState == null) { continue; } if (!StateMachineUtils.containsAtleastOne(source.getIds(), currentState.getIds())) { continue; } // special handling of join if (StateMachineUtils.isPseudoState(t.getTarget(), PseudoStateKind.JOIN)) { if (joinSyncStates.isEmpty()) { List<State<S, E>> joins = ((JoinPseudoState<S, E>) t.getTarget().getPseudoState()).getJoins(); joinSyncStates.addAll(joins); } joinSyncTransitions.add(t); boolean removed = joinSyncStates.remove(t.getSource()); boolean joincomplete = removed & joinSyncStates.isEmpty(); if (joincomplete) { for (Transition<S, E> tt : joinSyncTransitions) { StateContext<S, E> stateContext = buildStateContext(queuedMessage, tt, relayStateMachine); tt.transit(stateContext); stateMachineExecutorTransit.transit(tt, stateContext, queuedMessage); } joinSyncTransitions.clear(); break; } else { continue; } } StateContext<S, E> stateContext = buildStateContext(queuedMessage, t, relayStateMachine); try { stateContext = interceptors.preTransition(stateContext); } catch (Exception e) { // currently expect that if exception is // thrown, this transition will not match. // i.e. security may throw AccessDeniedException log.info("Interceptors threw exception", e); stateContext = null; } if (stateContext == null) { break; } try { transit = t.transit(stateContext); } catch (Exception e) { log.warn("Transition " + t + " caused error " + e); } if (transit) { stateMachineExecutorTransit.transit(t, stateContext, queuedMessage); interceptors.postTransition(stateContext); break; } } return transit; }