Author: ate
Date: Wed Mar 26 23:21:17 2014
New Revision: 1582115

URL: http://svn.apache.org/r1582115
Log:
SCXML-200: adding support for multiple <invoke> elements in a <state> or 
<parallel> instead of just one.
Note: this is primarily a model update only. Semantically and process-wise the 
<invoke> handling is not (by far) in line with the specification yet.

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/io/ModelUpdater.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Invoke.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionTarget.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
    
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCInstance.java?rev=1582115&r1=1582114&r2=1582115&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
 Wed Mar 26 23:21:17 2014
@@ -22,12 +22,14 @@ 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.TransitionalState;
 
@@ -72,11 +74,12 @@ public class SCInstance implements Seria
      */
     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
-     * (leaf) <code>State</code>s.
+     * their <code>invokeId</code>.
      */
-    private final Map<TransitionalState, Invoker> invokers;
+    private final Map<String, Invoker> invokers;
 
     /**
      * The evaluator for expressions.
@@ -108,7 +111,8 @@ public class SCInstance implements Seria
         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.invokers = Collections.synchronizedMap(new 
HashMap<TransitionalState, 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;
@@ -348,36 +352,44 @@ public class SCInstance implements Seria
     }
 
     /**
-    * Get the {@link Invoker} for this {@link TransitionalState}.
+    * 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 TransitionalState} is
-     * currently active and contains an &lt;invoke&gt; child.
+     * returned if and only if the {@link Invoke} parent TransitionalState is
+     * currently active and contains the &lt;invoke&gt; child.
      *
-     * @param state The <code>TransitionalState</code>.
+     * @param invoke The <code>Invoke</code>.
      * @return The Invoker.
      */
-    public Invoker getInvoker(final TransitionalState state) {
-        return invokers.get(state);
+    public Invoker getInvoker(final Invoke invoke) {
+        return invokers.get(invokeIds.get(invoke));
     }
 
     /**
-     * Set the {@link Invoker} for this {@link TransitionalState}.
+     * Set the {@link Invoker} for a {@link Invoke} and returns the unique 
invokerId for the Invoker
      *
-     * @param state The TransitionalState.
+     * @param invoke The Invoke.
      * @param invoker The Invoker.
+     * @return The invokeId
      */
-    public void setInvoker(final TransitionalState state,
-            final Invoker invoker) {
-        invokers.put(state, invoker);
+    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 the Map of {@link Invoker}s currently "active".
-     *
-     * @return The map of invokers.
+     * @return Returns the map of current active Invokes and their invokeId
      */
-    public Map<TransitionalState, Invoker> getInvokers() {
-        return invokers;
+    public Map<Invoke, String> getInvokeIds() {
+        return invokeIds;
     }
 
     /**

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java
 Wed Mar 26 23:21:17 2014
@@ -250,9 +250,7 @@ final class ModelUpdater {
             updateTransition(transition, targets);
         }
 
-        // TODO: state must may have multiple invokes
-        Invoke inv = state.getInvoke();
-        if (inv != null) {
+        for (Invoke inv : state.getInvokes()) {
             String type = inv.getType();
             if (SCXMLHelper.isStringEmpty(type)) {
                 logAndThrowModelError(ERR_INVOKE_NO_TYPE,

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
 Wed Mar 26 23:21:17 2014
@@ -984,7 +984,9 @@ public final class SCXMLReader {
                     configuration.parent.addTarget(child);
                     readInExternalTargets(configuration.parent, child);
                 }
-                s.setInvoke(include.getInvoke());
+                for (Invoke invoke : include.getInvokes()) {
+                    s.addInvoke(invoke);
+                }
                 if (include.getInitial() != null) {
                     s.setInitial(include.getInitial());
                 }
@@ -1111,6 +1113,7 @@ public final class SCXMLReader {
             throws XMLStreamException, ModelException {
 
         Invoke invoke = new Invoke();
+        invoke.setId(readAV(reader, ATTR_ID));
         invoke.setSrc(readAV(reader, ATTR_SRC));
         invoke.setSrcexpr(readAV(reader, ATTR_SRCEXPR));
         invoke.setType(readAV(reader, ATTR_TYPE));
@@ -1150,7 +1153,7 @@ public final class SCXMLReader {
             }
         }
 
-        parent.setInvoke(invoke);
+        parent.addInvoke(invoke);
     }
 
     /**

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
 Wed Mar 26 23:21:17 2014
@@ -533,8 +533,7 @@ public class SCXMLWriter {
             writeTransition(writer, t);
         }
 
-        Invoke inv = state.getInvoke();
-        if (inv != null) {
+        for (Invoke inv : state.getInvokes()) {
             writeInvoke(writer, inv);
         }
 
@@ -574,8 +573,7 @@ public class SCXMLWriter {
             writeTransition(writer, t);
         }
 
-        Invoke inv = parallel.getInvoke();
-        if (inv != null) {
+        for (Invoke inv : parallel.getInvokes()) {
             writeInvoke(writer, inv);
         }
 
@@ -733,6 +731,7 @@ public class SCXMLWriter {
             throws XMLStreamException {
 
         writer.writeStartElement(ELEM_INVOKE);
+        writeAV(writer, ATTR_ID, invoke.getId());
         writeAV(writer, ATTR_SRC, invoke.getSrc());
         writeAV(writer, ATTR_SRCEXPR, invoke.getSrcexpr());
         writeAV(writer, ATTR_TYPE, invoke.getType());

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Invoke.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Invoke.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Invoke.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Invoke.java
 Wed Mar 26 23:21:17 2014
@@ -38,6 +38,11 @@ public class Invoke implements Namespace
     private static final long serialVersionUID = 1L;
 
     /**
+     * Identifier for this Invoke.
+     * */
+    private String id;
+
+    /**
      * The type of target to be invoked.
      */
     private String type;
@@ -82,6 +87,24 @@ public class Invoke implements Namespace
     }
 
     /**
+     * Get the identifier for this invoke (may be null).
+     *
+     * @return Returns the id.
+     */
+    public final String getId() {
+        return id;
+    }
+
+    /**
+     * Set the identifier for this invoke.
+     *
+     * @param id The id to set.
+     */
+    public final void setId(final String id) {
+        this.id = id;
+    }
+
+    /**
      * Get the type for this &lt;invoke&gt; element.
      *
      * @return String Returns the type.
@@ -209,5 +232,23 @@ public class Invoke implements Namespace
         this.namespaces = namespaces;
     }
 
+    /**
+     * Enforce identity equality only
+     * @param other other object to compare with
+     * @return this == other
+     */
+    @Override
+    public final boolean equals(final Object other) {
+        return this == other;
+    }
+
+    /**
+     * Enforce returning identity based hascode
+     * @return {@link System#identityHashCode(Object) 
System.identityHashCode(this)}
+     */
+    @Override
+    public final int hashCode() {
+        return System.identityHashCode(this);
+    }
 }
 

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionTarget.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionTarget.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionTarget.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionTarget.java
 Wed Mar 26 23:21:17 2014
@@ -26,6 +26,7 @@ import java.io.Serializable;
 public abstract class TransitionTarget implements Serializable, Observable {
 
     private static final EnterableState[] ZERO_ANCESTORS = new 
EnterableState[0];
+
     /**
      * Identifier for this transition target. Other parts of the SCXML
      * document may refer to this &lt;state&gt; using this ID.

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
 Wed Mar 26 23:21:17 2014
@@ -41,14 +41,13 @@ public abstract class TransitionalState 
     private List<History> history;
 
     /**
-     * The Invoke child, which defines an external process that should
+     * The Invoke children, each which defines an external process that should
      * be invoked, immediately after the onentry executable content,
      * and the transitions become candidates after the invoked
      * process has completed its execution.
-     * May occur 0 or 1 times. Incompatible with the state or parallel
-     * property.
+     * May occur 0 or more times.
      */
-    private Invoke invoke;
+    private List<Invoke> invokes;
 
     /**
      * The set of EnterableState children contained in this TransitionalState
@@ -60,6 +59,7 @@ public abstract class TransitionalState 
         transitions = new ArrayList<Transition>();
         history = new ArrayList<History>();
         children = new ArrayList<EnterableState>();
+        invokes = new ArrayList<Invoke>();
     }
 
     /**
@@ -201,12 +201,12 @@ public abstract class TransitionalState 
     }
 
     /**
-     * Get the Invoke child (may be null).
+     * Get the Invoke children (may be empty).
      *
      * @return Invoke Returns the invoke.
      */
-    public final Invoke getInvoke() {
-        return invoke;
+    public final List<Invoke> getInvokes() {
+        return invokes;
     }
 
     /**
@@ -215,14 +215,14 @@ public abstract class TransitionalState 
      * @param invoke
      *            The invoke to set.
      */
-    public final void setInvoke(final Invoke invoke) {
-        this.invoke = invoke;
+    public final void addInvoke(final Invoke invoke) {
+        this.invokes.add(invoke);
     }
 
     /**
      * Get the set of child transition targets (may be empty).
      *
-     * @return Set Returns the children.
+     * @return Returns the children.
      *
      * @since 0.7
      */

Modified: 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java?rev=1582115&r1=1582114&r2=1582115&view=diff
==============================================================================
--- 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
 (original)
+++ 
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
 Wed Mar 26 23:21:17 2014
@@ -218,23 +218,26 @@ public class SCXMLSemanticsImpl implemen
                            final ErrorReporter errRep, final SCInstance 
scInstance) throws ModelException {
         NotificationRegistry nr = scInstance.getNotificationRegistry();
         Collection<TriggerEvent> internalEvents = 
step.getAfterStatus().getEvents();
-        Map<TransitionalState, Invoker> invokers = scInstance.getInvokers();
         // ExecutePhaseActions / OnExit
         for (EnterableState es : step.getExitList()) {
             OnExit oe = es.getOnExit();
             executeContent(oe, evtDispatcher, errRep, scInstance, 
internalEvents);
-            // check if invoke is active in this state
-            if (invokers.containsKey(es)) {
-                Invoker toCancel = invokers.get(es);
-                try {
-                    toCancel.cancel();
-                } catch (InvokerException ie) {
-                    TriggerEvent te = new TriggerEvent(es.getId()
-                            + ".invoke.cancel.failed", 
TriggerEvent.ERROR_EVENT);
-                    internalEvents.add(te);
+            if (es instanceof TransitionalState) {
+                // check if invokers are active in this state
+                for (Invoke inv : ((TransitionalState)es).getInvokes()) {
+                    Invoker toCancel = scInstance.getInvoker(inv);
+                    if (toCancel != null) {
+                        try {
+                            toCancel.cancel();
+                        } catch (InvokerException ie) {
+                            TriggerEvent te = new TriggerEvent(es.getId()
+                                    + ".invoke.cancel.failed", 
TriggerEvent.ERROR_EVENT);
+                            internalEvents.add(te);
+                        }
+                        // done here, don't wait for cancel response
+                        scInstance.removeInvoker(inv);
+                    }
                 }
-                // done here, don't wait for cancel response
-                invokers.remove(es);
             }
             nr.fireOnExit(es, es);
             nr.fireOnExit(stateMachine, es);
@@ -437,10 +440,9 @@ public class SCXMLSemanticsImpl implemen
         allEvents.addAll(step.getBeforeStatus().getEvents());
         allEvents.addAll(step.getExternalEvents());
         // Finalize invokes, if applicable
-        for (TransitionTarget tt : scInstance.getInvokers().keySet()) {
-            State s = (State) tt;
-            if (finalizeMatch(s.getId(), allEvents)) {
-                Finalize fn = s.getInvoke().getFinalize();
+        for (Map.Entry<Invoke, String> entry : 
scInstance.getInvokeIds().entrySet()) {
+            if (finalizeMatch(entry.getValue(), allEvents)) {
+                Finalize fn = entry.getKey().getFinalize();
                 if (fn != null) {
                     executeContent(fn, evtDispatcher, errRep, scInstance, 
step.getAfterStatus().getEvents());
                 }
@@ -768,10 +770,9 @@ public class SCXMLSemanticsImpl implemen
     throws ModelException {
         Set<TriggerEvent> allEvents = new HashSet<TriggerEvent>();
         allEvents.addAll(Arrays.asList(events));
-        for (Map.Entry<TransitionalState, Invoker> iEntry : 
scInstance.getInvokers().entrySet()) {
-            String parentId = iEntry.getKey().getId();
-            if (!finalizeMatch(parentId, allEvents)) { // prevent cycles
-                Invoker inv = iEntry.getValue();
+        for (Map.Entry<Invoke, String> entry : 
scInstance.getInvokeIds().entrySet()) {
+            if (!finalizeMatch(entry.getValue(), allEvents)) { // prevent 
cycles
+                Invoker inv = scInstance.getInvoker(entry.getKey());
                 try {
                     inv.parentEvents(events);
                 } catch (InvokerException ie) {
@@ -800,82 +801,85 @@ public class SCXMLSemanticsImpl implemen
             if (es instanceof TransitionalState) {
                 TransitionalState ts = (TransitionalState) es;
                 Context ctx = scInstance.getContext(ts);
-                Invoke i = ts.getInvoke();
-                if (i != null && scInstance.getInvoker(ts) == null) {
-                    String src = i.getSrc();
-                    if (src == null) {
-                        String srcexpr = i.getSrcexpr();
-                        Object srcObj;
-                        try {
-                            ctx.setLocal(NAMESPACES_KEY, i.getNamespaces());
-                            srcObj = eval.eval(ctx, srcexpr);
-                            ctx.setLocal(NAMESPACES_KEY, null);
-                            src = String.valueOf(srcObj);
-                        } catch (SCXMLExpressionException see) {
-                            errRep.onError(ErrorConstants.EXPRESSION_ERROR,
-                                    see.getMessage(), i);
-                        }
-                    }
-                    String source = src;
-                    PathResolver pr = i.getPathResolver();
-                    if (pr != null) {
-                        source = i.getPathResolver().resolvePath(src);
-                    }
-                    String type = i.getType();
-                    Invoker inv;
-                    try {
-                        inv = scInstance.newInvoker(type);
-                    } catch (InvokerException ie) {
-                        TriggerEvent te = new TriggerEvent(ts.getId()
-                                + ".invoke.failed", TriggerEvent.ERROR_EVENT);
-                        internalEvents.add(te);
-                        continue;
-                    }
-                    inv.setParentStateId(ts.getId());
-                    inv.setSCInstance(scInstance);
-                    List<Param> params = i.params();
-                    Map<String, Object> args = new HashMap<String, Object>();
-                    for (Param p : params) {
-                        String argExpr = p.getExpr();
-                        Object argValue = null;
-                        ctx.setLocal(NAMESPACES_KEY, p.getNamespaces());
-                        // Do we have an "expr" attribute?
-                        if (argExpr != null && argExpr.trim().length() > 0) {
+                for (Invoke i : ts.getInvokes()) {
+                    if (i != null && scInstance.getInvoker(i) == null) {
+                        String src = i.getSrc();
+                        if (src == null) {
+                            String srcexpr = i.getSrcexpr();
+                            Object srcObj;
                             try {
-                                argValue = eval.eval(ctx, argExpr);
+                                ctx.setLocal(NAMESPACES_KEY, 
i.getNamespaces());
+                                srcObj = eval.eval(ctx, srcexpr);
+                                ctx.setLocal(NAMESPACES_KEY, null);
+                                src = String.valueOf(srcObj);
                             } catch (SCXMLExpressionException see) {
                                 errRep.onError(ErrorConstants.EXPRESSION_ERROR,
                                         see.getMessage(), i);
                             }
-                        } else {
-                            // No. Does value of "name" attribute refer to a 
valid
-                            // location in the data model?
-                            try {
-                                argValue = eval.evalLocation(ctx, p.getName());
-                                if (argValue == null) {
+                        }
+                        String source = src;
+                        PathResolver pr = i.getPathResolver();
+                        if (pr != null) {
+                            source = i.getPathResolver().resolvePath(src);
+                        }
+                        String type = i.getType();
+                        Invoker inv;
+                        try {
+                            inv = scInstance.newInvoker(type);
+                        } catch (InvokerException ie) {
+                            TriggerEvent te = new TriggerEvent(ts.getId()
+                                    + ".invoke.failed", 
TriggerEvent.ERROR_EVENT);
+                            internalEvents.add(te);
+                            continue;
+                        }
+                        List<Param> params = i.params();
+                        Map<String, Object> args = new HashMap<String, 
Object>();
+                        for (Param p : params) {
+                            String argExpr = p.getExpr();
+                            Object argValue = null;
+                            ctx.setLocal(NAMESPACES_KEY, p.getNamespaces());
+                            // Do we have an "expr" attribute?
+                            if (argExpr != null && argExpr.trim().length() > 
0) {
+                                try {
+                                    argValue = eval.eval(ctx, argExpr);
+                                } catch (SCXMLExpressionException see) {
+                                    
errRep.onError(ErrorConstants.EXPRESSION_ERROR,
+                                            see.getMessage(), i);
+                                }
+                            } else {
+                                // No. Does value of "name" attribute refer to 
a valid
+                                // location in the data model?
+                                try {
+                                    argValue = eval.evalLocation(ctx, 
p.getName());
+                                    if (argValue == null) {
                                     // Generate error, 4.3.1 in 
WD-scxml-20080516
-                                    TriggerEvent te = new 
TriggerEvent(ts.getId()
-                                            + ERR_ILLEGAL_ALLOC,
-                                            TriggerEvent.ERROR_EVENT);
-                                    internalEvents.add(te);
+                                        TriggerEvent te = new 
TriggerEvent(ts.getId()
+                                                + ERR_ILLEGAL_ALLOC,
+                                                TriggerEvent.ERROR_EVENT);
+                                        internalEvents.add(te);
+                                    }
+                                } catch (SCXMLExpressionException see) {
+                                    
errRep.onError(ErrorConstants.EXPRESSION_ERROR,
+                                            see.getMessage(), i);
                                 }
-                            } catch (SCXMLExpressionException see) {
-                                errRep.onError(ErrorConstants.EXPRESSION_ERROR,
-                                        see.getMessage(), i);
                             }
+                            ctx.setLocal(NAMESPACES_KEY, null);
+                            args.put(p.getName(), argValue);
+                        }
+                        String invokeId = scInstance.setInvoker(i, inv);
+                        // TODO: API should reflect this isn't the parent 
state ID anymore but the invokeId
+                        inv.setParentStateId(invokeId);
+                        inv.setSCInstance(scInstance);
+                        try {
+                            inv.invoke(source, args);
+                        } catch (InvokerException ie) {
+                            TriggerEvent te = new TriggerEvent(ts.getId()
+                                    + ".invoke.failed", 
TriggerEvent.ERROR_EVENT);
+                            internalEvents.add(te);
+                            scInstance.removeInvoker(i);
+                            continue;
                         }
-                        ctx.setLocal(NAMESPACES_KEY, null);
-                        args.put(p.getName(), argValue);
-                    }
-                    try {
-                        inv.invoke(source, args);
-                    } catch (InvokerException ie) {
-                        TriggerEvent te = new TriggerEvent(ts.getId()
-                                + ".invoke.failed", TriggerEvent.ERROR_EVENT);
-                        internalEvents.add(te);
-                        continue;
                     }
-                    scInstance.setInvoker(ts, inv);
                 }
             }
         }


Reply via email to