Example usage for org.springframework.statemachine.state PseudoStateKind HISTORY_DEEP

List of usage examples for org.springframework.statemachine.state PseudoStateKind HISTORY_DEEP

Introduction

In this page you can find the example usage for org.springframework.statemachine.state PseudoStateKind HISTORY_DEEP.

Prototype

PseudoStateKind HISTORY_DEEP

To view the source code for org.springframework.statemachine.state PseudoStateKind HISTORY_DEEP.

Click Source Link

Document

History deep kind

Usage

From source file:org.springframework.statemachine.config.AbstractStateMachineFactory.java

@SuppressWarnings("unchecked")
private StateMachine<S, E> buildMachine(Map<Object, StateMachine<S, E>> machineMap,
        Map<S, State<S, E>> stateMap, Map<S, StateHolder<S, E>> holderMap,
        Collection<StateData<S, E>> stateDatas, Collection<TransitionData<S, E>> transitionsData,
        BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState,
        TransitionsData<S, E> stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler,
        String machineId, UUID uuid, StateMachineModel<S, E> stateMachineModel) {
    State<S, E> state = null;
    State<S, E> initialState = null;
    PseudoState<S, E> historyState = null;
    Action<S, E> initialAction = null;
    Collection<State<S, E>> states = new ArrayList<State<S, E>>();

    // for now loop twice and build states for
    // non initial/end pseudostates last

    for (StateData<S, E> stateData : stateDatas) {
        StateMachine<S, E> stateMachine = machineMap.get(stateData.getState());
        if (stateMachine == null) {
            // get a submachine from state data if we didn't have
            // it already. stays null if we don't have one.
            stateMachine = stateData.getSubmachine();
            if (stateMachine == null && stateData.getSubmachineFactory() != null) {
                stateMachine = stateData.getSubmachineFactory().getStateMachine(machineId);
            }/* w  w w .  ja v  a 2 s  .co  m*/
        }
        state = stateMap.get(stateData.getState());
        if (state != null) {
            states.add(state);
            if (stateData.isInitial()) {
                initialState = state;
            }
            continue;
        }
        if (stateMachine != null) {
            PseudoState<S, E> pseudoState = null;
            if (stateData.isInitial()) {
                pseudoState = new DefaultPseudoState<S, E>(PseudoStateKind.INITIAL);
            }
            state = new StateMachineState<S, E>(stateData.getState(), stateMachine, stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), pseudoState);
            // TODO: below if/else doesn't feel right
            if (stateDatas.size() > 1 && stateData.isInitial()) {
                initialState = state;
                initialAction = stateData.getInitialAction();
            } else if (stateDatas.size() == 1) {
                initialState = state;
                initialAction = stateData.getInitialAction();
            }
            states.add(state);
        } else {
            PseudoState<S, E> pseudoState = null;
            if (stateData.isInitial()) {
                pseudoState = new DefaultPseudoState<S, E>(PseudoStateKind.INITIAL);
            } else if (stateData.isEnd()) {
                pseudoState = new DefaultPseudoState<S, E>(PseudoStateKind.END);
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_SHALLOW) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_DEEP) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.JOIN) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.FORK) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.CHOICE) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.JUNCTION) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.ENTRY) {
                continue;
            } else if (stateData.getPseudoStateKind() == PseudoStateKind.EXIT) {
                continue;
            }
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            if (stateData.isInitial()) {
                initialState = state;
                initialAction = stateData.getInitialAction();
            }
            states.add(state);

        }
        stateMap.put(stateData.getState(), state);
    }

    for (StateData<S, E> stateData : stateDatas) {
        if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_SHALLOW) {
            State<S, E> defaultState = null;
            S s = stateData.getState();
            Collection<HistoryData<S, E>> historys = stateMachineTransitions.getHistorys();
            for (HistoryData<S, E> history : historys) {
                if (history.getSource().equals(s)) {
                    defaultState = stateMap.get(history.getTarget());
                }
            }
            StateHolder<S, E> defaultStateHolder = new StateHolder<S, E>(defaultState);
            StateHolder<S, E> containingStateHolder = new StateHolder<S, E>(
                    stateMap.get(stateData.getParent()));
            if (containingStateHolder.getState() == null) {
                holderMap.put((S) stateData.getParent(), containingStateHolder);
            }
            PseudoState<S, E> pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_SHALLOW,
                    defaultStateHolder, containingStateHolder);
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
            historyState = pseudoState;
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_DEEP) {
            State<S, E> defaultState = null;
            S s = stateData.getState();
            Collection<HistoryData<S, E>> historys = stateMachineTransitions.getHistorys();
            for (HistoryData<S, E> history : historys) {
                if (history.getSource().equals(s)) {
                    defaultState = stateMap.get(history.getTarget());
                }
            }
            StateHolder<S, E> defaultStateHolder = new StateHolder<S, E>(defaultState);
            StateHolder<S, E> containingStateHolder = new StateHolder<S, E>(
                    stateMap.get(stateData.getParent()));
            if (containingStateHolder.getState() == null) {
                holderMap.put((S) stateData.getParent(), containingStateHolder);
            }
            PseudoState<S, E> pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_DEEP,
                    defaultStateHolder, containingStateHolder);
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
            historyState = pseudoState;
        }

        if (stateData.getPseudoStateKind() == PseudoStateKind.CHOICE) {
            S s = stateData.getState();
            List<ChoiceData<S, E>> list = stateMachineTransitions.getChoices().get(s);
            List<ChoiceStateData<S, E>> choices = new ArrayList<ChoiceStateData<S, E>>();
            for (ChoiceData<S, E> c : list) {
                StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(c.getTarget()));
                if (holder.getState() == null) {
                    holderMap.put(c.getTarget(), holder);
                }
                choices.add(new ChoiceStateData<S, E>(holder, c.getGuard()));
            }
            PseudoState<S, E> pseudoState = new ChoicePseudoState<S, E>(choices);
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.JUNCTION) {
            S s = stateData.getState();
            List<JunctionData<S, E>> list = stateMachineTransitions.getJunctions().get(s);
            List<JunctionStateData<S, E>> junctions = new ArrayList<JunctionStateData<S, E>>();
            for (JunctionData<S, E> c : list) {
                StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(c.getTarget()));
                if (holder.getState() == null) {
                    holderMap.put(c.getTarget(), holder);
                }
                junctions.add(new JunctionStateData<S, E>(holder, c.getGuard()));
            }
            PseudoState<S, E> pseudoState = new JunctionPseudoState<S, E>(junctions);
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.ENTRY) {
            S s = stateData.getState();
            Collection<EntryData<S, E>> entrys = stateMachineTransitions.getEntrys();
            for (EntryData<S, E> entry : entrys) {
                if (s.equals(entry.getSource())) {
                    PseudoState<S, E> pseudoState = new EntryPseudoState<S, E>(stateMap.get(entry.getTarget()));
                    state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                            stateData.getEntryActions(), stateData.getExitActions(),
                            stateData.getStateActions(), pseudoState, stateMachineModel);
                    states.add(state);
                    stateMap.put(stateData.getState(), state);
                    break;
                }
            }
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.EXIT) {
            S s = stateData.getState();
            Collection<ExitData<S, E>> exits = stateMachineTransitions.getExits();
            for (ExitData<S, E> entry : exits) {
                if (s.equals(entry.getSource())) {
                    StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(entry.getTarget()));
                    if (holder.getState() == null) {
                        holderMap.put(entry.getTarget(), holder);
                    }
                    PseudoState<S, E> pseudoState = new ExitPseudoState<S, E>(holder);
                    state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                            stateData.getEntryActions(), stateData.getExitActions(),
                            stateData.getStateActions(), pseudoState, stateMachineModel);
                    states.add(state);
                    stateMap.put(stateData.getState(), state);
                    break;
                }
            }
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.FORK) {
            S s = stateData.getState();
            List<S> list = stateMachineTransitions.getForks().get(s);
            List<State<S, E>> forks = new ArrayList<State<S, E>>();
            for (S fs : list) {
                forks.add(stateMap.get(fs));
            }
            PseudoState<S, E> pseudoState = new ForkPseudoState<S, E>(forks);
            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
        } else if (stateData.getPseudoStateKind() == PseudoStateKind.JOIN) {
            S s = stateData.getState();
            List<S> list = stateMachineTransitions.getJoins().get(s);
            List<State<S, E>> joins = new ArrayList<State<S, E>>();

            // if join source is a regionstate, get
            // it's end states from regions
            if (list.size() == 1) {
                State<S, E> ss1 = stateMap.get(list.get(0));
                if (ss1 instanceof RegionState) {
                    Collection<Region<S, E>> regions = ((RegionState<S, E>) ss1).getRegions();
                    for (Region<S, E> r : regions) {
                        Collection<State<S, E>> ss2 = r.getStates();
                        for (State<S, E> ss3 : ss2) {
                            if (ss3.getPseudoState() != null
                                    && ss3.getPseudoState().getKind() == PseudoStateKind.END) {
                                joins.add(ss3);
                                continue;
                            }
                        }
                    }
                }
            } else {
                for (S fs : list) {
                    joins.add(stateMap.get(fs));
                }
            }

            List<JoinStateData<S, E>> joinTargets = new ArrayList<JoinStateData<S, E>>();
            Collection<TransitionData<S, E>> transitions = stateMachineTransitions.getTransitions();
            for (TransitionData<S, E> tt : transitions) {
                if (tt.getSource() == s) {
                    StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(tt.getTarget()));
                    if (holder.getState() == null) {
                        holderMap.put(tt.getTarget(), holder);
                    }
                    joinTargets.add(new JoinStateData<S, E>(holder, tt.getGuard()));
                }
            }
            JoinPseudoState<S, E> pseudoState = new JoinPseudoState<S, E>(joins, joinTargets);

            state = buildStateInternal(stateData.getState(), stateData.getDeferred(),
                    stateData.getEntryActions(), stateData.getExitActions(), stateData.getStateActions(),
                    pseudoState, stateMachineModel);
            states.add(state);
            stateMap.put(stateData.getState(), state);
        }
    }

    Collection<Transition<S, E>> transitions = new ArrayList<Transition<S, E>>();
    for (TransitionData<S, E> transitionData : transitionsData) {
        S source = transitionData.getSource();
        S target = transitionData.getTarget();
        E event = transitionData.getEvent();
        Long period = transitionData.getPeriod();
        Integer count = transitionData.getCount();

        Trigger<S, E> trigger = null;
        if (event != null) {
            trigger = new EventTrigger<S, E>(event);
        } else if (period != null) {
            TimerTrigger<S, E> t = new TimerTrigger<S, E>(period, count != null ? count : 0);
            if (beanFactory != null) {
                t.setBeanFactory(beanFactory);
            }
            if (taskExecutor != null) {
                t.setTaskExecutor(taskExecutor);
            }
            if (taskScheduler != null) {
                t.setTaskScheduler(taskScheduler);
            }
            trigger = t;
            ((AbstractState<S, E>) stateMap.get(source)).getTriggers().add(trigger);
        }

        if (transitionData.getKind() == TransitionKind.EXTERNAL) {
            // TODO can we do this?
            if (stateMap.get(source) == null || stateMap.get(target) == null) {
                continue;
            }
            DefaultExternalTransition<S, E> transition = new DefaultExternalTransition<S, E>(
                    stateMap.get(source), stateMap.get(target), transitionData.getActions(), event,
                    transitionData.getGuard(), trigger, transitionData.getSecurityRule());
            transitions.add(transition);

        } else if (transitionData.getKind() == TransitionKind.LOCAL) {
            // TODO can we do this?
            if (stateMap.get(source) == null || stateMap.get(target) == null) {
                continue;
            }
            DefaultLocalTransition<S, E> transition = new DefaultLocalTransition<S, E>(stateMap.get(source),
                    stateMap.get(target), transitionData.getActions(), event, transitionData.getGuard(),
                    trigger, transitionData.getSecurityRule());
            transitions.add(transition);
        } else if (transitionData.getKind() == TransitionKind.INTERNAL) {
            DefaultInternalTransition<S, E> transition = new DefaultInternalTransition<S, E>(
                    stateMap.get(source), transitionData.getActions(), event, transitionData.getGuard(),
                    trigger, transitionData.getSecurityRule());
            transitions.add(transition);
        }
    }

    if (stateMachineTransitions.getJoins() != null) {
        for (Entry<S, List<S>> entry : stateMachineTransitions.getJoins().entrySet()) {
            if (stateMap.get(entry.getKey()) != null) {
                List<S> entryList = entry.getValue();
                for (S entryState : entryList) {
                    State<S, E> source = stateMap.get(entryState);
                    if (source != null && !source.isOrthogonal()) {
                        State<S, E> target = stateMap.get(entry.getKey());
                        DefaultExternalTransition<S, E> transition = new DefaultExternalTransition<S, E>(source,
                                target, null, null, null, null, null);
                        transitions.add(transition);
                    }
                }
            }
        }
    }

    Transition<S, E> initialTransition = new InitialTransition<S, E>(initialState, initialAction);
    StateMachine<S, E> machine = buildStateMachineInternal(states, transitions, initialState, initialTransition,
            null, defaultExtendedState, historyState, contextEvents, beanFactory, taskExecutor, taskScheduler,
            beanName, machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId(),
            uuid, stateMachineModel);
    return machine;
}

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 av  a 2 s.c o 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

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  av  a2 s . co  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();
    }
}