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 2017/12/09 23:23:01 UTC

commons-scxml git commit: SCXML-256 Add SCXMLExecutor.run() ans SCXMLSemantics.initialize(...) methods and SCXML early/late binding

Repository: commons-scxml
Updated Branches:
  refs/heads/master 370360e03 -> 49768f8be


SCXML-256 Add SCXMLExecutor.run() ans SCXMLSemantics.initialize(...) methods and SCXML early/late binding

This fixes 6 SCXML IRP tests (both jexl and ecma)


Project: http://git-wip-us.apache.org/repos/asf/commons-scxml/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-scxml/commit/49768f8b
Tree: http://git-wip-us.apache.org/repos/asf/commons-scxml/tree/49768f8b
Diff: http://git-wip-us.apache.org/repos/asf/commons-scxml/diff/49768f8b

Branch: refs/heads/master
Commit: 49768f8bed23fe42100474423a6699580b972a16
Parents: 370360e
Author: Ate Douma <at...@apache.org>
Authored: Sun Dec 10 00:22:53 2017 +0100
Committer: Ate Douma <at...@apache.org>
Committed: Sun Dec 10 00:22:53 2017 +0100

----------------------------------------------------------------------
 .../org/apache/commons/scxml2/SCInstance.java   | 61 +++++++++++++++-----
 .../commons/scxml2/SCXMLExecutionContext.java   | 53 ++++++++++-------
 .../apache/commons/scxml2/SCXMLExecutor.java    | 57 +++++++++++++-----
 .../apache/commons/scxml2/SCXMLSemantics.java   | 53 ++++++++++-------
 .../apache/commons/scxml2/io/SCXMLReader.java   | 14 +++++
 .../apache/commons/scxml2/io/SCXMLWriter.java   |  3 +
 .../org/apache/commons/scxml2/model/SCXML.java  | 15 ++++-
 .../scxml2/semantics/SCXMLSemanticsImpl.java    | 15 +++--
 .../scxml2/env/javascript/JSEvaluatorTest.java  |  1 +
 .../org/apache/commons/scxml2/w3c/W3CTests.java |  8 +--
 .../org/apache/commons/scxml2/w3c/tests.xml     | 22 +++----
 11 files changed, 205 insertions(+), 97 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/SCInstance.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCInstance.java b/src/main/java/org/apache/commons/scxml2/SCInstance.java
index 51fbbf5..18a9757 100644
--- a/src/main/java/org/apache/commons/scxml2/SCInstance.java
+++ b/src/main/java/org/apache/commons/scxml2/SCInstance.java
@@ -171,12 +171,32 @@ public class SCInstance implements Serializable {
         histories.clear();
         stateConfiguration.clear();
 
-        // Clone root datamodel
-        Datamodel rootdm = stateMachine.getDatamodel();
-        cloneDatamodel(rootdm, getGlobalContext(), evaluator, errorReporter);
         initialized = true;
     }
 
+    protected void initializeDatamodel(final Map<String, Object> data) {
+        if (globalContext == null) {
+            // Clone root datamodel
+            Datamodel rootdm = stateMachine.getDatamodel();
+            cloneDatamodel(rootdm, getGlobalContext(), evaluator, errorReporter);
+
+            // initialize/override global context data
+            if (data != null) {
+                for (String key : data.keySet()) {
+                    if (globalContext.has(key)) {
+                        globalContext.set(key, data.get(key));
+                    }
+                }
+            }
+            if (stateMachine.isLateBinding() == null || Boolean.FALSE.equals(stateMachine.isLateBinding())) {
+                // early binding
+                for (EnterableState es : stateMachine.getChildren()) {
+                    getContext(es);
+                }
+            }
+        }
+    }
+
     /**
      * Detach this state machine instance to allow external serialization.
      * <p>
@@ -292,10 +312,12 @@ public class SCInstance implements Serializable {
             return;
         }
         for (Data datum : data) {
-            if (ctx.has(datum.getId())) {
-                // earlier or externally defined 'initial' value found: do not overwrite
+            if (getGlobalContext() == ctx && ctx.has(datum.getId())) {
+                // earlier/externally defined 'initial' value found: do not overwrite
                 continue;
             }
+            Object value = null;
+            boolean setValue = false;
             /*
             TODO: external data.src support (not yet implemented), including late-binding thereof
             // prefer "src" over "expr" over "inline"
@@ -304,22 +326,25 @@ public class SCInstance implements Serializable {
             } else
             */
             if (datum.getExpr() != null) {
-                Object value;
                 try {
                     ctx.setLocal(Context.NAMESPACES_KEY, datum.getNamespaces());
                     value = evaluator.eval(ctx, datum.getExpr());
-                    ctx.setLocal(Context.NAMESPACES_KEY, null);
+                    setValue = true;
                 } catch (SCXMLExpressionException see) {
                     if (internalIOProcessor != null) {
                         internalIOProcessor.addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
                     }
                     errorReporter.onError(ErrorConstants.EXPRESSION_ERROR, see.getMessage(), datum);
-                    continue;
+                } finally {
+                    ctx.setLocal(Context.NAMESPACES_KEY, null);
                 }
-                ctx.setLocal(datum.getId(), value);
             }
             else {
-                ctx.setLocal(datum.getId(), evaluator.cloneData(datum.getValue()));
+                value = evaluator.cloneData(datum.getValue());
+                setValue = true;
+            }
+            if (setValue) {
+                ctx.setLocal(datum.getId(), value);
             }
         }
     }
@@ -346,15 +371,21 @@ public class SCInstance implements Serializable {
     }
 
     /**
-     * Sets the running status of the state machine
-     * @param running flag indicating the running status of the state machine
-     * @throws IllegalStateException Exception thrown if trying to set the state machine running when in a Final state
+     * Starts the state machine, {@link #isRunning()} hereafter will return true
+     * @throws IllegalStateException Exception thrown if trying to start the state machine when in a Final state
      */
-    protected void setRunning(final boolean running) throws IllegalStateException {
+    public void start() throws IllegalStateException {
         if (!this.running && running && currentStatus.isFinal()) {
             throw new IllegalStateException("The state machine is in a Final state and cannot be set running again");
         }
-        this.running = running;
+        this.running = true;
+    }
+
+    /**
+     * Stops the state machine, {@link #isRunning()} hereafter will return false
+     */
+    public void stop() {
+        this.running = false;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java b/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
index 99b1339..545feac 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
@@ -180,20 +180,6 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
     }
 
     /**
-     * @return Returns true if this state machine is running
-     */
-    public boolean isRunning() {
-        return scInstance.isRunning();
-    }
-
-    /**
-     * Stop a running state machine
-     */
-    public void stopRunning() {
-        scInstance.setRunning(false);
-    }
-
-    /**
      * Set if the SCXML configuration should be checked before execution (default = true)
      * @param checkLegalConfiguration flag to set
      */
@@ -209,21 +195,46 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
     }
 
     /**
-     * Initialize method which will cancel all current active Invokers, clear the internal event queue and mark the
-     * state machine process as running (again).
-     *
-     * @throws ModelException if the state machine instance failed to initialize.
+     * Initialize will cancel all current active Invokers, clear the internal event queue and (re)initialize the state machine
+     * @throws ModelException
      */
-    public void initialize() throws ModelException {
+    public void initialize(final Map<String, Object> data) throws ModelException {
         if (!invokeIds.isEmpty()) {
-            for (Invoke invoke : new ArrayList<Invoke>(invokeIds.keySet())) {
+            for (Invoke invoke : new ArrayList<>(invokeIds.keySet())) {
                 cancelInvoker(invoke);
             }
         }
         internalEventQueue.clear();
         scInstance.initialize();
         initializeIOProcessors();
-        scInstance.setRunning(true);
+        scInstance.initializeDatamodel(data);
+    }
+    /**
+     * (re)start the state machine.
+     *
+     * @throws ModelException if the state machine instance failed to initialize.
+     */
+    public void start() throws ModelException {
+        if (scInstance.isRunning()) {
+            throw new IllegalStateException("The state machine has already started.");
+        } else if (scInstance.getGlobalContext() == null) {
+            throw new IllegalStateException("The state machine has not been initialized yet.");
+        }
+        scInstance.start();
+    }
+
+    /**
+     * @return Returns true if this state machine is running
+     */
+    public boolean isRunning() {
+        return scInstance.isRunning();
+    }
+
+    /**
+     * Stop the state machine
+     */
+    public void stop() {
+        scInstance.stop();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java b/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
index 78f17f6..465ff35 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
@@ -16,7 +16,9 @@
  */
 package org.apache.commons.scxml2;
 
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -134,7 +136,7 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
     }
 
     /**
-     * Initializes the state machine with a specific active configuration
+     * starts the state machine with a specific active configuration, as the result of a (first) step
      * <p>
      * This will first (re)initialize the current state machine: clearing all variable contexts, histories and current
      * status, and clones the SCXML root datamodel into the root context.
@@ -146,8 +148,8 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
      * @see SCXMLSemantics#isLegalConfiguration(java.util.Set, ErrorReporter)
      */
     public synchronized void setConfiguration(Set<String> atomicStateIds) throws ModelException {
-        exctx.initialize();
-        Set<EnterableState> states = new HashSet<EnterableState>();
+        semantics.initialize(exctx, Collections.EMPTY_MAP);
+        Set<EnterableState> states = new HashSet<>();
         for (String stateId : atomicStateIds) {
             TransitionTarget tt = getStateMachine().getTargets().get(stateId);
             if (tt instanceof EnterableState && ((EnterableState)tt).isAtomicState()) {
@@ -169,6 +171,7 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
         else {
             throw new ModelException("Illegal state machine configuration!");
         }
+        exctx.start();
     }
 
     /**
@@ -405,32 +408,56 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
         return exctx.isRunning();
     }
 
-    /**
-     * Initiate state machine execution.
-     *
-     * @throws ModelException in case there is a fatal SCXML object
-     *  model problem.
-     */
     public void go() throws ModelException {
-        // same as reset
-        this.reset();
+        go(Collections.EMPTY_MAP);
     }
 
     /**
-     * Clear all state and begin executing the state machine
-     *
+     * Clear all state, optionally initialize/override global context data, and begin executing the state machine
+     * @data optional data to initialize/override data defined (only) in the global context of the state machine
      * @throws ModelException if the state machine instance failed to initialize
      */
-    public void reset() throws ModelException {
+    public void go(final Map<String, Object> data) throws ModelException {
+        // first stop the state machine (flag only, otherwise start may fail hereafter)
+        exctx.stop();
         // clear any pending external events
         externalEventQueue.clear();
 
-        // go
+        // (re)initialize
+        semantics.initialize(exctx, data);
+
+        // begin
         semantics.firstStep(exctx);
         logState();
     }
 
     /**
+     * Same as {@link #go}
+     * @throws ModelException if the state machine instance failed to initialize
+     */
+    public void reset() throws ModelException {
+        go();
+    }
+
+    public Thread run() throws ModelException {
+        return run(Collections.EMPTY_MAP);
+    }
+
+    public Thread run(final Map<String, Object> data) throws ModelException {
+        go(data);
+        Thread t = new Thread(() -> {
+            try {
+                while (exctx.isRunning()) {
+                    triggerEvents();
+                }
+            } catch (ModelException e) {
+            }
+        });
+        t.start();
+        return t;
+    }
+
+    /**
      * Add a new external event, which may be done concurrently, and even when the current SCInstance is detached.
      * <p>
      * No processing of the vent will be done, until the next triggerEvent methods is invoked.

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java b/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
index ae24472..9daca8c 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.scxml2;
 
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.scxml2.model.EnterableState;
@@ -28,33 +29,31 @@ import org.apache.commons.scxml2.model.SCXML;
  *     W3C SCXML Algorithm for SCXML Interpretation</a>
  * from the <code>SCXMLExecutor</code> and therefore make it pluggable.</p>
  * <p>
- * From an SCXML execution POV, there are only three entry points needed into the Algorithm, namely:
+ * From an SCXML execution POV, there are only four entry points needed into the Algorithm, namely:
  * </p>
  * <ul>
- *  <li>Performing the initialization of the state machine and completing a first macro step,
- *   see: {@link #firstStep(SCXMLExecutionContext)}. The state machine thereafter should be ready
- *   for processing external events (or be terminated already)</li>
- *  <li>Processing a single external event and completing the macro step for it, after which the
- *   state machine should be ready for processing another external event (if any), or be terminated already.
- *   See: {@link #nextStep(SCXMLExecutionContext, TriggerEvent)}.
+ *  <li>1: {@link #initialize(SCXMLExecutionContext, Map)} - Initialization of the state machine, optionally with external
+ *  (initial) data for the root (global) data elements in the root &lt;datamodel&gt;
  *  </li>
- *  <li>Finally, if the state machine terminated ({@link SCXMLExecutionContext#isRunning()} == false), after either
- *   of the above steps, finalize the state machine by performing the final step.
- *   See: {@link #finalStep(SCXMLExecutionContext)}.
- *   </li>
+ *  <li>2: {@link #firstStep(SCXMLExecutionContext)} - Performing and completing a first macro step, The state machine
+ *  thereafter should be ready for processing external events (or be terminated already)</li>
+ *  <li>3: {@link #nextStep(SCXMLExecutionContext, TriggerEvent)} - Processing a single external event and completing the
+ *  macro step for it, after which the state machine should be ready for processing another external event (if any),
+ *  or be terminated already.</li>
+ *  <li>4: {@link #finalStep(SCXMLExecutionContext)} - If the state machine terminated
+ *  ({@link SCXMLExecutionContext#isRunning()} == false), after either of the above steps, finalize the state machine
+ *  by performing the final step.</li>
  * </ul>
  * <p>After a state machine has been terminated you can re-initialize the execution context, and start again.</p>
  * <p>
- * Except for the loading of the SCXML document and (re)initializing the {@link SCXMLExecutionContext}, the above steps
- * represent the <b>interpret</b>,<b>mainEventLoop</b> and <b>exitInterpreter</b> entry points specified in Algorithm
- * for SCXML Interpretation, but more practically and logically broken into separate steps so that the blocking wait
- * for external events can be handled externally.
- * </p>
+ * The first two methods represent the <b>interpret</b> entry point specified in the Algorithm for SCXML Interpretation.
+ * The third and fourth method represent the <b>mainEventLoop</b> and <b>exitInterpreter</b> entry points.
+ * These have been more practically and logically broken into four different methods so that the blocking wait for
+ * external events can be handled externally.</p>
  * <p>
- *  These three entry points are the only interface methods used by the SCXMLExecutor. It is up to the
- *  specific SCXMLSemantics implementation to provide the concrete handling for these according to the Algorithm in
- *  the SCXML specification (or possibly something else/different).
- * </p>
+ *  It is up to the specific SCXMLSemantics implementation to provide the concrete handling for these methods according
+ *  to the <a href="https://www.w3.org/TR/2015/REC-scxml-20150901/#AlgorithmforSCXMLInterpretation">Algorithm for SCXML
+ *  Interpretation</a> in the SCXML specification (or possibly something else/non-conforming implementation).</p>
  * <p>
  * The default {@link org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl} provides an implementation of the
  * specification, and can easily be overridden/customized as a whole or only on specific parts of the Algorithm
@@ -72,8 +71,8 @@ import org.apache.commons.scxml2.model.SCXML;
 public interface SCXMLSemantics {
 
     /**
-     * Optional post processing immediately following SCXMLReader. May be used
-     * for removing pseudo-states etc.
+     * Optional post processing after loading an {@link SCXML} document, invoked by {@link SCXMLExecutor}
+     * when setting the {@link SCXMLExecutor#setStateMachine(SCXML)}. May be used for removing pseudo-states etc.
      *
      * @param input  SCXML state machine
      * @param errRep ErrorReporter callback
@@ -82,6 +81,16 @@ public interface SCXMLSemantics {
     SCXML normalizeStateMachine(final SCXML input, final ErrorReporter errRep);
 
     /**
+     * Initialize the SCXML state machine, optionally initializing (overriding) root &lt;datamodel&gt;&lt;data&gt; elements
+     * with external values provided through a data map.
+     * @param data A data map to initialize/override &lt;data&gt; elements in the root (global) &lt;datamodel&gt; with
+     *             ids matching the keys in the map (other data map entries will be ignored)
+     * @param exctx The execution context to initialize
+     * @throws ModelException
+     */
+    void initialize(final SCXMLExecutionContext exctx, final Map<String, Object> data) throws ModelException;
+
+    /**
      * First step in the execution of an SCXML state machine.
      * <p>
      * In the default implementation, this will first (re)initialize the state machine instance, destroying any existing

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
index b5b3329..f2f4ff5 100644
--- a/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
+++ b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
@@ -274,6 +274,7 @@ public final class SCXMLReader {
     private static final String ATTR_ARRAY = "array";
     private static final String ATTR_ATTR = "attr";
     private static final String ATTR_AUTOFORWARD = "autoforward";
+    static final String ATTR_BINDING = "binding";
     private static final String ATTR_COND = "cond";
     private static final String ATTR_DATAMODEL = "datamodel";
     private static final String ATTR_DELAY = "delay";
@@ -303,6 +304,9 @@ public final class SCXMLReader {
     private static final String ATTR_TYPEEXPR = "typeexpr";
     private static final String ATTR_VERSION = "version";
 
+    static final String BINDING_LATE = "late";
+    static final String BINDING_EARLY = "early";
+
     //------------------------- PUBLIC API METHODS -------------------------//
     /*
      * Public methods
@@ -633,6 +637,16 @@ public final class SCXMLReader {
         scxml.setName(readAV(reader, ATTR_NAME));
         scxml.setProfile(readAV(reader, ATTR_PROFILE));
         scxml.setVersion(readRequiredAV(reader, ELEM_SCXML, ATTR_VERSION));
+        String binding = readAV(reader, ATTR_BINDING);
+        if (binding != null) {
+            if (BINDING_LATE.equals(binding)) {
+                scxml.setLateBinding(true);
+            } else if (BINDING_EARLY.equals(binding)) {
+                scxml.setLateBinding(false);
+            } else {
+                reportIgnoredAttribute(reader, configuration, ELEM_SCXML, ATTR_BINDING, binding);
+            }
+        }
         if (!SCXML_REQUIRED_VERSION.equals(scxml.getVersion())) {
             throw new ModelException(new MessageFormat(ERR_INVALID_VERSION).format(new Object[] {scxml.getVersion()}));
         }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java b/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
index d4c6800..11842c6 100644
--- a/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
+++ b/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
@@ -494,6 +494,9 @@ public class SCXMLWriter {
         writeAV(writer, ATTR_VERSION, scxml.getVersion());
         writeAV(writer, ATTR_INITIAL, scxml.getInitial());
         writeAV(writer, ATTR_DATAMODEL, scxml.getDatamodelName());
+        if (scxml.isLateBinding() != null) {
+            writeAV(writer, SCXMLReader.ATTR_BINDING, scxml.isLateBinding() ? SCXMLReader.BINDING_LATE : SCXMLReader.BINDING_EARLY);
+        }
         writeAV(writer, ATTR_NAME, scxml.getName());
         writeAV(writer, ATTR_PROFILE, scxml.getProfile());
         writeAV(writer, ATTR_EXMODE, scxml.getExmode());

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/model/SCXML.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/SCXML.java b/src/main/java/org/apache/commons/scxml2/model/SCXML.java
index 2598372..f6764ca 100644
--- a/src/main/java/org/apache/commons/scxml2/model/SCXML.java
+++ b/src/main/java/org/apache/commons/scxml2/model/SCXML.java
@@ -28,8 +28,7 @@ import java.util.Map;
  * root&quot;.
  *
  */
-public class SCXML implements Serializable, Observable,
-                              NamespacePrefixesHolder {
+public class SCXML implements Serializable, Observable, NamespacePrefixesHolder {
 
     /**
      * Serial version UID.
@@ -88,6 +87,10 @@ public class SCXML implements Serializable, Observable,
      */
     private String exmode;
 
+    /**
+     * optional flag indicating if this document uses late or early (default) binding
+     */
+    private Boolean lateBinding;
 
     /**
      * The datamodel name as specified as "datamodel" attribute on this document
@@ -201,6 +204,14 @@ public class SCXML implements Serializable, Observable,
         this.datamodel = datamodel;
     }
 
+    public final void setLateBinding(final Boolean lateBinding) {
+        this.lateBinding = lateBinding;
+    }
+
+    public final Boolean isLateBinding() {
+        return lateBinding;
+    }
+
     /**
      * Get the immediate child targets of the SCXML root.
      *

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java b/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
index 0c7863e..0278832 100644
--- a/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
+++ b/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
@@ -87,6 +87,11 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
         return input;
     }
 
+    public void initialize(final SCXMLExecutionContext exctx, final Map<String, Object> data) throws ModelException {
+        // (re)initialize the execution context and state machine instance
+        exctx.initialize(data);
+    }
+
     /**
      * First step in the execution of an SCXML state machine.
      * <p>
@@ -109,8 +114,8 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
      * the execution.
      */
     public void firstStep(final SCXMLExecutionContext exctx) throws ModelException {
-        // (re)initialize the execution context and state machine instance
-        exctx.initialize();
+        // starts the state machine instance
+        exctx.start();
         // execute global script if defined
         executeGlobalScript(exctx);
         // enter initial states
@@ -160,7 +165,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
             return;
         }
         if (isCancelEvent(event)) {
-            exctx.stopRunning();
+            exctx.stop();
         }
         else {
             setSystemEventVariable(exctx.getScInstance(), event, false);
@@ -300,7 +305,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
                     TriggerEvent event = exctx.nextInternalEvent();
                     if (event != null) {
                         if (isCancelEvent(event)) {
-                            exctx.stopRunning();
+                            exctx.stop();
                         }
                         else {
                             setSystemEventVariable(exctx.getScInstance(), event, true);
@@ -1030,7 +1035,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
             if (es instanceof Final) {
                 State parent = (State)es.getParent();
                 if (parent == null) {
-                    exctx.stopRunning();
+                    exctx.stop();
                 }
                 else {
                     exctx.getInternalIOProcessor().addEvent(new TriggerEvent("done.state."+parent.getId(),TriggerEvent.CHANGE_EVENT));

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
index dc02916..e898b9c 100644
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
@@ -108,6 +108,7 @@ public class JSEvaluatorTest {
     @Before
     public void setUp() throws Exception {
             fsm = SCXMLTestHelper.getExecutor(SCXMLReader.read(new StringReader(SCRIPT)));
+            fsm.go();
             evaluator = fsm.getEvaluator();
             context = fsm.getGlobalContext();
             context.set(Context.NAMESPACES_KEY,null);

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java b/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
index edf7c5c..f86f22a 100644
--- a/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
+++ b/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
@@ -662,12 +662,8 @@ public class W3CTests {
             exec.addListener(doc, trc);
             exec.registerInvokerClass("scxml", SimpleSCXMLInvoker.class);
             exec.registerInvokerClass("http://www.w3.org/TR/scxml/", SimpleSCXMLInvoker.class);
-            exec.go();
-            Final end;
-            while ((end = exec.getStatus().getFinalState()) == null) {
-                Thread.sleep(100);
-                exec.triggerEvents();
-            }
+            exec.run().join();
+            Final end = exec.getStatus().getFinalState();
             System.out.println("                final state: "+end.getId());
             if (!testCase.isManual()) {
                 return end.getId().equals("pass");

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/49768f8b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
index deccdac..8f32647 100644
--- a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
+++ b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
@@ -53,10 +53,10 @@
   <test id="159" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="276" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="277" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="279" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="279" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="280" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="550" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
-  <test id="551" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="550" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
+  <test id="551" mandatory="true"                    manual="false" jexl="true" ecma="true"/>
   <test id="552" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="286" mandatory="true"                    manual="false" jexl="false" ecma="true"/>
   <test id="287" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
@@ -72,7 +72,7 @@
   <test id="302" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="303" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="304" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="307" mandatory="true"                    manual="true"  jexl="false"  ecma="false" finalState="final"/>
+  <test id="307" mandatory="true"                    manual="true"  jexl="false" ecma="false" finalState="final"/>
   <test id="309" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="310" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="311" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
@@ -86,17 +86,17 @@
   <test id="322" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="323" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="324" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="325" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
-  <test id="326" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="325" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
+  <test id="326" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="329" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="330" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="331" mandatory="true"                    manual="false" jexl="false" ecma="true"/>
+  <test id="331" mandatory="true"                    manual="false" jexl="false" ecma="true" implemented="false"/>
   <test id="332" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="333" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="335" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="336" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="337" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="338" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="338" mandatory="true"                    manual="false" jexl="false" ecma="false" implemented="false"/>
   <test id="339" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="342" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="346" mandatory="true"  profile="minimal" manual="false" jexl="true"  ecma="true"/>
@@ -118,7 +118,7 @@
   <test id="205" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
   <test id="521" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="553" mandatory="true"                    manual="false" jexl="true"  ecma="true"/>
-  <test id="207" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="207" mandatory="true"                    manual="false" jexl="false" ecma="false" implemented="false"/>
   <test id="208" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="210" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="215" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
@@ -135,7 +135,7 @@
   <test id="233" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="234" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="235" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
-  <test id="236" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
+  <test id="236" mandatory="true"                    manual="false" jexl="false" ecma="false" implemented="false"/>
   <test id="237" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="239" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="240" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
@@ -151,7 +151,7 @@
   <test id="530" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="554" mandatory="true"                    manual="false" jexl="false" ecma="false"/>
   <test id="436" mandatory="true"  profile="minimal" manual="false"                           minimal="true"/>
-  <test id="278" mandatory="false"                   manual="false" jexl="false" ecma="false"/>
+  <test id="278" mandatory="false" profile="ecma"    manual="false"              ecma="true"/>
   <test id="444" mandatory="false" profile="ecma"    manual="false"              ecma="true"/>
   <test id="445" mandatory="false" profile="ecma"    manual="false"              ecma="true"/>
   <test id="448" mandatory="false" profile="ecma"    manual="false"              ecma="true"/>