Почему происходит выход из состояния при переходе в одно из его подсостояний? - PullRequest
1 голос
/ 25 сентября 2019

Я пытаюсь реализовать конечный автомат с вложенными состояниями (как показано ниже) с помощью Spring Statemachine (версия 2.1.3).

Направленный конечный автомат

В приведенном ниже коде я предполагаю, что stateMachineDepth3 соответствует этой машине

package de.iotiq.test.statemachine;

import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;

public class Main {
    public static void main(String[] args) throws Exception {
        StateMachine<States, String> stateMachineDepth2;
        StateMachine<States, String> stateMachineDepth3;

        StateMachineBuilder.Builder<States, String> builder2 = StateMachineBuilder.builder();
        StateMachineBuilder.Builder<States, String> builder3 = StateMachineBuilder.builder();

        configureL2(builder2.configureStates(), null);
        configureL2(builder2.configureTransitions());

        configureL1(builder3.configureStates());
        configureL1(builder3.configureTransitions());

        stateMachineDepth2 = builder2.build();
        stateMachineDepth3 = builder3.build();

        stateMachineDepth2.addStateListener(new StateMachineListenerAdapter<States, String>() {

            @Override
            public void stateEntered(State<States, String> state) {
                System.out.println("State (D2) -> " + state.getId());
            }

            @Override
            public void stateExited(State<States, String> state) {
                System.out.println("State (D2) <- " + state.getId());
            }
        });

        stateMachineDepth3.addStateListener(new StateMachineListenerAdapter<States, String>() {

            @Override
            public void stateEntered(State<States, String> state) {
                System.out.println("State (D3) -> " + state.getId());
            }

            @Override
            public void stateExited(State<States, String> state) {
                System.out.println("State (D3) <- " + state.getId());
            }
        });

        stateMachineDepth2.start();
        stateMachineDepth3.start();
    }

    private static void configureL1(StateMachineStateConfigurer<States, String> states) throws Exception {
        states
            .withStates()
                .initial(States.S1)
                .state(States.S1)
                .state(States.S2)
        ;

        configureL2(states, States.S2);
    }

    private static void configureL2(StateMachineStateConfigurer<States, String> states, States parent) throws Exception {
        states
            .withStates()
                .parent(parent)
                .initial(States.S2a)
                .state(States.S2a)
                .state(States.S2b)
        ;

        configureL3(states);
    }

    private static void configureL3(StateMachineStateConfigurer<States, String> states) throws Exception {
        states
            .withStates()
                .parent(States.S2b)
                .initial(States.S2b1)
                .state(States.S2b1)
                .choice(States.S2b2)
                .state(States.S2b2)
                .state(States.S2b3)
                .state(States.S2b4)
                .state(States.S2b5)
        ;
    }

    private static void configureL1(StateMachineTransitionConfigurer<States, String> transitions) throws Exception {
        transitions
            .withExternal()
                .source(States.S1)
                .target(States.S2)
        ;

        configureL2(transitions);
    }

    private static void configureL2(StateMachineTransitionConfigurer<States, String> transitions) throws Exception {
        transitions
            .withExternal()
                .source(States.S2a)
                .target(States.S2b)
        ;

        configureL3(transitions);
    }

    private static void configureL3(StateMachineTransitionConfigurer<States, String> transitions) throws Exception {
        transitions
            .withExternal()
                .source(States.S2b1)
                .target(States.S2b2)
                .and()
            .withChoice()
                .source(States.S2b2)
                .first(States.S2b3, decide())
                .last(States.S2b4)
                .and()
            .withExternal()
                .source(States.S2b3)
                .target(States.S2b5)
                .and()
            .withExternal()
                .source(States.S2b4)
                .target(States.S2b5)
        ;
    }

    private static Guard<States, String> decide() {
        return new Guard<States, String>() {

            public boolean evaluate(StateContext<States, String> context) {

                System.out.println("eveluating...");

                return false;
            }
        };
    }
}

, когда я запускаю ее с stateMachineDepth3.start(); Я получаю следующий вывод

State (D3) -> S1
State (D3) <- S1
State (D3) -> S2
State (D3) -> S2a
State (D3) <- S2a
State (D3) -> S2b
State (D3) -> S2b1
eveluating...
State (D3) <- S2b1
State (D3) <- S2b
State (D3) -> S2b4
State (D3) <- S2b4
State (D3) -> S2b5

Как виднос выхода при переходе от S2b1 к S2b4 он выходит из S2b, что не должно быть.

Для конечного автомата с глубиной 2, как в stateMachineDepth2,который состоит из S2 внутренних элементов, похоже, что переходы такие же, как и ожидалось.Вывод будет таким, как показано ниже:

State (D2) -> S2a
State (D2) <- S2a
State (D2) -> S2b
State (D2) -> S2b1
eveluating...
State (D2) <- S2b1
State (D2) -> S2b4
State (D2) <- S2b4
State (D2) -> S2b5

Можете ли вы увидеть что-то неправильное в моей реализации statemachine?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...