You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by at...@apache.org on 2014/03/14 01:50:35 UTC

svn commit: r1577400 - in /commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2: SCXMLExecutor.java SCXMLSemantics.java semantics/SCXMLSemanticsImpl.java

Author: ate
Date: Fri Mar 14 00:50:35 2014
New Revision: 1577400

URL: http://svn.apache.org/r1577400
Log:
SCXML-196

Modified:
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java?rev=1577400&r1=1577399&r2=1577400&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java Fri Mar 14 00:50:35 2014
@@ -437,17 +437,12 @@ public class SCXMLExecutor implements Se
         // CreateEmptyStatus
         currentStatus = new Status();
         Step step = new Step(null, currentStatus);
+        // execute initial script if defined
+        semantics.executeGlobalScript(step, stateMachine, eventdispatcher, errorReporter, scInstance);
         // DetermineInitialStates
-        semantics.determineInitialStates(stateMachine,
-                step.getAfterStatus().getStates(),
-                step.getEntryList(), errorReporter, scInstance);
-        // execute initial script if defined configured as transition so as to not trigger events
-        if (stateMachine.getInitialScript() != null) {
-            step.getTransitList().add((Transition)stateMachine.getInitialScript().getParent());
-        }
-        // ExecuteActions
-        semantics.executeActions(step, stateMachine, eventdispatcher,
-                errorReporter, scInstance);
+        semantics.determineInitialStates(step, stateMachine, errorReporter, scInstance);
+        // enter initial states
+        semantics.enterStates(step, stateMachine, eventdispatcher, errorReporter, scInstance);
         // AssignCurrentStatus
         updateStatus(step);
         // Execute Immediate Transitions

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java?rev=1577400&r1=1577399&r2=1577400&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java Fri Mar 14 00:50:35 2014
@@ -16,29 +16,18 @@
  */
 package org.apache.commons.scxml2;
 
-import java.util.List;
-import java.util.Set;
-
 import org.apache.commons.scxml2.model.ModelException;
 import org.apache.commons.scxml2.model.SCXML;
-import org.apache.commons.scxml2.model.TransitionTarget;
 
 /**
- * <p>The purpose of this interface is to separate the interpretation algorithm
+ * <p>The purpose of this interface is to separate the the
+ * <a href="http://www.w3.org/TR/2014/CR-scxml-20140313/#AlgorithmforSCXMLInterpretation">
+ *     W3C SCXML Algorithm for SCXML Interpretation</a>
  * from the <code>SCXMLExecutor</code> and therefore make it pluggable.</p>
  *
  * <p>Semantics agnostic utility functions and common operators as defined in
  * UML can be found in the <code>SCXMLHelper</code> or attached directly to
- * the SCXML model elements. Some of the possible semantic interpretations
- * are, for example:</p>
- *
- * <ul>
- * <li>STATEMATE
- * <li>RHAPSODY
- * <li>ROOMCharts
- * <li>UML 1.5
- * <li>UML 2.0
- * </ul>
+ * the SCXML model elements.</p>
  *
  * <p>Specific semantics can be created by subclassing
  * <code>org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl</code>.</p>
@@ -57,15 +46,25 @@ public interface SCXMLSemantics {
      */
     SCXML normalizeStateMachine(final SCXML input, final ErrorReporter errRep);
 
+    public void executeGlobalScript(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                                    final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+
+    public void exitStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                           final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+
+    public void executeTransitionContent(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                                         final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+
+    public void enterStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                            final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+
     /**
      * Determining the initial state(s) for this state machine.
      *
-     * @param input
+     * @param step
+     *            provides target states and entry list to fill in [out]
+     * @param stateMachine
      *            SCXML state machine
-     * @param states
-     *            a set of States to populate
-     * @param entryList
-     *            a list of States and Parallels to enter
      * @param errRep
      *            ErrorReporter callback
      * @param scInstance
@@ -74,8 +73,7 @@ public interface SCXMLSemantics {
      * @throws ModelException
      *             in case there is a fatal SCXML object model problem.
      */
-    void determineInitialStates(final SCXML input, final Set<TransitionTarget> states,
-            final List<TransitionTarget> entryList, final ErrorReporter errRep,
+    void determineInitialStates(final Step step, final SCXML stateMachine, final ErrorReporter errRep,
             final SCInstance scInstance)
     throws ModelException;
 
@@ -195,6 +193,5 @@ public interface SCXMLSemantics {
      */
     void initiateInvokes(final Step step, final ErrorReporter errRep,
             final SCInstance scInstance);
-
 }
 

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java?rev=1577400&r1=1577399&r2=1577400&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java Fri Mar 14 00:50:35 2014
@@ -46,6 +46,7 @@ import org.apache.commons.scxml2.Trigger
 import org.apache.commons.scxml2.invoke.Invoker;
 import org.apache.commons.scxml2.invoke.InvokerException;
 import org.apache.commons.scxml2.model.Action;
+import org.apache.commons.scxml2.model.Executable;
 import org.apache.commons.scxml2.model.Finalize;
 import org.apache.commons.scxml2.model.History;
 import org.apache.commons.scxml2.model.Initial;
@@ -185,6 +186,19 @@ public class SCXMLSemanticsImpl implemen
         return false;
     }
 
+    protected void executeContent(Executable exec, final EventDispatcher evtDispatcher, final ErrorReporter errRep,
+                                  final SCInstance scInstance, final Collection<TriggerEvent> internalEvents)
+            throws ModelException {
+
+        try {
+            for (Action action : exec.getActions()) {
+                action.execute(evtDispatcher, errRep, scInstance, appLog, internalEvents);
+            }
+        } catch (SCXMLExpressionException e) {
+            errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), exec);
+        }
+    }
+
     /**
      * @param input
      *            SCXML state machine
@@ -193,86 +207,32 @@ public class SCXMLSemanticsImpl implemen
      *            ErrorReporter callback
      */
     public SCXML normalizeStateMachine(final SCXML input,
-            final ErrorReporter errRep) {
+                                       final ErrorReporter errRep) {
         //it is a no-op for now
         return input;
     }
 
-    /**
-     * @param input
-     *            SCXML state machine [in]
-     * @param targets
-     *            a set of initial targets to populate [out]
-     * @param entryList
-     *            a list of States and Parallels to enter [out]
-     * @param errRep
-     *            ErrorReporter callback [inout]
-     * @param scInstance
-     *            The state chart instance [in]
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
-     */
-    public void determineInitialStates(final SCXML input, final Set<TransitionTarget> targets,
-            final List<TransitionTarget> entryList, final ErrorReporter errRep,
-            final SCInstance scInstance)
-            throws ModelException {
-        TransitionTarget tmp = input.getInitialTarget();
-        if (tmp == null) {
-            errRep.onError(ErrorConstants.NO_INITIAL,
-                    "SCXML initialstate is missing!", input);
-        } else {
-            targets.add(tmp);
-            determineTargetStates(targets, errRep, scInstance);
-            //set of ALL entered states (even if initialState is a jump-over)
-            Set<TransitionTarget> onEntry = SCXMLHelper.getAncestorClosure(targets, null);
-            // sort onEntry according state hierarchy
-            TransitionTarget[] oen = onEntry.toArray(new TransitionTarget[onEntry.size()]);
-            onEntry.clear();
-            Arrays.sort(oen, getTTComparator());
-            // we need to impose reverse order for the onEntry list
-            List<TransitionTarget> entering = Arrays.asList(oen);
-            Collections.reverse(entering);
-            entryList.addAll(entering);
-
+    public void executeGlobalScript(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                                    final ErrorReporter errRep, final SCInstance scInstance) throws ModelException {
+        if (stateMachine.getInitialScript() != null) {
+            try {
+                stateMachine.getInitialScript().execute(evtDispatcher, errRep, scInstance, appLog,
+                        step.getAfterStatus().getEvents());
+            } catch (SCXMLExpressionException e) {
+                errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), stateMachine);
+            }
         }
     }
 
-    /**
-     * Executes all OnExit/Transition/OnEntry transitional actions.
-     *
-     * @param step
-     *            provides EntryList, TransitList, ExitList gets
-     *            updated its AfterStatus/Events
-     * @param stateMachine
-     *            state machine - SCXML instance
-     * @param evtDispatcher
-     *            the event dispatcher - EventDispatcher instance
-     * @param errRep
-     *            error reporter
-     * @param scInstance
-     *            The state chart instance
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
-     */
-    public void executeActions(final Step step, final SCXML stateMachine,
-            final EventDispatcher evtDispatcher,
-            final ErrorReporter errRep, final SCInstance scInstance)
-    throws ModelException {
+    public void exitStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                           final ErrorReporter errRep, final SCInstance scInstance) throws ModelException {
         NotificationRegistry nr = scInstance.getNotificationRegistry();
         Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents();
         Map<TransitionTarget, Invoker> invokers = scInstance.getInvokers();
         // ExecutePhaseActions / OnExit
         for (TransitionTarget tt : step.getExitList()) {
             OnExit oe = tt.getOnExit();
-            try {
-                for (Action onExitAct : oe.getActions()) {
-                    onExitAct.execute(evtDispatcher,
-                        errRep, scInstance, appLog, internalEvents);
-                }
-            } catch (SCXMLExpressionException e) {
-                errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(),
-                        oe);
-            }
+            executeContent(oe, evtDispatcher, errRep, scInstance, internalEvents);
             // check if invoke is active in this state
             if (invokers.containsKey(tt)) {
                 Invoker toCancel = invokers.get(tt);
@@ -280,7 +240,7 @@ public class SCXMLSemanticsImpl implemen
                     toCancel.cancel();
                 } catch (InvokerException ie) {
                     TriggerEvent te = new TriggerEvent(tt.getId()
-                        + ".invoke.cancel.failed", TriggerEvent.ERROR_EVENT);
+                            + ".invoke.cancel.failed", TriggerEvent.ERROR_EVENT);
                     internalEvents.add(te);
                 }
                 // done here, don't wait for cancel response
@@ -292,35 +252,29 @@ public class SCXMLSemanticsImpl implemen
                     TriggerEvent.CHANGE_EVENT);
             internalEvents.add(te);
         }
-        // ExecutePhaseActions / Transitions
+    }
+
+    public void executeTransitionContent(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                                         final ErrorReporter errRep, final SCInstance scInstance) throws ModelException {
+        NotificationRegistry nr = scInstance.getNotificationRegistry();
+        Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents();
         for (Transition t : step.getTransitList()) {
-            try {
-                for (Action transitAct : t.getActions()) {
-                    transitAct.execute(evtDispatcher,
-                        errRep, scInstance, appLog, internalEvents);
-                }
-            } catch (SCXMLExpressionException e) {
-                errRep.onError(ErrorConstants.EXPRESSION_ERROR,
-                    e.getMessage(), t);
-            }
+            executeContent(t, evtDispatcher, errRep, scInstance, internalEvents);
             List<TransitionTarget> rtargets = t.getRuntimeTargets();
             for (TransitionTarget tt : rtargets) {
                 nr.fireOnTransition(t, t.getParent(), tt, t);
                 nr.fireOnTransition(stateMachine, t.getParent(), tt, t);
             }
         }
-        // ExecutePhaseActions / OnEntry
+    }
+
+    public void enterStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
+                            final ErrorReporter errRep, final SCInstance scInstance) throws ModelException {
+        NotificationRegistry nr = scInstance.getNotificationRegistry();
+        Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents();
         for (TransitionTarget tt : step.getEntryList()) {
             OnEntry oe = tt.getOnEntry();
-            try {
-                for (Action onEntryAct : oe.getActions()) {
-                    onEntryAct.execute(evtDispatcher,
-                        errRep, scInstance, appLog, internalEvents);
-                }
-            } catch (SCXMLExpressionException e) {
-                errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(),
-                        oe);
-            }
+            executeContent(oe, evtDispatcher, errRep, scInstance, internalEvents);
             nr.fireOnEntry(tt, tt);
             nr.fireOnEntry(stateMachine, tt);
             TriggerEvent te = new TriggerEvent(tt.getId() + ".entry",
@@ -330,17 +284,8 @@ public class SCXMLSemanticsImpl implemen
             if (tt instanceof State) {
                 State ts = (State) tt;
                 Initial ini = ts.getInitial();
-                if (ts.isComposite() && ini != null) {
-                    try {
-                        for (Action initialAct : ini.getTransition().
-                                getActions()) {
-                            initialAct.execute(evtDispatcher,
-                                errRep, scInstance, appLog, internalEvents);
-                        }
-                    } catch (SCXMLExpressionException e) {
-                        errRep.onError(ErrorConstants.EXPRESSION_ERROR,
-                            e.getMessage(), ini);
-                    }
+                if (ts.isComposite() && ini != null) { // TODO: use step.getDefaultEntrySet().contains(tt) instead
+                    executeContent(ini.getTransition(), evtDispatcher, errRep, scInstance, internalEvents);
                 }
                 if (ts.isFinal()) {
                     State parent = (State) ts.getParent();
@@ -368,7 +313,7 @@ public class SCXMLSemanticsImpl implemen
                         }
                         if (finCount == pCount) {
                             te = new TriggerEvent(p.getId() + ".done",
-                                        TriggerEvent.CHANGE_EVENT);
+                                    TriggerEvent.CHANGE_EVENT);
                             internalEvents.add(te);
                             scInstance.setDone(p, true);
                         }
@@ -379,6 +324,69 @@ public class SCXMLSemanticsImpl implemen
     }
 
     /**
+     * @param step
+     *            provides target states and entry list to fill in [out]
+     * @param stateMachine
+     *            SCXML state machine [in]
+     * @param errRep
+     *            ErrorReporter callback [inout]
+     * @param scInstance
+     *            The state chart instance [in]
+     * @throws org.apache.commons.scxml2.model.ModelException
+     *             in case there is a fatal SCXML object model problem.
+     */
+    public void determineInitialStates(final Step step, final SCXML stateMachine, final ErrorReporter errRep,
+                                       final SCInstance scInstance)
+            throws ModelException {
+        TransitionTarget tmp = stateMachine.getInitialTarget();
+        if (tmp == null) {
+            errRep.onError(ErrorConstants.NO_INITIAL,
+                    "SCXML initialstate is missing!", stateMachine);
+        } else {
+            Set<TransitionTarget> targets = step.getAfterStatus().getStates();
+            targets.add(tmp);
+            determineTargetStates(targets, errRep, scInstance);
+            //set of ALL entered states (even if initialState is a jump-over)
+            Set<TransitionTarget> onEntry = SCXMLHelper.getAncestorClosure(targets, null);
+            // sort onEntry according state hierarchy
+            TransitionTarget[] oen = onEntry.toArray(new TransitionTarget[onEntry.size()]);
+            onEntry.clear();
+            Arrays.sort(oen, getTTComparator());
+            // we need to impose reverse order for the onEntry list
+            List<TransitionTarget> entering = Arrays.asList(oen);
+            Collections.reverse(entering);
+            step.getEntryList().addAll(entering);
+
+        }
+    }
+
+    /**
+     * Executes all OnExit/Transition/OnEntry transitional actions.
+     *
+     * @param step
+     *            provides EntryList, TransitList, ExitList gets
+     *            updated its AfterStatus/Events
+     * @param stateMachine
+     *            state machine - SCXML instance
+     * @param evtDispatcher
+     *            the event dispatcher - EventDispatcher instance
+     * @param errRep
+     *            error reporter
+     * @param scInstance
+     *            The state chart instance
+     * @throws ModelException
+     *             in case there is a fatal SCXML object model problem.
+     */
+    public void executeActions(final Step step, final SCXML stateMachine,
+                               final EventDispatcher evtDispatcher,
+                               final ErrorReporter errRep, final SCInstance scInstance)
+            throws ModelException {
+        exitStates(step, stateMachine, evtDispatcher, errRep, scInstance);
+        executeTransitionContent(step, stateMachine, evtDispatcher, errRep, scInstance);
+        enterStates(step, stateMachine, evtDispatcher, errRep, scInstance);
+    }
+
+    /**
      * @param stateMachine
      *            a SM to traverse [in]
      * @param step
@@ -447,15 +455,7 @@ public class SCXMLSemanticsImpl implemen
             if (finalizeMatch(s.getId(), allEvents)) {
                 Finalize fn = s.getInvoke().getFinalize();
                 if (fn != null) {
-                    try {
-                        for (Action fnAct : fn.getActions()) {
-                            fnAct.execute(evtDispatcher, errRep, scInstance, appLog,
-                                step.getAfterStatus().getEvents());
-                        }
-                    } catch (SCXMLExpressionException e) {
-                        errRep.onError(ErrorConstants.EXPRESSION_ERROR,
-                            e.getMessage(), fn);
-                    }
+                    executeContent(fn, evtDispatcher, errRep, scInstance, step.getAfterStatus().getEvents());
                 }
             }
         }