scxmlapache-commons-scxml

State transition from state in scxml


I am trying to implement a control flow using Apache scxml. My state transitions are like

<scxml initial="State1">

    <state id = "State1"><transition event="event1" target="State2"></state>
    <state id = "State2">
        <transition event="event2" target="State3">
        <transition event="event3" target="State4">
    </state>
   <state id = "State3">
        <transition event="event4" target="State2">
   </state>

   <state id = "State4">
        <transition event="event5" target="State2">
   </state>

   <state id = "State5"><transition target="State1">
</scxml>

as a state machine it works fine and working without any issue. But I have couple of requirement for which I am facing issues in

  1. I have to check an external event in each state and if that event is true I have to go to the last state of the cycle. what would be the best way to achieve this?

  2. It is possible that when I am in state2 I can go to state4 or state5 via state3. Is it possible that I can fire an event or change the state from state3 after checking the conditions to go to state4 or state5?

Both the issues above seems to have the same solution but I am not able to figure out the best way to implement them.


Solution

  • Check an external event […] and if that event is true […] go to the last state of the cycle.

    You can do this most elegantly by wrapping all states in a parent wrapper and transitioning from there. For example:

    <scxml xmlns="http://www.w3.org/2005/07/scxml" initial="state1">
       <state id='all'>
         <!-- this will always be tested, no matter which child state you are in -->
         <transition event="externalevent" target="state5" />
         <state id="state1"><!-- ... --></state>
         <state id="state2"><!-- ... --></state>
         <state id="state3"><!-- ... --></state>
         <state id="state4"><!-- ... --></state>
         <state id="state5"><!-- ... --></state>
       </state>
    </scxml>
    

    It is possible that when I am in state2 I can go to state4 or state5 via state3?

    It seems like a bad pattern you are describing, but yes, this is possible. You need to set a flag on the way into the state, and use that flag to transition out immediately. For example, using a simple Lua datamodel (not supported by Apache SCXML, but used here for clarity):

     <datamodel>
       <data id="bounceTo" expr="-1" />
     </datamodel>
    
     <state id="state2">
       <transition event="bounce-3-4" target="state3">
         <assign location="bounceTo" expr="4" />
       </transition>
       <transition event="bounce-3-5" target="state3">
         <assign location="bounceTo" expr="5" />
       </transition>
     </state>
    
     <state id="state3">
       <transition cond="bounceTo==4" target="state4">
         <assign location="bounceTo" expr="-1" />
       </transition>
       <transition cond="bounceTo==5" target="state5">
         <assign location="bounceTo" expr="-1" />
       </transition>
     </state>
    

    Setting, testing, and clearing the data value in Apache SCXML is beyond my ken.

    However, I must ask WHY you want to do this. It seems that it would be far better, in my opinion, to replicate the enter or exit actions you presumably want from state3 on the transitions themselves, and let those transitions directly target state 4 or 5.