commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1583086 [1/3] - in /commons/proper/scxml/trunk/src: main/java/org/apache/commons/scxml2/ main/java/org/apache/commons/scxml2/invoke/ main/java/org/apache/commons/scxml2/model/ main/java/org/apache/commons/scxml2/semantics/ test/java/org/ap...
Date Sun, 30 Mar 2014 00:18:41 GMT
Author: ate
Date: Sun Mar 30 00:18:40 2014
New Revision: 1583086

URL: http://svn.apache.org/r1583086
Log:
SCXML-197: Better separation of concern between SCXMLExecutor and SCInstance and introducing a new SCXMLExecutionContext
See: https://issues.apache.org/jira/browse/SCXML-197
- move all persistable state to SCInstance and support detach/(re)attach the instance from the SCXMLExecutor, which no longer is Serializable
- introduce a new SCXMLExecutionContext to encapsulate all internal API and services
- switch to using the SCXMLExecutionContext as primary interface (parameter) for the SCXMLSemantics algorithms
- switch to use a restricted ActionExecutionContext (subset of SCXMLExecutionContext) as interface for the Action (SCXML Executable Content) execution
- add internal and (synchronous) external event queues and switch to 'single event step' processing as requirement by the SCXML specification

Added:
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java   (with props)
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java   (with props)
Modified:
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java
    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/Status.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Step.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Cancel.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/ElseIf.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Foreach.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/If.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Log.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Raise.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Script.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Send.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Var.java
    commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/NamespacePrefixedXPathsTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCXMLExecutorTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/StatusTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WildcardTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/WizardsTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/SerializableInitialBaseScriptTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/javascript/JSExampleTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/issues/Issue112Test.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/DatamodelTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/Hello.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/HistoryTest.java
    commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/model/StatelessModelTest.java

Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java?rev=1583086&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java Sun Mar 30 00:18:40 2014
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.scxml2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.scxml2.model.SCXML;
+
+/**
+ * ActionExecutionContext providing restricted access to the SCXML model, instance and services needed
+ * for the execution of {@link org.apache.commons.scxml2.model.Action} instances
+ */
+public class ActionExecutionContext {
+
+    /**
+     * The SCXML execution context this action exection context belongs to
+     */
+    private final SCXMLExecutionContext exctx;
+
+    /**
+     * Constructor
+     * @param exctx The SCXML execution context this action execution context belongs to
+     */
+    public ActionExecutionContext(SCXMLExecutionContext exctx) {
+        this.exctx = exctx;
+    }
+
+    /**
+     * @return Returns the state machine
+     */
+    public SCXML getStatemachine() {
+        return exctx.getStatemachine();
+    }
+
+    /**
+     * @return Returns the SCInstance
+     */
+    // TODO: remove access to SCInstance
+    public SCInstance getScInstance() {
+        return exctx.getScInstance();
+    }
+
+    /**
+     * @return Returns The evaluator.
+     */
+    public Evaluator getEvaluator() {
+        return exctx.getEvaluator();
+    }
+
+    /**
+     * @return Returns the error reporter
+     */
+    public ErrorReporter getErrorReporter() {
+        return exctx.getErrorReporter();
+    }
+
+    /**
+     * @return Returns the event dispatcher
+     */
+    public EventDispatcher getEventDispatcher() {
+        return exctx.getEventDispatcher();
+    }
+
+    /**
+     * Add an event to the internal queue
+     * @param event The event
+     */
+    public void addInternalEvent(TriggerEvent event) {
+        exctx.addInternalEvent(event);
+    }
+
+    /**
+     * @return Returns the SCXML Execution Logger for the application
+     */
+    public Log getAppLog() {
+        return exctx.getAppLog();
+    }
+}
\ No newline at end of file

Propchange: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/ActionExecutionContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java Sun Mar 30 00:18:40 2014
@@ -22,15 +22,11 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
-import org.apache.commons.scxml2.invoke.Invoker;
-import org.apache.commons.scxml2.invoke.InvokerException;
 import org.apache.commons.scxml2.model.Datamodel;
 import org.apache.commons.scxml2.model.EnterableState;
 import org.apache.commons.scxml2.model.History;
-import org.apache.commons.scxml2.model.Invoke;
-import org.apache.commons.scxml2.model.TransitionTarget;
+import org.apache.commons.scxml2.model.SCXML;
 import org.apache.commons.scxml2.model.TransitionalState;
 
 /**
@@ -46,9 +42,19 @@ public class SCInstance implements Seria
     private static final long serialVersionUID = 2L;
 
     /**
-     * The notification registry.
+     * The stateMachine being executed.
      */
-    private NotificationRegistry notificationRegistry;
+    private SCXML stateMachine;
+
+    /**
+     * The current status of the stateMachine.
+     */
+    private final Status currentStatus;
+
+    /**
+     * The owning state machine executor.
+     */
+    private transient SCXMLExecutor executor;
 
     /**
      * The <code>Map</code> of <code>Context</code>s per
@@ -69,24 +75,6 @@ public class SCInstance implements Seria
     private final Map<EnterableState, Boolean> completions;
 
     /**
-     * The <code>Invoker</code> classes <code>Map</code>, keyed by
-     * &lt;invoke&gt; target types (specified using "type" attribute).
-     */
-    private final Map<String, Class<? extends Invoker>> invokerClasses;
-
-    private final Map<Invoke, String> invokeIds;
-    /**
-     * The <code>Map</code> of active <code>Invoker</code>s, keyed by
-     * their <code>invokeId</code>.
-     */
-    private final Map<String, Invoker> invokers;
-
-    /**
-     * The evaluator for expressions.
-     */
-    private Evaluator evaluator;
-
-    /**
      * The root context.
      */
     private Context rootContext;
@@ -97,44 +85,50 @@ public class SCInstance implements Seria
     private Context globalScriptContext;
 
     /**
-     * The owning state machine executor.
-     */
-    private SCXMLExecutor executor;
-
-    /**
-     * Constructor.
+     * Constructor
      *
      * @param executor The executor that this instance is attached to.
      */
     SCInstance(final SCXMLExecutor executor) {
-        this.notificationRegistry = new NotificationRegistry();
+        this.currentStatus = new Status();
+        this.executor = executor;
         this.contexts = Collections.synchronizedMap(new HashMap<EnterableState, Context>());
         this.histories = Collections.synchronizedMap(new HashMap<History, Set<EnterableState>>());
-        this.invokerClasses = Collections.synchronizedMap(new HashMap<String, Class<? extends Invoker>>());
-        this.invokeIds = Collections.synchronizedMap(new HashMap<Invoke, String>());
-        this.invokers = Collections.synchronizedMap(new HashMap<String, Invoker>());
         this.completions = Collections.synchronizedMap(new HashMap<EnterableState, Boolean>());
-        this.evaluator = null;
-        this.rootContext = null;
-        this.executor = executor;
     }
 
     /**
-     * Get the <code>Evaluator</code>.
-     *
-     * @return The evaluator.
+     * @return Return the state machine for this instance
      */
-    public Evaluator getEvaluator() {
-        return evaluator;
+    public SCXML getStateMachine() {
+        return stateMachine;
     }
 
     /**
-     * Set the <code>Evaluator</code>.
-     *
-     * @param evaluator The evaluator.
+     * Sets the state machine for this instance
+     * @param stateMachine The state machine for this instance
+     */
+    void setStateMachine(SCXML stateMachine) {
+        this.stateMachine = stateMachine;
+        currentStatus.getStates().clear();
+        contexts.clear();
+        histories.clear();
+        completions.clear();
+    }
+
+    /**
+     * @return Returns the current status (active atomic states) for this instance
+     */
+    public Status getCurrentStatus() {
+        return currentStatus;
+    }
+
+    /**
+     * Re-attach the executor
+     * @param executor The executor that this instance will be re-attached to.
      */
-    void setEvaluator(final Evaluator evaluator) {
-        this.evaluator = evaluator;
+    void setExecutor(SCXMLExecutor executor) {
+        this.executor = executor;
     }
 
     /**
@@ -143,8 +137,8 @@ public class SCInstance implements Seria
      * @return The root context.
      */
     public Context getRootContext() {
-        if (rootContext == null && evaluator != null) {
-            rootContext = evaluator.newContext(null);
+        if (rootContext == null && executor.getEvaluator() != null) {
+            rootContext = executor.getEvaluator().newContext(null);
         }
         return rootContext;
     }
@@ -162,32 +156,13 @@ public class SCInstance implements Seria
         if (globalScriptContext == null) {
             Context rootContext = getRootContext();
             if (rootContext != null) {
-                globalScriptContext = evaluator.newContext(getRootContext());
+                globalScriptContext = executor.getEvaluator().newContext(getRootContext());
             }
         }
         return globalScriptContext;
     }
 
     /**
-     * Get the notification registry.
-     *
-     * @return The notification registry.
-     */
-    public NotificationRegistry getNotificationRegistry() {
-        return notificationRegistry;
-    }
-
-    /**
-     * Set the notification registry.
-     *
-     * @param notifRegistry The notification registry.
-     */
-    @SuppressWarnings("unused")
-    void setNotificationRegistry(final NotificationRegistry notifRegistry) {
-        this.notificationRegistry = notifRegistry;
-    }
-
-    /**
      * Get the <code>Context</code> for this <code>EnterableState</code>.
      * If one is not available it is created.
      *
@@ -200,13 +175,13 @@ public class SCInstance implements Seria
             EnterableState parent = state.getParent();
             if (parent == null) {
                 // docroot
-                context = evaluator.newContext(getGlobalScriptContext());
+                context = executor.getEvaluator().newContext(getGlobalScriptContext());
             } else {
-                context = evaluator.newContext(getContext(parent));
+                context = executor.getEvaluator().newContext(getContext(parent));
             }
             if (state instanceof TransitionalState) {
                 Datamodel datamodel = ((TransitionalState)state).getDatamodel();
-                SCXMLHelper.cloneDatamodel(datamodel, context, evaluator, null);
+                SCXMLHelper.cloneDatamodel(datamodel, context, executor.getEvaluator(), null);
             }
             contexts.put(state, context);
         }
@@ -288,111 +263,6 @@ public class SCInstance implements Seria
     }
 
     /**
-     * Get the {@link SCXMLExecutor} this instance is attached to.
-     *
-     * @return The SCXMLExecutor this instance is attached to.
-     * @see org.apache.commons.scxml2.SCXMLExecutor
-     */
-    public SCXMLExecutor getExecutor() {
-        return executor;
-    }
-
-    /**
-     * Register an {@link Invoker} class for this target type.
-     *
-     * @param type The target type (specified by "type" attribute of
-     *             &lt;invoke&gt; tag).
-     * @param invokerClass The <code>Invoker</code> <code>Class</code>.
-     */
-    void registerInvokerClass(final String type,
-            final Class<? extends Invoker> invokerClass) {
-        invokerClasses.put(type, invokerClass);
-    }
-
-    /**
-     * Remove the {@link Invoker} class registered for this target
-     * type (if there is one registered).
-     *
-     * @param type The target type (specified by "type" attribute of
-     *             &lt;invoke&gt; tag).
-     */
-    void unregisterInvokerClass(final String type) {
-        invokerClasses.remove(type);
-    }
-
-    /**
-     * Get the {@link Invoker} for this {@link TransitionTarget}.
-     * May return <code>null</code>. A non-null <code>Invoker</code> will be
-     * returned if and only if the <code>TransitionTarget</code> is
-     * currently active and contains an &lt;invoke&gt; child.
-     *
-     * @param type The type of the target being invoked.
-     * @return An {@link Invoker} for the specified type, if an
-     *         invoker class is registered against that type,
-     *         <code>null</code> otherwise.
-     * @throws InvokerException When a suitable {@link Invoker} cannot
-     *                          be instantiated.
-     */
-    public Invoker newInvoker(final String type)
-    throws InvokerException {
-        Class<? extends Invoker> invokerClass = invokerClasses.get(type);
-        if (invokerClass == null) {
-            throw new InvokerException("No Invoker registered for type \""
-                + type + "\"");
-        }
-        Invoker invoker;
-        try {
-            invoker = invokerClass.newInstance();
-        } catch (InstantiationException ie) {
-            throw new InvokerException(ie.getMessage(), ie.getCause());
-        } catch (IllegalAccessException iae) {
-            throw new InvokerException(iae.getMessage(), iae.getCause());
-        }
-        return invoker;
-    }
-
-    /**
-    * Get the {@link Invoker} for this {@link Invoke}.
-     * May return <code>null</code>. A non-null {@link Invoker} will be
-     * returned if and only if the {@link Invoke} parent TransitionalState is
-     * currently active and contains the &lt;invoke&gt; child.
-     *
-     * @param invoke The <code>Invoke</code>.
-     * @return The Invoker.
-     */
-    public Invoker getInvoker(final Invoke invoke) {
-        return invokers.get(invokeIds.get(invoke));
-    }
-
-    /**
-     * Set the {@link Invoker} for a {@link Invoke} and returns the unique invokerId for the Invoker
-     *
-     * @param invoke The Invoke.
-     * @param invoker The Invoker.
-     * @return The invokeId
-     */
-    public String setInvoker(final Invoke invoke, final Invoker invoker) {
-        String invokeId = invoke.getId();
-        if (SCXMLHelper.isStringEmpty(invokeId)) {
-            invokeId = UUID.randomUUID().toString();
-        }
-        invokeIds.put(invoke, invokeId);
-        invokers.put(invokeId, invoker);
-        return invokeId;
-    }
-
-    public void removeInvoker(final Invoke invoke) {
-        invokers.remove(invokeIds.remove(invoke));
-    }
-
-    /**
-     * @return Returns the map of current active Invokes and their invokeId
-     */
-    public Map<Invoke, String> getInvokeIds() {
-        return invokeIds;
-    }
-
-    /**
      * Get the completion status for this composite
      * {@link EnterableState}.
      *

Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java?rev=1583086&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java Sun Mar 30 00:18:40 2014
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.scxml2;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml2.invoke.Invoker;
+import org.apache.commons.scxml2.invoke.InvokerException;
+import org.apache.commons.scxml2.model.Invoke;
+import org.apache.commons.scxml2.model.SCXML;
+
+/**
+ * SCXMLExecutionContext provides all the services and internal data used during the interpretation of an SCXML
+ * statemachine across micro and macro steps
+ */
+public class SCXMLExecutionContext {
+
+    /**
+     * SCXML Execution Logger for the application.
+     */
+    private Log appLog = LogFactory.getLog(SCXMLExecutionContext.class);
+
+    /**
+     * The executor this execution context belongs to.
+     */
+    private final SCXMLExecutor executor;
+
+    /**
+     * The action execution context instance, providing restricted access to this execution context
+     */
+    private final ActionExecutionContext actionExecutionContext;
+
+    /**
+     * The internal event queue
+     */
+    private final Queue<TriggerEvent> internalEventQueue = new LinkedList<TriggerEvent>();
+
+    /**
+     * The map storing the unique invokeId for an Invoke with an active Invoker
+     */
+    private final Map<Invoke, String> invokeIds = new HashMap<Invoke, String>();
+
+    /**
+     * The Map of active Invoker, keyed by their unique invokeId.
+     */
+    private final Map<String, Invoker> invokers = new HashMap<String, Invoker>();
+
+    /**
+     * Running status for this state machine
+     */
+    private boolean running;
+
+    /**
+     * Constructor
+     * @param executor the executor this execution context belongs to
+     */
+    SCXMLExecutionContext(SCXMLExecutor executor) {
+        this.executor = executor;
+        this.actionExecutionContext = new ActionExecutionContext(this);
+        running = true;
+    }
+
+    /**
+     * @return Returns the restricted execution context for actions
+     */
+    public ActionExecutionContext getActionExecutionContext() {
+        return actionExecutionContext;
+    }
+
+    /**
+     * @return Returns true if this state machine is running
+     */
+    public boolean isRunning() {
+        return running;
+    }
+
+    /**
+     * Stop a running state machine
+     */
+    public void stopRunning() {
+        this.running = false;
+    }
+
+    /**
+     * Internal reset which will cancel all current active Invokers, clear the internal event queue and mark the
+     * state machine process as running (again).
+     */
+    void reset() {
+        if (!invokeIds.isEmpty()) {
+            for (Invoke invoke : new ArrayList<Invoke>(invokeIds.keySet())) {
+                cancelInvoker(invoke);
+            }
+        }
+        internalEventQueue.clear();
+        running = true;
+    }
+
+    /**
+     * @return Returns the SCXML Execution Logger for the application
+     */
+    public Log getAppLog() {
+        return appLog;
+    }
+
+    /**
+     * @return Returns the state machine
+     */
+    public SCXML getStatemachine() {
+        return executor.getStateMachine();
+    }
+
+    /**
+     * @return Returns the SCInstance
+     */
+    public SCInstance getScInstance() {
+        return executor.getSCInstance();
+    }
+
+    /**
+     * @return Returns The evaluator.
+     */
+    public Evaluator getEvaluator() {
+        return executor.getEvaluator();
+    }
+
+    /**
+     * @return Returns the error reporter
+     */
+    public ErrorReporter getErrorReporter() {
+        return executor.getErrorReporter();
+    }
+
+    /**
+     * @return Returns the event dispatcher
+     */
+    public EventDispatcher getEventDispatcher() {
+        return executor.getEventdispatcher();
+    }
+
+    /**
+     * @return Returns the notification registry
+     */
+    public NotificationRegistry getNotificationRegistry() {
+        return executor.getNotificationRegistry();
+    }
+
+    /**
+     * Get the {@link Invoker} for this {@link Invoke}.
+     * May return <code>null</code>. A non-null {@link Invoker} will be
+     * returned if and only if the {@link Invoke} parent TransitionalState is
+     * currently active and contains the &lt;invoke&gt; child.
+     *
+     * @param invoke The <code>Invoke</code>.
+     * @return The Invoker.
+     */
+    public Invoker getInvoker(final Invoke invoke) {
+        return invokers.get(invokeIds.get(invoke));
+    }
+
+    /**
+     * Create a new {@link Invoker}
+     *
+     * @param type The type of the target being invoked.
+     * @return An {@link Invoker} for the specified type, if an
+     *         invoker class is registered against that type,
+     *         <code>null</code> otherwise.
+     * @throws InvokerException When a suitable {@link Invoker} cannot
+     *                          be instantiated.
+     */
+    public Invoker newInvoker(String type) throws InvokerException {
+        return executor.newInvoker(type);
+    }
+
+    /**
+     * Set the {@link Invoker} for a {@link Invoke} and returns the unique invokerId for the Invoker
+     *
+     * @param invoke The Invoke.
+     * @param invoker The Invoker.
+     * @return The invokeId
+     */
+    public String setInvoker(final Invoke invoke, final Invoker invoker) {
+        String invokeId = invoke.getId();
+        if (SCXMLHelper.isStringEmpty(invokeId)) {
+            invokeId = UUID.randomUUID().toString();
+        }
+        invokeIds.put(invoke, invokeId);
+        invokers.put(invokeId, invoker);
+        return invokeId;
+    }
+
+    /**
+     * Remove a previously active Invoker, which must already have been canceled
+     * @param invoke The Invoke for the Invoker to remove
+     */
+    public void removeInvoker(final Invoke invoke) {
+        invokers.remove(invokeIds.remove(invoke));
+    }
+
+    /**
+     * @return Returns the map of current active Invokes and their invokeId
+     */
+    public Map<Invoke, String> getInvokeIds() {
+        return invokeIds;
+    }
+
+
+    /**
+     * Cancel and remove an active Invoker
+     *
+     * @param invoke The Invoke for the Invoker to cancel
+     */
+    public void cancelInvoker(Invoke invoke) {
+        String invokeId = invokeIds.get(invoke);
+        if (invokeId != null) {
+            try {
+                invokers.get(invokeId).cancel();
+            } catch (InvokerException ie) {
+                TriggerEvent te = new TriggerEvent(invokeId
+                        + ".invoke.cancel.failed", TriggerEvent.ERROR_EVENT);
+                addInternalEvent(te);
+            }
+            removeInvoker(invoke);
+        }
+    }
+
+    /**
+     * Add an event to the internal queue
+     * @param event The event
+     */
+    public void addInternalEvent(TriggerEvent event) {
+        internalEventQueue.add(event);
+    }
+
+    /**
+     * @return Returns the next event from the internal queue, if available
+     */
+    TriggerEvent nextInternalEvent() {
+        return internalEventQueue.poll();
+    }
+}

Propchange: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

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=1583086&r1=1583085&r2=1583086&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 Sun Mar 30 00:18:40 2014
@@ -16,23 +16,21 @@
  */
 package org.apache.commons.scxml2;
 
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.scxml2.invoke.Invoker;
+import org.apache.commons.scxml2.invoke.InvokerException;
 import org.apache.commons.scxml2.model.Datamodel;
 import org.apache.commons.scxml2.model.EnterableState;
 import org.apache.commons.scxml2.model.History;
 import org.apache.commons.scxml2.model.ModelException;
 import org.apache.commons.scxml2.model.Observable;
 import org.apache.commons.scxml2.model.SCXML;
-import org.apache.commons.scxml2.model.State;
 import org.apache.commons.scxml2.model.TransitionTarget;
 import org.apache.commons.scxml2.model.TransitionalState;
 import org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl;
@@ -48,14 +46,8 @@ import org.apache.commons.scxml2.system.
  *
  * @see SCXMLSemantics
  */
-@SuppressWarnings("deprecation") // TODO: remove again after refactoring is done
-public class SCXMLExecutor implements Serializable {
-
-    /**
-     * Serial version UID.
-     */
-    private static final long serialVersionUID = 1L;
-
+@SuppressWarnings("unused deprecation") // TODO: remove again after refactoring is done
+public class SCXMLExecutor {
 
     /**
      * The special variable for storing single event data / payload.
@@ -85,14 +77,9 @@ public class SCXMLExecutor implements Se
     private Log log = LogFactory.getLog(SCXMLExecutor.class);
 
     /**
-     * The stateMachine being executed.
+     * The evaluator for expressions.
      */
-    private SCXML stateMachine;
-
-    /**
-     * The current status of the stateMachine.
-     */
-    private Status currentStatus;
+    private Evaluator evaluator;
 
     /**
      * The event dispatcher to interface with external documents etc.
@@ -105,6 +92,11 @@ public class SCXMLExecutor implements Se
     private ErrorReporter errorReporter = null;
 
     /**
+     * The notification registry.
+     */
+    private NotificationRegistry notificationRegistry;
+
+    /**
      * Run-to-completion.
      */
     private boolean superStep = true;
@@ -120,6 +112,22 @@ public class SCXMLExecutor implements Se
     private SCInstance scInstance;
 
     /**
+     * The external event queue
+     */
+    private final Queue<TriggerEvent> externalEventQueue = new ConcurrentLinkedQueue<TriggerEvent>();
+
+    /**
+     * The <code>Invoker</code> classes <code>Map</code>, keyed by
+     * &lt;invoke&gt; target types (specified using "type" attribute).
+     */
+    private final Map<String, Class<? extends Invoker>> invokerClasses;
+
+    /**
+     * The state machine execution context
+     */
+    private SCXMLExecutionContext exctx;
+
+    /**
      * Get the state chart instance for this executor.
      *
      * @return The SCInstance for this executor.
@@ -129,12 +137,48 @@ public class SCXMLExecutor implements Se
     }
 
     /**
+     * Detach the current SCInstance to allow external serialization.
+     * <p>
+     * {@link #attachInstance(SCInstance)} can be used to re-attach a previously detached instance
+     * </p>
+     * <p>
+     * Note: until an instance is re-attached, no operations are allowed (and probably throw exceptions) except
+     * for {@link #addEvent(TriggerEvent)} which might still be used (concurrently) by running Invokers, or
+     * {@link #hasPendingEvents()} to check for possible pending events.
+     * </p>
+     * @return the detached instance
+     */
+    public SCInstance detachInstance() {
+        SCInstance instance = scInstance;
+        scInstance.setExecutor(null);
+        scInstance = null;
+        return instance;
+    }
+
+    /**
+     * Re-attach a previously detached SCInstance.
+     * <p>
+     * Note: an already attached instance will get overwritten (and thus lost).
+     * </p>
+     * @param instance An previously detached SCInstance
+     */
+    public void attachInstance(SCInstance instance) {
+        if (scInstance != null ) {
+            scInstance.setExecutor(null);
+        }
+        scInstance = instance;
+        if (scInstance != null) {
+            scInstance.setExecutor(this);
+        }
+    }
+
+    /**
      * Log the current set of active states.
      */
     private void logState() {
         if (log.isDebugEnabled()) {
             StringBuilder sb = new StringBuilder("Current States: [ ");
-            for (EnterableState es : currentStatus.getStates()) {
+            for (EnterableState es : getCurrentStatus().getStates()) {
                 sb.append(es.getId()).append(", ");
             }
             int length = sb.length();
@@ -147,61 +191,42 @@ public class SCXMLExecutor implements Se
      * @param step The most recent Step
      */
     private void updateStatus(final Step step) {
-        currentStatus = step.getAfterStatus();
-        scInstance.getRootContext().setLocal("_ALL_STATES",
-                SCXMLHelper.getAncestorClosure(currentStatus.getStates(), null));
-        setEventData(currentStatus.getEvents().toArray(new TriggerEvent[currentStatus.getEvents().size()]));
+        getCurrentStatus().getStates().clear();
+        getCurrentStatus().getStates().addAll(step.getAfterStatus().getStates());
+        scInstance.getRootContext().setLocal("_ALL_STATES", getCurrentStatus().getAllStates());
     }
 
     /**
-     * @param evts The events being triggered.
-     * @return Object[] Previous values.
+     * @param evt The event being triggered.
      */
-    private Object[] setEventData(final TriggerEvent[] evts) {
+    private void setEventData(final TriggerEvent evt) {
         Context rootCtx = scInstance.getRootContext();
-        Object[] oldData = { rootCtx.get(EVENT_DATA), rootCtx.get(EVENT_DATA_MAP), rootCtx.get(EVENT_VARIABLE) };
-        int len = evts.length;
-        if (len > 0) { // 0 has retry semantics (eg: see usage in reset())
-            Object eventData = null;
-            EventVariable eventVar = null;
-            Map<String, Object> payloadMap = new HashMap<String, Object>();
-            for (TriggerEvent te : evts) {
-                payloadMap.put(te.getName(), te.getPayload());
-            }
-            if (len == 1) {
-                // we have only one event
-                eventData = evts[0].getPayload();
-
-                // NOTE: According to spec 5.10.1, _event.type must be 'platform', 'internal' or 'external'.
-                //       So, error or variable change trigger events can be translated into 'platform' type event variables.
-                //       However, the Send model for <send> element doesn't support any target yet, and so
-                //       'internal' type can't supported either.
-                //       All the others must be 'external'.
+        Object eventData = null;
+        EventVariable eventVar = null;
+        Map<String, Object> payloadMap = new HashMap<String, Object>();
+        if (evt != null) { // 0 has retry semantics (eg: see usage in reset())
+            payloadMap.put(evt.getName(), evt.getPayload());
+            eventData = evt.getPayload();
+
+            // NOTE: According to spec 5.10.1, _event.type must be 'platform', 'internal' or 'external'.
+            //       So, error or variable change trigger events can be translated into 'platform' type event variables.
+            //       However, the Send model for <send> element doesn't support any target yet, and so
+            //       'internal' type can't supported either.
+            //       All the others must be 'external'.
 
-                String eventType = EventVariable.TYPE_EXTERNAL;
-                final int triggerEventType = evts[0].getType();
+            String eventType = EventVariable.TYPE_EXTERNAL;
+            final int triggerEventType = evt.getType();
 
-                if (triggerEventType == TriggerEvent.ERROR_EVENT || triggerEventType == TriggerEvent.CHANGE_EVENT) {
-                    eventType = EventVariable.TYPE_PLATFORM;
-                }
-
-                // TODO: determine sendid, origin, originType and invokeid based on context later.
-                eventVar = new EventVariable(evts[0].getName(), eventType, null, null, null, null, eventData);
+            if (triggerEventType == TriggerEvent.ERROR_EVENT || triggerEventType == TriggerEvent.CHANGE_EVENT) {
+                eventType = EventVariable.TYPE_PLATFORM;
             }
-            rootCtx.setLocal(EVENT_DATA, eventData);
-            rootCtx.setLocal(EVENT_DATA_MAP, payloadMap);
-            rootCtx.setLocal(EVENT_VARIABLE, eventVar);
-        }
-        return oldData;
-    }
 
-    /**
-     * @param oldData The old values to restore to.
-     */
-    private void restoreEventData(final Object[] oldData) {
-        scInstance.getRootContext().setLocal(EVENT_DATA, oldData[0]);
-        scInstance.getRootContext().setLocal(EVENT_DATA_MAP, oldData[1]);
-        scInstance.getRootContext().setLocal(EVENT_VARIABLE, oldData[2]);
+            // TODO: determine sendid, origin, originType and invokeid based on context later.
+            eventVar = new EventVariable(evt.getName(), eventType, null, null, null, null, eventData);
+        }
+        rootCtx.setLocal(EVENT_DATA, eventData);
+        rootCtx.setLocal(EVENT_DATA_MAP, payloadMap);
+        rootCtx.setLocal(EVENT_VARIABLE, eventVar);
     }
 
     /**
@@ -234,10 +259,9 @@ public class SCXMLExecutor implements Se
     public SCXMLExecutor(final Evaluator expEvaluator,
                          final EventDispatcher evtDisp, final ErrorReporter errRep,
                          final SCXMLSemantics semantics) {
+        this.evaluator = expEvaluator;
         this.eventdispatcher = evtDisp;
         this.errorReporter = errRep;
-        this.currentStatus = new Status();
-        this.stateMachine = null;
         if (semantics == null) {
             // Use default semantics, if none provided
             this.semantics = new SCXMLSemanticsImpl();
@@ -245,7 +269,9 @@ public class SCXMLExecutor implements Se
             this.semantics = semantics;
         }
         this.scInstance = new SCInstance(this);
-        this.scInstance.setEvaluator(expEvaluator);
+        this.notificationRegistry = new NotificationRegistry();
+        this.invokerClasses = new HashMap<String, Class<? extends Invoker>>();
+        this.exctx = new SCXMLExecutionContext(this);
     }
 
     /**
@@ -254,7 +280,7 @@ public class SCXMLExecutor implements Se
      * @return The current Status
      */
     public synchronized Status getCurrentStatus() {
-        return currentStatus;
+        return scInstance.getCurrentStatus();
     }
 
     /**
@@ -264,7 +290,7 @@ public class SCXMLExecutor implements Se
      * @param evaluator The evaluator to set.
      */
     public void setEvaluator(final Evaluator evaluator) {
-        this.scInstance.setEvaluator(evaluator);
+        this.evaluator = evaluator;
     }
 
     /**
@@ -273,7 +299,7 @@ public class SCXMLExecutor implements Se
      * @return Evaluator The evaluator in use.
      */
     public Evaluator getEvaluator() {
-        return scInstance.getEvaluator();
+        return evaluator;
     }
 
     /**
@@ -308,7 +334,7 @@ public class SCXMLExecutor implements Se
      * @return Returns the stateMachine.
      */
     public SCXML getStateMachine() {
-        return stateMachine;
+        return scInstance.getStateMachine();
     }
 
     /**
@@ -318,7 +344,9 @@ public class SCXMLExecutor implements Se
      * @param stateMachine The stateMachine to set.
      */
     public void setStateMachine(final SCXML stateMachine) {
-        this.stateMachine = semantics.normalizeStateMachine(stateMachine, errorReporter);
+        exctx.reset();
+        scInstance.setStateMachine(semantics.normalizeStateMachine(stateMachine, errorReporter));
+        externalEventQueue.clear();
     }
 
     /**
@@ -358,6 +386,25 @@ public class SCXMLExecutor implements Se
     }
 
     /**
+     * Get the notification registry.
+     *
+     * @return The notification registry.
+     */
+    public NotificationRegistry getNotificationRegistry() {
+        return notificationRegistry;
+    }
+
+    /**
+     * Set the notification registry.
+     *
+     * @param notifRegistry The notification registry.
+     */
+    @SuppressWarnings("unused")
+    void setNotificationRegistry(final NotificationRegistry notifRegistry) {
+        this.notificationRegistry = notifRegistry;
+    }
+
+    /**
      * Use &quot;super-step&quot;, default is <code>true</code>
      * (that is, run-to-completion is default).
      *
@@ -402,17 +449,17 @@ public class SCXMLExecutor implements Se
      *         model problem.
      */
     public synchronized void reset() throws ModelException {
-        // Reset all variable contexts
-        Context rootCtx = scInstance.getRootContext();
-        // Clone root datamodel
-        if (stateMachine == null) {
+        if (getStateMachine() == null) {
             log.error(ERR_NO_STATE_MACHINE);
             throw new ModelException(ERR_NO_STATE_MACHINE);
-        } else {
-            Datamodel rootdm = stateMachine.getDatamodel();
-            SCXMLHelper.cloneDatamodel(rootdm, rootCtx,
-                    scInstance.getEvaluator(), log);
         }
+        // Reset all variable contexts
+        exctx.reset();
+        Context rootContext = scInstance.getRootContext();
+        // Clone root datamodel
+        SCXML stateMachine = getStateMachine();
+        Datamodel rootdm = stateMachine.getDatamodel();
+        SCXMLHelper.cloneDatamodel(rootdm, rootContext, getEvaluator(), log);
         if (scInstance.getGlobalScriptContext() != null) {
             scInstance.getGlobalScriptContext().reset();
         }
@@ -424,30 +471,33 @@ public class SCXMLExecutor implements Se
                     context.reset();
                     if (tt instanceof TransitionalState) {
                         Datamodel dm = ((TransitionalState)tt).getDatamodel();
-                        SCXMLHelper.cloneDatamodel(dm, context, scInstance.getEvaluator(), log);
+                        SCXMLHelper.cloneDatamodel(dm, context, getEvaluator(), log);
                     }
                 }
             } else if (tt instanceof History) {
                 scInstance.reset((History) tt);
             }
         }
-        // CreateEmptyStatus
-        currentStatus = new Status();
-        Step step = new Step(null, currentStatus);
+        // Clear currentStatus
+        getCurrentStatus().getStates().clear();
+        Step step = new Step(null, getCurrentStatus());
         // execute global script if defined
-        semantics.executeGlobalScript(step, stateMachine, eventdispatcher, errorReporter, scInstance);
+        semantics.executeGlobalScript(exctx, step);
         // DetermineInitialStates
-        semantics.determineInitialStates(step, stateMachine, errorReporter, scInstance);
+        semantics.determineInitialStates(exctx, step);
         // enter initial states
-        semantics.enterStates(step, stateMachine, eventdispatcher, errorReporter, scInstance);
+        semantics.enterStates(exctx, step);
         // AssignCurrentStatus
         updateStatus(step);
         // Execute Immediate Transitions
-        if (superStep && currentStatus.getEvents().size() > 0) {
-            this.triggerEvents(new TriggerEvent[0]);
+
+        TriggerEvent event = exctx.nextInternalEvent();
+
+        if (event != null) {
+            handleEvent(event);
         } else {
             // InitiateInvokes only after state machine has stabilized
-            semantics.initiateInvokes(step, errorReporter, scInstance);
+            semantics.initiateInvokes(this, exctx, step);
             logState();
         }
     }
@@ -463,7 +513,10 @@ public class SCXMLExecutor implements Se
      */
     public void triggerEvent(final TriggerEvent evt)
             throws ModelException {
-        triggerEvents(new TriggerEvent[]{evt});
+        if (evt != null) {
+            externalEventQueue.add(evt);
+        }
+        triggerEvents();
     }
 
     /**
@@ -476,47 +529,88 @@ public class SCXMLExecutor implements Se
      * @throws ModelException in case there is a fatal SCXML object
      *            model problem.
      */
-    public synchronized void triggerEvents(final TriggerEvent[] evts)
+    public void triggerEvents(final TriggerEvent[] evts)
             throws ModelException {
-        // Set event data, saving old values
-        Object[] oldData = setEventData(evts);
+        if (evts != null) {
+            for (TriggerEvent evt : evts) {
+                if (evt != null) {
+                    externalEventQueue.add(evt);
+                }
+            }
+        }
+        triggerEvents();
+    }
 
-        // Forward events (external only) to any existing invokes,
-        // and finalize processing
-        semantics.processInvokes(evts, errorReporter, scInstance);
+    /**
+     * 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.
+     * </p>
+     * @param evt an external event
+     */
+    public void addEvent(final TriggerEvent evt) {
+        if (evt != null) {
+            externalEventQueue.add(evt);
+        }
+    }
+
+    /**
+     * @return Returns true if there are pending external events to be processed.
+     */
+    public boolean hasPendingEvents() {
+        return !externalEventQueue.isEmpty();
+    }
+
+    /**
+     * Trigger all pending and incoming events, until there are no more pending events
+     * @throws ModelException in case there is a fatal SCXML object model problem.
+     */
+    public void triggerEvents() throws ModelException {
+        TriggerEvent evt;
+        while ((evt = externalEventQueue.poll()) != null) {
+            // Forward events (external only) to any existing invokes,
+            // and finalize processing
+            semantics.processInvokes(exctx, evt);
+            handleEvent(evt);
+        }
+    }
+
+    /**
+     * The internal worker method for handling the next external event
+     * @param evt an external event
+     * @throws ModelException in case there is a fatal SCXML object model problem.
+     */
+    protected void handleEvent(final TriggerEvent evt)
+            throws ModelException {
+        TriggerEvent event = evt;
 
-        List<TriggerEvent> evs = new ArrayList<TriggerEvent>(Arrays.asList(evts));
         Step step;
 
         do {
+            setEventData(event);
+
             // CreateStep
-            step = new Step(evs, currentStatus);
+            step = new Step(event, getCurrentStatus());
             // EnumerateReachableTransitions
-            semantics.enumerateReachableTransitions(stateMachine, step,
-                errorReporter);
+            semantics.enumerateReachableTransitions(exctx, step);
             // FilterTransitionSet
-            semantics.filterTransitionsSet(step, eventdispatcher,
-                errorReporter, scInstance);
+            semantics.filterTransitionsSet(exctx, step);
             // FollowTransitions
-            semantics.followTransitions(step, errorReporter, scInstance);
+            semantics.followTransitions(exctx, step);
             // UpdateHistoryStates
-            semantics.updateHistoryStates(step, errorReporter, scInstance);
+            semantics.updateHistoryStates(exctx, step);
             // ExecuteActions
-            semantics.executeActions(step, stateMachine, eventdispatcher,
-                errorReporter, scInstance);
+            semantics.executeActions(exctx, step);
             // AssignCurrentStatus
             updateStatus(step);
-            // ***Cleanup external events if superStep
-            if (superStep) {
-                evs.clear();
-            }
-        } while (superStep && currentStatus.getEvents().size() > 0);
+
+            event = exctx.nextInternalEvent();
+
+        } while (event != null);
 
         // InitiateInvokes only after state machine has stabilized
-        semantics.initiateInvokes(step, errorReporter, scInstance);
+        semantics.initiateInvokes(this, exctx, step);
 
-        // Restore event data
-        restoreEventData(oldData);
         logState();
     }
 
@@ -527,7 +621,7 @@ public class SCXMLExecutor implements Se
      * @param listener The SCXMLListener.
      */
     public void addListener(final Observable observable, final SCXMLListener listener) {
-        scInstance.getNotificationRegistry().addListener(observable, listener);
+        notificationRegistry.addListener(observable, listener);
     }
 
     /**
@@ -538,8 +632,7 @@ public class SCXMLExecutor implements Se
      */
     public void removeListener(final Observable observable,
             final SCXMLListener listener) {
-        scInstance.getNotificationRegistry().removeListener(observable,
-                listener);
+        notificationRegistry.removeListener(observable, listener);
     }
 
     /**
@@ -551,7 +644,7 @@ public class SCXMLExecutor implements Se
      */
     public void registerInvokerClass(final String type,
             final Class<? extends Invoker> invokerClass) {
-        scInstance.registerInvokerClass(type, invokerClass);
+        invokerClasses.put(type, invokerClass);
     }
 
     /**
@@ -562,7 +655,33 @@ public class SCXMLExecutor implements Se
      *             attribute of &lt;invoke&gt; tag).
      */
     public void unregisterInvokerClass(final String type) {
-        scInstance.unregisterInvokerClass(type);
+        invokerClasses.remove(type);
+    }
+
+    /**
+     * Create a new {@link Invoker}
+     *
+     * @param type The type of the target being invoked.
+     * @return An {@link Invoker} for the specified type, if an
+     *         invoker class is registered against that type,
+     *         <code>null</code> otherwise.
+     * @throws org.apache.commons.scxml2.invoke.InvokerException When a suitable {@link Invoker} cannot
+     *                          be instantiated.
+     */
+    Invoker newInvoker(final String type)
+            throws InvokerException {
+        Class<? extends Invoker> invokerClass = invokerClasses.get(type);
+        if (invokerClass == null) {
+            throw new InvokerException("No Invoker registered for type \""
+                    + type + "\"");
+        }
+        try {
+            return invokerClass.newInstance();
+        } catch (InstantiationException ie) {
+            throw new InvokerException(ie.getMessage(), ie.getCause());
+        } catch (IllegalAccessException iae) {
+            throw new InvokerException(iae.getMessage(), iae.getCause());
+        }
     }
 }
 

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=1583086&r1=1583085&r2=1583086&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 Sun Mar 30 00:18:40 2014
@@ -38,160 +38,95 @@ public interface SCXMLSemantics {
      * Optional post processing immediately following SCXMLReader. May be used
      * for removing pseudo-states etc.
      *
-     * @param input
-     *            SCXML state machine
+     * @param input  SCXML state machine
+     * @param errRep ErrorReporter callback
      * @return normalized SCXML state machine, pseudo states are removed, etc.
-     * @param errRep
-     *            ErrorReporter callback
      */
     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 executeGlobalScript(final SCXMLExecutionContext context, final Step step) throws ModelException;
 
-    public void exitStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
-                           final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+    public void exitStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
-    public void executeTransitionContent(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
-                                         final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+    public void executeTransitionContent(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
-    public void enterStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher,
-                            final ErrorReporter errRep, final SCInstance scInstance) throws ModelException;
+    public void enterStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
     /**
      * Determining the initial state(s) for this state machine.
      *
-     * @param step
-     *            provides target states and entry list to fill in [out]
-     * @param stateMachine
-     *            SCXML state machine
-     * @param errRep
-     *            ErrorReporter callback
-     * @param scInstance
-     *            The state chart instance
-     *
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
-     */
-    void determineInitialStates(final Step step, final SCXML stateMachine, final ErrorReporter errRep,
-            final SCInstance scInstance)
-    throws ModelException;
+     * @param ctx  provides the execution context
+     * @param step provides target states and entry list to fill in [out]
+     *
+     * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
+     */
+    void determineInitialStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
     /**
      * 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.
-     */
-    void executeActions(final Step step, final SCXML stateMachine,
-            final EventDispatcher evtDispatcher, final ErrorReporter errRep,
-            final SCInstance scInstance)
-    throws ModelException;
+     * @param ctx  provides the execution context
+     * @param step provides EntryList, TransitList, ExitList gets updated its AfterStatus/Events
+     *
+     * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
+     */
+    void executeActions(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
     /**
      * Enumerate all the reachable transitions.
      *
-     * @param stateMachine
-     *            a state machine to traverse
-     * @param step
-     *            with current status and list of transitions to populate
-     * @param errRep
-     *            ErrorReporter callback
+     * @param ctx  provides the execution context
+     * @param step with current status and list of transitions to populate
      */
-    void enumerateReachableTransitions(final SCXML stateMachine,
-            final Step step, final ErrorReporter errRep);
+    void enumerateReachableTransitions(final SCXMLExecutionContext ctx, final Step step);
 
     /**
      * Filter the transitions set, eliminate those whose guard conditions
      * are not satisfied.
      *
-     * @param step
-     *            with current status
-     * @param evtDispatcher
-     *            the event dispatcher - EventDispatcher instance
-     * @param errRep
-     *            ErrorReporter callback
-     * @param scInstance
-     *            The state chart instance
-     *
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
-     */
-    void filterTransitionsSet(final Step step,
-            final EventDispatcher evtDispatcher, final ErrorReporter errRep,
-            final SCInstance scInstance)
-    throws ModelException;
+     * @param ctx  provides the execution context
+     * @param step with current status
+     *
+     * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
+     */
+    void filterTransitionsSet(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
     /**
      * Follow the candidate transitions for this execution Step, and update the
      * lists of entered and exited states accordingly.
      *
+     * @param ctx  provides the execution context
      * @param step The current Step
-     * @param errorReporter The ErrorReporter for the current environment
-     * @param scInstance The state chart instance
      *
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
+     * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
      */
-    void followTransitions(final Step step, final ErrorReporter errorReporter,
-            final SCInstance scInstance)
-    throws ModelException;
+    void followTransitions(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
 
     /**
      * Go over the exit list and update history information for
      * relevant states.
      *
-     * @param step
-     *            The current Step
-     * @param errRep
-     *            ErrorReporter callback
-     * @param scInstance
-     *            The state chart instance
+     * @param ctx  provides the execution context
+     * @param step The current Step
      */
-    void updateHistoryStates(final Step step, final ErrorReporter errRep,
-            final SCInstance scInstance);
+    void updateHistoryStates(final SCXMLExecutionContext ctx, final Step step);
 
     /**
      * Forward events to invoked activities, execute finalize handlers.
      *
-     * @param events
-     *            The events to be forwarded
-     * @param errRep
-     *            ErrorReporter callback
-     * @param scInstance
-     *            The state chart instance
-     *
-     * @throws ModelException
-     *             in case there is a fatal SCXML object model problem.
-     */
-    void processInvokes(final TriggerEvent[] events,
-            final ErrorReporter errRep, final SCInstance scInstance)
-    throws ModelException;
+     * @param ctx    provides the execution context
+     * @param event The event to be forwarded
+     *
+     * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
+     */
+    void processInvokes(final SCXMLExecutionContext ctx, final TriggerEvent event) throws ModelException;
 
     /**
      * Initiate any new invoked activities.
      *
-     * @param step
-     *            The current Step
-     * @param errRep
-     *            ErrorReporter callback
-     * @param scInstance
-     *            The state chart instance
-     *
+     * @param ctx  provides the execution context
+     * @param step The current Step
      */
-    void initiateInvokes(final Step step, final ErrorReporter errRep,
-            final SCInstance scInstance);
+    void initiateInvokes(final SCXMLExecutor executor, final SCXMLExecutionContext ctx, final Step step);
 }
 

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java Sun Mar 30 00:18:40 2014
@@ -17,8 +17,6 @@
 package org.apache.commons.scxml2;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -42,11 +40,6 @@ public class Status implements Serializa
     private Set<EnterableState> states;
 
     /**
-     * The events that are currently queued.
-     */
-    private Collection<TriggerEvent> events;
-
-    /**
      * Have we reached a final configuration for this state machine.
      *
      * True - if all the states are final and there are not events
@@ -55,22 +48,20 @@ public class Status implements Serializa
      * @return Whether a final configuration has been reached.
      */
     public boolean isFinal() {
-        boolean rslt = true;
-        for (EnterableState es : states) {
-            if (!(es instanceof Final)) {
-                rslt = false;
-                break;
-            }
-            //the status is final only if these are top-level states
-            if (es.getParent() != null) {
-                rslt = false;
-                break;
+        return getFinalState() != null;
+    }
+
+    /**
+     * @return Returns the single top level active final state or null otherwise
+     */
+    public Final getFinalState() {
+        if (states.size() == 1) {
+            EnterableState es = states.iterator().next();
+            if (es instanceof Final && es.getParent() == null) {
+                return (Final)es;
             }
         }
-        if (!events.isEmpty()) {
-            rslt = false;
-        }
-        return rslt;
+        return null;
     }
 
     /**
@@ -78,7 +69,6 @@ public class Status implements Serializa
      */
     public Status() {
         states = new HashSet<EnterableState>();
-        events = new ArrayList<TriggerEvent>();
     }
 
     /**
@@ -91,15 +81,6 @@ public class Status implements Serializa
     }
 
     /**
-     * Get the events that are currently queued.
-     *
-     * @return The events that are currently queued.
-     */
-    public Collection<TriggerEvent> getEvents() {
-        return events;
-    }
-
-    /**
      * Get the complete states configuration.
      *
      * @return complete states configuration including simple states and their

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Step.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Step.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Step.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Step.java Sun Mar 30 00:18:40 2014
@@ -17,13 +17,15 @@
 package org.apache.commons.scxml2;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.scxml2.model.EnterableState;
 import org.apache.commons.scxml2.model.SimpleTransition;
+import org.apache.commons.scxml2.model.TransitionalState;
 
 /**
  * A logical unit of progression in the execution of a SCXML model.
@@ -32,9 +34,9 @@ import org.apache.commons.scxml2.model.S
 public class Step {
 
     /**
-     * The external events in this step.
+     * The event in this step.
      */
-    private Collection<TriggerEvent> externalEvents;
+    private TriggerEvent event;
 
     /**
      * The status before this step.
@@ -57,9 +59,9 @@ public class Step {
     private List<EnterableState> entryList;
 
     /**
-     * The list of TransitionTargets that were entered during this step by default
+     * The set of TransitionTargets that were entered during this step by default
      */
-    private List<EnterableState> defaultEntryList;
+    private Set<EnterableState> defaultEntrySet;
 
     private Map<String, SimpleTransition> defaultHistoryTransitionEntryMap;
     /**
@@ -68,23 +70,16 @@ public class Step {
     private List<SimpleTransition> transitList;
 
     /**
-     * Constructor.
-      */
-    public Step() {
-        this(null, null);
-    }
+     * The set of activated states which invokes need to be invoked after the current macro step.
+     */
+    private Set<TransitionalState> statesToInvoke;
 
     /**
-     * @param externalEvents The external events received in this
-     *     unit of progression
+     * @param event The event received in this unit of progression
      * @param beforeStatus The before status
      */
-    public Step(final Collection<TriggerEvent> externalEvents, final Status beforeStatus) {
-        if (externalEvents != null) {
-            this.externalEvents = externalEvents;
-        } else {
-            this.externalEvents = new ArrayList<TriggerEvent>();
-        }
+    public Step(TriggerEvent event, final Status beforeStatus) {
+        this.event = event;
         if (beforeStatus != null) {
             this.beforeStatus = beforeStatus;
         } else {
@@ -93,9 +88,10 @@ public class Step {
         this.afterStatus = new Status();
         this.exitList = new ArrayList<EnterableState>();
         this.entryList = new ArrayList<EnterableState>();
-        this.defaultEntryList = new ArrayList<EnterableState>();
+        this.defaultEntrySet = new HashSet<EnterableState>();
         this.defaultHistoryTransitionEntryMap = new HashMap<String, SimpleTransition>();
         this.transitList = new ArrayList<SimpleTransition>();
+        this.statesToInvoke = new HashSet<TransitionalState>();
     }
 
     /**
@@ -106,13 +102,6 @@ public class Step {
     }
 
     /**
-     * @param afterStatus The afterStatus to set.
-     */
-    public void setAfterStatus(final Status afterStatus) {
-        this.afterStatus = afterStatus;
-    }
-
-    /**
      * @return Returns the beforeStatus.
      */
     public Status getBeforeStatus() {
@@ -120,13 +109,6 @@ public class Step {
     }
 
     /**
-     * @param beforeStatus The beforeStatus to set.
-     */
-    public void setBeforeStatus(final Status beforeStatus) {
-        this.beforeStatus = beforeStatus;
-    }
-
-    /**
      * @return Returns the entryList.
      */
     public List<EnterableState> getEntryList() {
@@ -134,10 +116,10 @@ public class Step {
     }
 
     /**
-     * @return Returns the defaultEntryList.
+     * @return Returns the defaultEntrySet.
      */
-    public List<EnterableState> getDefaultEntryList() {
-        return defaultEntryList;
+    public Set<EnterableState> getDefaultEntrySet() {
+        return defaultEntrySet;
     }
 
     /**
@@ -155,10 +137,10 @@ public class Step {
     }
 
     /**
-     * @return Returns the externalEvents.
+     * @return Returns the current event.
      */
-    public Collection<TriggerEvent> getExternalEvents() {
-        return externalEvents;
+    public TriggerEvent getEvent() {
+        return event;
     }
 
     /**
@@ -168,5 +150,11 @@ public class Step {
         return transitList;
     }
 
+    /**
+     * @return Returns the set of activated states which invokes need to be invoked after the current macro step.
+     */
+    public Set<TransitionalState> getStatesToInvoke() {
+        return statesToInvoke;
+    }
 }
 

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java Sun Mar 30 00:18:40 2014
@@ -16,24 +16,19 @@
  */
 package org.apache.commons.scxml2.invoke;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.commons.scxml2.SCXMLExecutor;
 import org.apache.commons.scxml2.TriggerEvent;
-import org.apache.commons.scxml2.model.ModelException;
 
 /**
- * Trigger the given {@link TriggerEvent} (or array of) on the given
+ * Trigger the given {@link TriggerEvent} on the given
  * state machine executor asynchronously, once.
  */
 class AsyncTrigger implements Runnable {
 
     /** The state machine executor. */
     private final SCXMLExecutor executor;
-    /** The event(s) to be triggered. */
-    private final TriggerEvent[] events;
-    /** The log. */
-    private final Log log = LogFactory.getLog(AsyncTrigger.class);
+    /** The event to be triggered. */
+    private final TriggerEvent event;
 
     /**
      * Constructor.
@@ -43,12 +38,11 @@ class AsyncTrigger implements Runnable {
      */
     AsyncTrigger(final SCXMLExecutor executor, final TriggerEvent event) {
         this.executor = executor;
-        this.events = new TriggerEvent[1];
-        this.events[0] = event;
+        this.event = event;
     }
 
     /**
-     * Fire the trigger(s) asynchronously.
+     * Fire the trigger asynchronously.
      */
     public void start() {
         new Thread(this).start();
@@ -58,13 +52,7 @@ class AsyncTrigger implements Runnable {
      * Fire the event(s).
      */
     public void run() {
-        try {
-            synchronized (executor) {
-                executor.triggerEvents(events);
-            }
-        } catch (ModelException me) {
-            log.error(me.getMessage(), me);
-        }
+        executor.addEvent(event);
     }
 
 }

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java Sun Mar 30 00:18:40 2014
@@ -18,7 +18,7 @@ package org.apache.commons.scxml2.invoke
 
 import java.util.Map;
 
-import org.apache.commons.scxml2.SCInstance;
+import org.apache.commons.scxml2.SCXMLExecutor;
 import org.apache.commons.scxml2.TriggerEvent;
 
 /**
@@ -51,7 +51,7 @@ import org.apache.commons.scxml2.Trigger
  *   <li>Instantiation via {@link Class#newInstance()}
  *       (Invoker implementation requires accessible constructor).</li>
  *   <li>Configuration (setters for parent state ID and
- *       {@link SCInstance}).</li>
+ *       {@link SCXMLExecutor}).</li>
  *   <li>Initiation of invoked activity via invoke() method, passing
  *       the source URI and the map of params.</li>
  *   <li>Zero or more bi-directional event triggering.</li>
@@ -78,12 +78,12 @@ public interface Invoker {
     void setParentStateId(String parentStateId);
 
     /**
-     * Set the "context" of the parent state machine, which provides the
+     * Set the execution "context" of the parent state machine, which provides the
      * channel.
      *
-     * @param scInstance The "context" of the parent state machine.
+     * @param parentExecutor The execution "context" of the parent state machine.
      */
-    void setSCInstance(SCInstance scInstance);
+    void setParentExecutor(SCXMLExecutor parentExecutor);
 
     /**
      * Begin this invocation.

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java Sun Mar 30 00:18:40 2014
@@ -25,7 +25,6 @@ import javax.xml.stream.XMLStreamExcepti
 
 import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
-import org.apache.commons.scxml2.SCInstance;
 import org.apache.commons.scxml2.SCXMLExecutor;
 import org.apache.commons.scxml2.TriggerEvent;
 import org.apache.commons.scxml2.env.SimpleDispatcher;
@@ -48,8 +47,8 @@ public class SimpleSCXMLInvoker implemen
     /** Event prefix, all events sent to the parent executor must begin
      *  with this prefix. */
     private String eventPrefix;
-    /** Invoking document's SCInstance. */
-    private SCInstance parentSCInstance;
+    /** Invoking document's SCXMLExecutor */
+    private SCXMLExecutor parentExecutor;
     /** The invoked state machine executor. */
     private SCXMLExecutor executor;
     /** Cancellation status. */
@@ -75,8 +74,8 @@ public class SimpleSCXMLInvoker implemen
     /**
      * {@inheritDoc}.
      */
-    public void setSCInstance(final SCInstance scInstance) {
-        this.parentSCInstance = scInstance;
+    public void setParentExecutor(final SCXMLExecutor parentExecutor) {
+        this.parentExecutor = parentExecutor;
     }
 
     /**
@@ -94,7 +93,7 @@ public class SimpleSCXMLInvoker implemen
         } catch (XMLStreamException xse) {
             throw new InvokerException(xse.getMessage(), xse.getCause());
         }
-        Evaluator eval = parentSCInstance.getEvaluator();
+        Evaluator eval = parentExecutor.getEvaluator();
         executor = new SCXMLExecutor(eval,
             new SimpleDispatcher(), new SimpleErrorReporter());
         Context rootCtx = eval.newContext(null);
@@ -113,7 +112,7 @@ public class SimpleSCXMLInvoker implemen
         if (executor.getCurrentStatus().isFinal()) {
             TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
                 TriggerEvent.SIGNAL_EVENT);
-            new AsyncTrigger(parentSCInstance.getExecutor(), te).start();
+            new AsyncTrigger(parentExecutor, te).start();
         }
     }
 
@@ -134,7 +133,7 @@ public class SimpleSCXMLInvoker implemen
         if (!doneBefore && executor.getCurrentStatus().isFinal()) {
             TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
                 TriggerEvent.SIGNAL_EVENT);
-            new AsyncTrigger(parentSCInstance.getExecutor(), te).start();
+            new AsyncTrigger(parentExecutor, te).start();
         }
     }
 
@@ -146,7 +145,7 @@ public class SimpleSCXMLInvoker implemen
         cancelled = true;
         TriggerEvent te = new TriggerEvent(eventPrefix
             + invokeCancelResponse, TriggerEvent.SIGNAL_EVENT);
-        new AsyncTrigger(parentSCInstance.getExecutor(), te).start();
+        new AsyncTrigger(parentExecutor, te).start();
     }
 
 }

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java Sun Mar 30 00:18:40 2014
@@ -17,15 +17,10 @@
 package org.apache.commons.scxml2.model;
 
 import java.io.Serializable;
-import java.util.Collection;
 import java.util.Map;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.scxml2.ErrorReporter;
-import org.apache.commons.scxml2.EventDispatcher;
-import org.apache.commons.scxml2.SCInstance;
+import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.TriggerEvent;
 
 /**
  * An abstract base class for executable elements in SCXML,
@@ -126,24 +121,14 @@ public abstract class Action implements 
     /**
      * Execute this action instance.
      *
-     * @param evtDispatcher The EventDispatcher for this execution instance
-     * @param errRep        The ErrorReporter to broadcast any errors
-     *                      during execution.
-     * @param scInstance    The state machine execution instance information.
-     * @param appLog        The application Log.
-     * @param derivedEvents The collection to which any internal events
-     *                      arising from the execution of this action
-     *                      must be added.
+     * @param exctx The ActionExecutionContext for this execution instance
      *
      * @throws ModelException If the execution causes the model to enter
      *                        a non-deterministic state.
      * @throws SCXMLExpressionException If the execution involves trying
      *                        to evaluate an expression which is malformed.
      */
-    public abstract void execute(final EventDispatcher evtDispatcher,
-        final ErrorReporter errRep, final SCInstance scInstance,
-        final Log appLog, final Collection<TriggerEvent> derivedEvents)
-    throws ModelException, SCXMLExpressionException;
+    public abstract void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException;
 
     /**
      * Return the key under which the current document namespaces are saved

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java Sun Mar 30 00:18:40 2014
@@ -17,20 +17,16 @@
 package org.apache.commons.scxml2.model;
 
 import java.io.IOException;
-import java.util.Collection;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.Context;
-import org.apache.commons.scxml2.ErrorReporter;
 import org.apache.commons.scxml2.Evaluator;
-import org.apache.commons.scxml2.EventDispatcher;
 import org.apache.commons.scxml2.PathResolver;
-import org.apache.commons.scxml2.SCInstance;
 import org.apache.commons.scxml2.SCXMLExpressionException;
 import org.apache.commons.scxml2.SCXMLHelper;
 import org.apache.commons.scxml2.TriggerEvent;
@@ -179,13 +175,10 @@ public class Assign extends Action imple
      * {@inheritDoc}
      */
     @Override
-    public void execute(final EventDispatcher evtDispatcher,
-            final ErrorReporter errRep, final SCInstance scInstance,
-            final Log appLog, final Collection<TriggerEvent> derivedEvents)
-    throws ModelException, SCXMLExpressionException {
+    public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException {
         EnterableState parentState = getParentEnterableState();
-        Context ctx = scInstance.getContext(parentState);
-        Evaluator eval = scInstance.getEvaluator();
+        Context ctx = exctx.getScInstance().getContext(parentState);
+        Evaluator eval = exctx.getEvaluator();
         ctx.setLocal(getNamespacesKey(), getNamespaces());
         // "location" gets preference over "name"
         if (!SCXMLHelper.isStringEmpty(location)) {
@@ -222,21 +215,23 @@ public class Assign extends Action imple
                     Object valueObject = eval.eval(ctx, expr);
                     SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
                 }
-                if (appLog.isDebugEnabled()) {
-                    appLog.debug("<assign>: data node '" + oldNode.getNodeName()
+                if (exctx.getAppLog().isDebugEnabled()) {
+                    exctx.getAppLog().debug("<assign>: data node '" + oldNode.getNodeName()
                         + "' updated");
                 }
+                /* TODO: send to notificationRegistry instead?
                 TriggerEvent ev = new TriggerEvent(name + ".change",
                     TriggerEvent.CHANGE_EVENT);
-                derivedEvents.add(ev);
+                exctx.addInternalEvent(ev);
+                */
             } else {
-                appLog.error("<assign>: location does not point to"
+                exctx.getAppLog().error("<assign>: location does not point to"
                     + " a <data> node");
             }
         } else {
             // lets try "name" (usage as in Sep '05 WD, useful with <var>)
             if (!ctx.has(name)) {
-                errRep.onError(ErrorConstants.UNDEFINED_VARIABLE, name
+                exctx.getErrorReporter().onError(ErrorConstants.UNDEFINED_VARIABLE, name
                     + " = null", parentState);
             } else {
                 Object varObj;
@@ -246,13 +241,12 @@ public class Assign extends Action imple
                     varObj = eval.eval(ctx, expr);
                 }
                 ctx.set(name, varObj);
-                if (appLog.isDebugEnabled()) {
-                    appLog.debug("<assign>: Set variable '" + name + "' to '"
+                if (exctx.getAppLog().isDebugEnabled()) {
+                    exctx.getAppLog().debug("<assign>: Set variable '" + name + "' to '"
                         + String.valueOf(varObj) + "'");
                 }
-                TriggerEvent ev = new TriggerEvent(name + ".change",
-                    TriggerEvent.CHANGE_EVENT);
-                derivedEvents.add(ev);
+                TriggerEvent ev = new TriggerEvent(name + ".change", TriggerEvent.CHANGE_EVENT);
+                exctx.addInternalEvent(ev);
             }
         }
         ctx.setLocal(getNamespacesKey(), null);

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Cancel.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Cancel.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Cancel.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Cancel.java Sun Mar 30 00:18:40 2014
@@ -16,14 +16,8 @@
  */
 package org.apache.commons.scxml2.model;
 
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.scxml2.ErrorReporter;
-import org.apache.commons.scxml2.EventDispatcher;
-import org.apache.commons.scxml2.SCInstance;
+import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.TriggerEvent;
 
 /**
  * The class in this SCXML object model that corresponds to the
@@ -71,11 +65,8 @@ public class Cancel extends Action {
      * {@inheritDoc}
      */
     @Override
-    public void execute(final EventDispatcher evtDispatcher,
-            final ErrorReporter errRep, final SCInstance scInstance,
-            final Log appLog, final Collection<TriggerEvent> derivedEvents)
-    throws ModelException, SCXMLExpressionException {
-        evtDispatcher.cancel(sendid);
+    public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException {
+        exctx.getEventDispatcher().cancel(sendid);
     }
 }
 

Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/ElseIf.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/ElseIf.java?rev=1583086&r1=1583085&r2=1583086&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/ElseIf.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/ElseIf.java Sun Mar 30 00:18:40 2014
@@ -16,14 +16,8 @@
  */
 package org.apache.commons.scxml2.model;
 
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.scxml2.ErrorReporter;
-import org.apache.commons.scxml2.EventDispatcher;
-import org.apache.commons.scxml2.SCInstance;
+import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.TriggerEvent;
 
 /**
  * The class in this SCXML object model that corresponds to the
@@ -71,10 +65,7 @@ public class ElseIf extends Action {
      * {@inheritDoc}
      */
     @Override
-    public void execute(final EventDispatcher evtDispatcher,
-            final ErrorReporter errRep, final SCInstance scInstance,
-            final Log appLog, final Collection<TriggerEvent> derivedEvents)
-    throws ModelException, SCXMLExpressionException {
+    public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException {
         // nothing to do, the <if> container will take care of this
     }
 



Mime
View raw message