List of usage examples for org.springframework.statemachine.transition Transition getSource
State<S, E> getSource();
From source file:gov.grantsolutions.REST.StateMachineController.java
@RequestMapping(value = "/commitment/availableEvents/{currentState}", method = RequestMethod.GET) public @ResponseBody List<String> availableCommitmentEvents(@PathVariable final String currentState) { List<String> list = new ArrayList<String>(); if (!StringUtils.isEmpty(currentState)) { Iterator<Transition<String, String>> transitions = commitmentState.getTransitions().iterator(); while (transitions.hasNext()) { Transition<String, String> transition = transitions.next(); if (currentState.equalsIgnoreCase(transition.getSource().getId())) { list.add(transition.getTrigger().getEvent()); }/* www . jav a 2 s .c o m*/ } } return list; }
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 ww w.j a v a 2s .c om 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
protected synchronized boolean acceptEvent(Message<E> message) { if ((currentState != null && currentState.shouldDefer(message))) { log.info("Current state " + currentState + " deferred event " + message); stateMachineExecutor.queueDeferredEvent(message); return true; }/*from w w w. jav a2s. co m*/ if ((currentState != null && currentState.sendEvent(message))) { return true; } if (log.isDebugEnabled()) { log.debug("Queue event " + message + " " + this); } for (Transition<S, E> transition : transitions) { State<S, E> source = transition.getSource(); Trigger<S, E> trigger = transition.getTrigger(); if (StateMachineUtils.containsAtleastOne(source.getIds(), currentState.getIds())) { if (trigger != null && trigger.evaluate(new DefaultTriggerContext<S, E>(message.getPayload()))) { stateMachineExecutor.queueEvent(message); return true; } } } // if we're about to not accept event, check defer again in case // state was changed between original check and now if ((currentState != null && currentState.shouldDefer(message))) { log.info("Current state " + currentState + " deferred event " + message); stateMachineExecutor.queueDeferredEvent(message); return true; } return false; }
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 www . ja v a 2s . 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(); }//from w w w .j a va2s. 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;//from w ww . j a va 2s . c om } 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 a2 s. c om } 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; }/* www. 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; }
From source file:org.springframework.statemachine.support.DefaultStateMachineExecutor.java
private boolean processEventQueue() { if (log.isDebugEnabled()) { log.debug("Process event queue, size=" + eventQueue.size()); }// w w w . j a v a2 s . c om Message<E> queuedEvent = eventQueue.poll(); State<S, E> currentState = stateMachine.getState(); if (queuedEvent != null) { if ((currentState != null && currentState.shouldDefer(queuedEvent))) { log.info("Current state " + currentState + " deferred event " + queuedEvent); queueDeferredEvent(queuedEvent); return true; } for (Transition<S, E> transition : transitions) { State<S, E> source = transition.getSource(); Trigger<S, E> trigger = transition.getTrigger(); if (StateMachineUtils.containsAtleastOne(source.getIds(), currentState.getIds())) { if (trigger != null && trigger.evaluate(new DefaultTriggerContext<S, E>(queuedEvent.getPayload()))) { queueTrigger(trigger, queuedEvent); return true; } } } } return false; }
From source file:org.springframework.statemachine.support.DefaultStateMachineExecutor.java
private void processTriggerQueue() { if (!isRunning()) { return;//from ww w . j ava2 s. com } if (!initialHandled.getAndSet(true)) { ArrayList<Transition<S, E>> trans = new ArrayList<Transition<S, E>>(); trans.add(initialTransition); // TODO: should we merge if initial event is actually used? if (initialEvent != null) { handleInitialTrans(initialTransition, initialEvent); } else { handleInitialTrans(initialTransition, forwardedInitialEvent); } return; } if (log.isDebugEnabled()) { log.debug("Process trigger queue, size=" + triggerQueue.size() + " " + this); } TriggerQueueItem queueItem = triggerQueue.poll(); // keep message here so that we can // pass it to triggerless transitions State<S, E> currentState = stateMachine.getState(); if (queueItem != null && currentState != null) { if (log.isDebugEnabled()) { log.debug("Process trigger item " + queueItem + " " + this); } // queued message is kept on a class level order to let // triggerless transition to receive this message if it doesn't // kick in in this poll loop. queuedMessage = queueItem.message; E event = queuedMessage != null ? queuedMessage.getPayload() : null; // need all transitions trigger could match, event trigger may match // multiple // need to go up from substates and ask if trigger transit, if not // check super ArrayList<Transition<S, E>> trans = new ArrayList<Transition<S, E>>(); if (event != null) { ArrayList<S> ids = new ArrayList<S>(currentState.getIds()); Collections.reverse(ids); for (S id : ids) { for (Entry<Trigger<S, E>, Transition<S, E>> e : triggerToTransitionMap.entrySet()) { Trigger<S, E> tri = e.getKey(); E ee = tri.getEvent(); Transition<S, E> tra = e.getValue(); if (event.equals(ee)) { if (tra.getSource().getId().equals(id) && !trans.contains(tra)) { trans.add(tra); continue; } } } } } // most likely timer if (trans.isEmpty()) { trans.add(triggerToTransitionMap.get(queueItem.trigger)); } // go through candidates and transit max one handleTriggerTrans(trans, queuedMessage); } if (stateMachine.getState() != null) { // loop triggerless transitions here so that // all "chained" transitions will get queue message boolean transit = false; do { transit = handleTriggerTrans(triggerlessTransitions, queuedMessage); } while (transit); } }