Example usage for org.springframework.statemachine.transition Transition getSource

List of usage examples for org.springframework.statemachine.transition Transition getSource

Introduction

In this page you can find the example usage for org.springframework.statemachine.transition Transition getSource.

Prototype

State<S, E> getSource();

Source Link

Document

Gets the source state of this transition.

Usage

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);
    }
}