Commons SCXML - 强制跳转到给定状态

发布于 2024-09-15 08:25:35 字数 249 浏览 7 评论 0原文

我正在使用 Apache Commons SCXML,我想知道是否可以告诉州政府机(SCXMLExecutor)跳转到给定状态。

我无法使用 initialstate 属性,因为我希望状态机恢复(即从电源故障中恢复),而我唯一拥有的就是最后一个状态。这就是为什么我正在考虑告诉状态机直接跳转到它。

I am using Apache Commons SCXML, and I would like to know if it is possible to tell the state machine (SCXMLExecutor) to jump to a given state.

I can not use the initialstate attribute, because I want the state machine to recover (i.e. from power failures), and the only thing I have is the last state. That is why I was thinking about telling the state machine to make a direct jump to it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你如我软肋 2024-09-22 08:25:35

在一般情况下,在状态机没有“意识到”的情况下跳转到一个状态是一个非常糟糕的主意,因为特定状态的执行可能存在不满足的先决条件(也就是说,如果您达到了“正常”)方式。更好的想法是设计具有“重新启动”功能的状态机,将其实现为输入“重新启动”事件以及处理该事件所需的状态和转换。

In the general case it's a really bad idea to jump to a state without the state machine's being "aware" of it, because there may be preconditions for a particular state's execution that aren't satisfied (that would be if you reached the state the "normal") way. A better idea is to design the state machine with a "restart" capability, implemented as an input "restart" event and the states and transitions necessary to handle it.

眼眸里的那抹悲凉 2024-09-22 08:25:35

这是一个老问题,但我刚刚遇到这个问题,也需要一个答案,并认为这可能会帮助其他人回答它。我将其用作单元测试的一部分,在单元测试中,进入特定状态非常有用(我想确保如果在状态 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);
}

This is an old question, but I just hit this and needed an answer to it as well and thought it might help others to answer it. I am using this as part of unit testing, where it IS extremely useful to just get to a particular state (I want to be sure that if at state A, if a sequence of events happens, it goes to state B - and still goes there after I tinker with the state machine XML!)

I finally found this code in SCXMLTestHelper and it worked. Just call it with the executor and the destination state.

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);
}
玩物 2024-09-22 08:25:35

这是一个老问题,但是在 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。幸运的是,这个对象是受保护的并且可以被派生类调用。

It's an old question, but in common-scxml2 the given code doesn't work anymore. I did some research and found a solution for the current version that works fine.

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

The main problem is the inaccessible SCInstance which contains the running statemachine. Fortunately this object is protected and can be called by derived classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文