Commons SCXML - принудительный переход в заданное состояние

Я использую Apache Commons SCXML, и я хотел бы знать, можно ли сказать конечному автомату (SCXMLExecutor) перейти в заданное состояние.

Я не могу использовать initialstate атрибут, потому что я хочу, чтобы конечный автомат восстанавливался (то есть после сбоев питания), и единственное, что у меня есть, это последнее состояние. Вот почему я думал о том, чтобы сказать государственному аппарату сделать прямой прыжок к нему.

3 ответа

Решение

В общем случае это действительно плохая идея - перейти в состояние, если конечный автомат "не знает" об этом, потому что могут быть предварительные условия для выполнения конкретного состояния, которые не удовлетворяются (это было бы, если бы вы достигли состояния "нормальный") путь. Лучшей идеей является разработка конечного автомата с возможностью "перезапуска", реализованного как входное событие "перезапуска", а также состояний и переходов, необходимых для его обработки.

Это старый вопрос, но я только что ответил на него, и мне тоже нужен был ответ, и я подумал, что это может помочь другим ответить на него. Я использую это как часть модульного тестирования, где чрезвычайно полезно просто перейти в определенное состояние (я хочу быть уверен, что если в состоянии A, если происходит последовательность событий, он переходит в состояние B - и все еще идет там после того как я повозился с конечным автоматом XML!)

Я наконец нашел этот код в SCXMLTestHelper, и он работал. Просто позвоните с исполнителем и государством назначения.

public static void setCurrentState(SCXMLExecutor exec, final String id) throws IllegalArgumentException{
    try {
        exec.reset();
    } catch (ModelException me) {
        throw new IllegalArgumentException("Provided SCXMLExecutor "
                + "instance cannot be reset.");
    }
    TransitionTarget active = (TransitionTarget) exec.getStateMachine().
            getTargets().get(id);
    if (active == null) {
        throw new IllegalArgumentException("No target with id '" + id
                + "' present in state machine.");
    }
    Set current = exec.getCurrentStatus().getStates();
    current.clear();
    current.add(active);
}

Это старый вопрос, но в common-scxml2 данный код больше не работает. Я провел небольшое исследование и нашел решение для текущей версии, которое отлично работает.

      import org.apache.commons.scxml2.SCInstance;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.model.EnterableState;
import org.apache.commons.scxml2.model.TransitionTarget;

public class AccessibleSCXMLExecutor extends SCXMLExecutor {

    public void setCurrentState(String targetId) {
        final EnterableState targetState = getStateMachine().getChildren().stream()
                .filter(s -> s.getId().equals(targetId))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("The state '" + targetId + "' is unknown"));

        final SCInstance scInstance = getSCInstance();
        scInstance.getStateConfiguration().clear();
        scInstance.getStateConfiguration().enterState(targetState);
    }
}

Основная проблема — недоступный SCInstance, содержащий работающий конечный автомат. К счастью, этот объектprotectedи может вызываться производными классами.

Другие вопросы по тегам