List of usage examples for org.springframework.statemachine.transition Transition getKind
TransitionKind getKind();
From source file:demo.web.StateMachineController.java
@PostConstruct public void setup() { stateMachine.addStateListener(new StateMachineListenerAdapter<States, Events>() { @Override// w w w. j av a2 s . c o m public void stateEntered(State<States, Events> state) { StateMachineMessage message = new StateMachineMessage(); message.setMessage("Enter state " + state.getId().toString()); simpMessagingTemplate.convertAndSend("/topic/sm.message", message); } @Override public void stateExited(State<States, Events> state) { StateMachineMessage message = new StateMachineMessage(); message.setMessage("Exit state " + state.getId().toString()); simpMessagingTemplate.convertAndSend("/topic/sm.message", message); } @Override public void stateChanged(State<States, Events> from, State<States, Events> to) { Map<Object, Object> variables = stateMachine.getExtendedState().getVariables(); ArrayList<StateMachineEvent> list = new ArrayList<StateMachineEvent>(); for (States state : stateMachine.getState().getIds()) { list.add(new StateMachineEvent(state.toString())); } simpMessagingTemplate.convertAndSend("/topic/sm.states", list); simpMessagingTemplate.convertAndSend("/topic/sm.variables", variables); } @Override public void transitionEnded(Transition<States, Events> transition) { if (transition != null && transition.getKind() == TransitionKind.INTERNAL) { Map<Object, Object> variables = stateMachine.getExtendedState().getVariables(); simpMessagingTemplate.convertAndSend("/topic/sm.variables", variables); } } @Override public void stateMachineError(StateMachine<States, Events> stateMachine, Exception exception) { handleStateMachineError(new StateMachineException("Received error from machine", exception)); } }); stateMachineEnsemble.addEnsembleListener(new EnsembleListenerAdapter<States, Events>() { @Override public void ensembleLeaderGranted(StateMachine<States, Events> stateMachine) { StateMachineMessage message = new StateMachineMessage(); message.setMessage("Leader granted " + stateMachine.getUuid().toString()); simpMessagingTemplate.convertAndSend("/topic/sm.message", message); } @Override public void ensembleLeaderRevoked(StateMachine<States, Events> stateMachine) { StateMachineMessage message = new StateMachineMessage(); message.setMessage("Leader revoked " + stateMachine.getUuid().toString()); simpMessagingTemplate.convertAndSend("/topic/sm.message", message); } }); }
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(//from w ww .j a v a 2 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 boolean isInitialTransition(Transition<S, E> transition) { return transition != null && transition.getKind() == TransitionKind.INITIAL; }
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. ja v a2s . c o m*/ } 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;//w w w .j ava 2s .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;//from w w w . j a v a 2 s. c o 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); }