Example usage for org.springframework.statemachine.access StateMachineAccess addStateMachineInterceptor

List of usage examples for org.springframework.statemachine.access StateMachineAccess addStateMachineInterceptor

Introduction

In this page you can find the example usage for org.springframework.statemachine.access StateMachineAccess addStateMachineInterceptor.

Prototype

void addStateMachineInterceptor(StateMachineInterceptor<S, E> interceptor);

Source Link

Document

Adds the state machine interceptor.

Usage

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

/**
 * Main constructor that create a {@link StateMachine}.
 *
 * @param uuid for internal usage. Can be null, in that case a random one will be generated.
 * @param machineId represent a user Id, up to you to set what you want.
 * @return a {@link StateMachine}//from w w w.  j  a va2s. c  om
 */
@SuppressWarnings("unchecked")
public StateMachine<S, E> getStateMachine(UUID uuid, String machineId) {
    StateMachineModel<S, E> stateMachineModel = resolveStateMachineModel(machineId);
    if (stateMachineModel.getConfigurationData().isVerifierEnabled()) {
        StateMachineModelVerifier<S, E> verifier = stateMachineModel.getConfigurationData().getVerifier();
        if (verifier == null) {
            verifier = new CompositeStateMachineModelVerifier<S, E>();
        }
        verifier.verify(stateMachineModel);
    }

    // shared
    DefaultExtendedState defaultExtendedState = new DefaultExtendedState();

    StateMachine<S, E> machine = null;

    // we store mappings from state id's to states which gets
    // created during the process. This is needed for transitions to
    // find a correct mappings because they use state id's, not actual
    // states.
    final Map<S, State<S, E>> stateMap = new HashMap<S, State<S, E>>();
    Stack<MachineStackItem<S, E>> regionStack = new Stack<MachineStackItem<S, E>>();
    Stack<StateData<S, E>> stateStack = new Stack<StateData<S, E>>();
    Map<Object, StateMachine<S, E>> machineMap = new HashMap<Object, StateMachine<S, E>>();
    Map<S, StateHolder<S, E>> holderMap = new HashMap<S, StateHolder<S, E>>();

    Iterator<Node<StateData<S, E>>> iterator = buildStateDataIterator(stateMachineModel);
    while (iterator.hasNext()) {
        Node<StateData<S, E>> node = iterator.next();
        StateData<S, E> stateData = node.getData();
        StateData<S, E> peek = stateStack.isEmpty() ? null : stateStack.peek();

        // simply push and continue
        if (stateStack.isEmpty()) {
            stateStack.push(stateData);
            continue;
        }

        boolean stackContainsSameParent = false;
        Iterator<StateData<S, E>> ii = stateStack.iterator();
        while (ii.hasNext()) {
            StateData<S, E> sd = ii.next();
            if (stateData != null && ObjectUtils.nullSafeEquals(stateData.getState(), sd.getParent())) {
                stackContainsSameParent = true;
                break;
            }
        }

        if (stateData != null && !stackContainsSameParent) {
            stateStack.push(stateData);
            continue;
        }

        Collection<StateData<S, E>> stateDatas = popSameParents(stateStack);
        int initialCount = getInitialCount(stateDatas);
        Collection<Collection<StateData<S, E>>> regionsStateDatas = splitIntoRegions(stateDatas);
        Collection<TransitionData<S, E>> transitionsData = getTransitionData(iterator.hasNext(), stateDatas,
                stateMachineModel);

        if (initialCount > 1) {
            for (Collection<StateData<S, E>> regionStateDatas : regionsStateDatas) {
                machine = buildMachine(machineMap, stateMap, holderMap, regionStateDatas, transitionsData,
                        resolveBeanFactory(stateMachineModel), contextEvents, defaultExtendedState,
                        stateMachineModel.getTransitionsData(), resolveTaskExecutor(stateMachineModel),
                        resolveTaskScheduler(stateMachineModel), machineId, null, stateMachineModel);
                regionStack.push(new MachineStackItem<S, E>(machine));
            }

            Collection<Region<S, E>> regions = new ArrayList<Region<S, E>>();
            while (!regionStack.isEmpty()) {
                MachineStackItem<S, E> pop = regionStack.pop();
                regions.add(pop.machine);
            }
            S parent = (S) peek.getParent();
            RegionState<S, E> rstate = buildRegionStateInternal(parent, regions, null,
                    stateData != null ? stateData.getEntryActions() : null,
                    stateData != null ? stateData.getExitActions() : null,
                    new DefaultPseudoState<S, E>(PseudoStateKind.INITIAL));
            if (stateData != null) {
                stateMap.put(stateData.getState(), rstate);
            } else {
                // TODO: don't like that we create a last machine here
                Collection<State<S, E>> states = new ArrayList<State<S, E>>();
                states.add(rstate);
                Transition<S, E> initialTransition = new InitialTransition<S, E>(rstate);
                StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(),
                        rstate, initialTransition, null, defaultExtendedState, null, contextEvents,
                        resolveBeanFactory(stateMachineModel), resolveTaskExecutor(stateMachineModel),
                        resolveTaskScheduler(stateMachineModel), beanName,
                        machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId(),
                        uuid, stateMachineModel);
                machine = m;
            }
        } else {
            machine = buildMachine(machineMap, stateMap, holderMap, stateDatas, transitionsData,
                    resolveBeanFactory(stateMachineModel), contextEvents, defaultExtendedState,
                    stateMachineModel.getTransitionsData(), resolveTaskExecutor(stateMachineModel),
                    resolveTaskScheduler(stateMachineModel), machineId, uuid, stateMachineModel);
            if (peek.isInitial() || (!peek.isInitial() && !machineMap.containsKey(peek.getParent()))) {
                machineMap.put(peek.getParent(), machine);
            }
        }

        stateStack.push(stateData);
    }

    // setup autostart for top-level machine
    if (machine instanceof LifecycleObjectSupport) {
        ((LifecycleObjectSupport) machine)
                .setAutoStartup(stateMachineModel.getConfigurationData().isAutoStart());
    }

    // set top-level machine as relay
    final StateMachine<S, E> fmachine = machine;
    fmachine.getStateMachineAccessor().doWithAllRegions(new StateMachineFunction<StateMachineAccess<S, E>>() {

        @Override
        public void apply(StateMachineAccess<S, E> function) {
            function.setRelay(fmachine);
        }
    });

    // add monitoring hooks
    final StateMachineMonitor<S, E> stateMachineMonitor = stateMachineModel.getConfigurationData()
            .getStateMachineMonitor();
    if (stateMachineMonitor != null || defaultStateMachineMonitor != null) {
        fmachine.getStateMachineAccessor().doWithRegion(new StateMachineFunction<StateMachineAccess<S, E>>() {

            @Override
            public void apply(StateMachineAccess<S, E> function) {
                if (defaultStateMachineMonitor != null) {
                    function.addStateMachineMonitor(defaultStateMachineMonitor);
                }
                if (stateMachineMonitor != null) {
                    function.addStateMachineMonitor(stateMachineMonitor);
                }
            }
        });
    }

    // TODO: should error out if sec is enabled but spring-security is not in cp
    if (stateMachineModel.getConfigurationData().isSecurityEnabled()) {
        final StateMachineSecurityInterceptor<S, E> securityInterceptor = new StateMachineSecurityInterceptor<S, E>(
                stateMachineModel.getConfigurationData().getTransitionSecurityAccessDecisionManager(),
                stateMachineModel.getConfigurationData().getEventSecurityAccessDecisionManager(),
                stateMachineModel.getConfigurationData().getEventSecurityRule());
        log.info("Adding security interceptor " + securityInterceptor);
        fmachine.getStateMachineAccessor()
                .doWithAllRegions(new StateMachineFunction<StateMachineAccess<S, E>>() {

                    @Override
                    public void apply(StateMachineAccess<S, E> function) {
                        function.addStateMachineInterceptor(securityInterceptor);
                    }
                });
    }

    // setup distributed state machine if needed.
    // we wrap previously build machine with a distributed
    // state machine and set it to use given ensemble.
    if (stateMachineModel.getConfigurationData().getStateMachineEnsemble() != null) {
        DistributedStateMachine<S, E> distributedStateMachine = new DistributedStateMachine<S, E>(
                stateMachineModel.getConfigurationData().getStateMachineEnsemble(), machine);
        distributedStateMachine.setAutoStartup(stateMachineModel.getConfigurationData().isAutoStart());
        distributedStateMachine.afterPropertiesSet();
        machine = distributedStateMachine;
    }

    for (StateMachineListener<S, E> listener : stateMachineModel.getConfigurationData()
            .getStateMachineListeners()) {
        machine.addStateListener(listener);
    }

    // go through holders and fix state references which
    // were not known at a time holder was created
    for (Entry<S, StateHolder<S, E>> holder : holderMap.entrySet()) {
        holder.getValue().setState(stateMap.get(holder.getKey()));
    }

    return delegateAutoStartup(machine);
}

From source file:org.springframework.statemachine.ensemble.DistributedStateMachine.java

@Override
protected void onInit() throws Exception {
    // TODO: should we register with all, not just top one?
    delegate.getStateMachineAccessor().doWithRegion(new StateMachineFunction<StateMachineAccess<S, E>>() {

        @Override/*from w  ww. j a  v a2 s .c  om*/
        public void apply(StateMachineAccess<S, E> function) {
            function.addStateMachineInterceptor(interceptor);
        }
    });

}

From source file:org.springframework.statemachine.recipes.tasks.TasksHandler.java

/**
 * Instantiates a new tasks handler. Intentionally private instantiation
 * meant to be called from a builder.//from   w  w  w  .ja va  2  s.  c om
 *
 * @param tasks the wrapped tasks
 * @param listener the tasks listener
 * @param taskExecutor the task executor
 * @param persist the state machine persist
 */
private TasksHandler(List<TaskWrapper> tasks, TasksListener listener, TaskExecutor taskExecutor,
        StateMachinePersist<String, String, Void> persist) {
    this.persist = persist;
    try {
        stateMachine = buildStateMachine(tasks, taskExecutor);
        if (persist != null) {
            final LocalStateMachineInterceptor interceptor = new LocalStateMachineInterceptor(persist);
            stateMachine.getStateMachineAccessor()
                    .doWithAllRegions(new StateMachineFunction<StateMachineAccess<String, String>>() {

                        @Override
                        public void apply(StateMachineAccess<String, String> function) {
                            function.addStateMachineInterceptor(interceptor);
                        }
                    });
        }
    } catch (Exception e) {
        throw new StateMachineException("Error building state machine from tasks", e);
    }
    if (listener != null) {
        addTasksListener(listener);
    }
}