Repository: commons-scxml
Updated Branches:
  refs/heads/master b5dd05b28 -> 4e13be179


SCXML-264 Support <invoke> with inline (<content> body) SCXML statemachine 
definition


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

Branch: refs/heads/master
Commit: 4e13be179dccbf311fced2a2eeb71a04db170bb7
Parents: b5dd05b
Author: Ate Douma <a...@apache.org>
Authored: Sun Dec 10 16:24:17 2017 +0100
Committer: Ate Douma <a...@apache.org>
Committed: Sun Dec 10 16:24:17 2017 +0100

----------------------------------------------------------------------
 src/changes/changes.xml                         |  6 +-
 .../apache/commons/scxml2/invoke/Invoker.java   | 17 ++++-
 .../scxml2/invoke/SimpleSCXMLInvoker.java       | 29 +++++++-
 .../apache/commons/scxml2/io/ContentParser.java | 20 ++++++
 .../apache/commons/scxml2/io/SCXMLReader.java   | 35 +++++++--
 .../apache/commons/scxml2/io/SCXMLWriter.java   |  1 +
 .../org/apache/commons/scxml2/model/Assign.java | 29 +-------
 .../apache/commons/scxml2/model/Content.java    | 39 ++++++++--
 .../org/apache/commons/scxml2/model/Invoke.java | 75 ++++++++++----------
 .../scxml2/model/PathResolverHolder.java        | 43 -----------
 .../org/apache/commons/scxml2/model/SCXML.java  | 25 +++++++
 .../org/apache/commons/scxml2/model/Send.java   |  5 +-
 .../scxml2/invoke/InvokeParamNameTest.java      | 21 ++++--
 .../org/apache/commons/scxml2/w3c/tests.xml     | 56 +++++++--------
 14 files changed, 239 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f5c434c..363de8c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -35,7 +35,11 @@
     <release version="2.0" date="In Git master"
       description="Latest unreleased code">
 
-      <action dev="ate" type="update" issue="SCXML-263">
+      <action dev="ate" type="fix" issue="SCXML-264">
+        [12-10-2017] Support &lt;invoke&gt; with inline (<content> body) SCXML 
statemachine definition
+      </action>
+
+      <action dev="ate" type="fix" issue="SCXML-263">
         [12-10-2017] Javascript engine (Nashorn) cannot be shared between 
multiple SCXML instance executions
       </action>
 

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java 
b/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
index 09dcf84..663a985 100644
--- a/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
+++ b/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
@@ -96,17 +96,28 @@ public interface Invoker {
     SCXMLIOProcessor getChildIOProcessor();
 
     /**
-     * Begin this invocation.
+     * Invoke the SCXML document located at an external URL.
      *
-     * @param source The source URI of the activity being invoked.
+     * @param url The source URL of the SCXML document to invoke.
      * @param params The &lt;param&gt; values
      * @throws InvokerException In case there is a fatal problem with
      *                          invoking the source.
      */
-    void invoke(String source, Map<String, Object> params)
+    void invoke(String url, Map<String, Object> params)
     throws InvokerException;
 
     /**
+     * Invoke the SCXML document provided as inline XML content
+     *
+     * @param content The SCXML document as inline XML content
+     * @param params The &lt;param&gt; values
+     * @throws InvokerException In case there is a fatal problem with
+     *                          invoking the source.
+     */
+    void invokeContent(String content, Map<String, Object> params)
+            throws InvokerException;
+
+    /**
      * Forwards the event triggered on the parent state machine
      * on to the invoked activity.
      *

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java 
b/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
index ee7262f..9277e0a 100644
--- a/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
+++ b/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
@@ -18,12 +18,12 @@ package org.apache.commons.scxml2.invoke;
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.io.StringReader;
 import java.net.URL;
 import java.util.Map;
 
 import javax.xml.stream.XMLStreamException;
 
-import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.EventBuilder;
 import org.apache.commons.scxml2.SCXMLExecutor;
 import org.apache.commons.scxml2.SCXMLIOProcessor;
@@ -89,11 +89,11 @@ public class SimpleSCXMLInvoker implements Invoker, 
Serializable {
      * {@inheritDoc}.
      */
     @Override
-    public void invoke(final String source, final Map<String, Object> params)
+    public void invoke(final String url, final Map<String, Object> params)
     throws InvokerException {
         SCXML scxml;
         try {
-            scxml = SCXMLReader.read(new URL(source));
+            scxml = SCXMLReader.read(new URL(url));
         } catch (ModelException me) {
             throw new InvokerException(me.getMessage(), me.getCause());
         } catch (IOException ioe) {
@@ -101,6 +101,29 @@ public class SimpleSCXMLInvoker implements Invoker, 
Serializable {
         } catch (XMLStreamException xse) {
             throw new InvokerException(xse.getMessage(), xse.getCause());
         }
+        execute(scxml, params);
+    }
+
+    /**
+     * {@inheritDoc}.
+     */
+    @Override
+    public void invokeContent(final String content, final Map<String, Object> 
params)
+            throws InvokerException {
+        SCXML scxml;
+        try {
+            scxml = SCXMLReader.read(new StringReader(content));
+        } catch (ModelException me) {
+            throw new InvokerException(me.getMessage(), me.getCause());
+        } catch (IOException ioe) {
+            throw new InvokerException(ioe.getMessage(), ioe.getCause());
+        } catch (XMLStreamException xse) {
+            throw new InvokerException(xse.getMessage(), xse.getCause());
+        }
+        execute(scxml, params);
+    }
+
+    protected void execute(SCXML scxml, final Map<String, Object> params) 
throws InvokerException {
         try {
             executor = new SCXMLExecutor(parentSCXMLExecutor, invokeId, scxml);
         }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/io/ContentParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/io/ContentParser.java 
b/src/main/java/org/apache/commons/scxml2/io/ContentParser.java
index e3ae09d..1f4290e 100644
--- a/src/main/java/org/apache/commons/scxml2/io/ContentParser.java
+++ b/src/main/java/org/apache/commons/scxml2/io/ContentParser.java
@@ -18,10 +18,18 @@ package org.apache.commons.scxml2.io;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringWriter;
 import java.net.URL;
+import java.util.Properties;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -172,6 +180,18 @@ public class ContentParser {
         return doc != null ? doc.getDocumentElement() : null;
     }
 
+    public String transformXml(final Node node) throws TransformerException {
+        StringWriter writer = new StringWriter();
+        Transformer transformer = 
TransformerFactory.newInstance().newTransformer();
+        Properties outputProps = new Properties();
+        outputProps.put(OutputKeys.OMIT_XML_DECLARATION, "no");
+        outputProps.put(OutputKeys.STANDALONE, "no");
+        outputProps.put(OutputKeys.INDENT, "yes");
+        transformer.setOutputProperties(outputProps);
+        transformer.transform(new DOMSource(node), new StreamResult(writer));
+        return writer.toString();
+    }
+
     /**
      * Parse a string into a content object, following the SCXML rules as 
specified for the ECMAscript (section B.2.1) Data Model
      * <ul>

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java 
b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
index ab06d6f..9918196 100644
--- a/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
+++ b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
@@ -41,6 +41,7 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.util.XMLEventAllocator;
 import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
@@ -589,6 +590,7 @@ public final class SCXMLReader {
             throws IOException, ModelException, XMLStreamException {
 
         SCXML scxml = new SCXML();
+        scxml.setPathResolver(configuration.pathResolver);
         while (reader.hasNext()) {
             String name, nsURI;
             switch (reader.next()) {
@@ -1163,11 +1165,11 @@ public final class SCXMLReader {
 
         Invoke invoke = new Invoke();
         invoke.setId(readAV(reader, ATTR_ID));
+        invoke.setIdlocation(readAV(reader, ATTR_IDLOCATION));
         invoke.setSrc(readAV(reader, ATTR_SRC));
         invoke.setSrcexpr(readAV(reader, ATTR_SRCEXPR));
         invoke.setType(readAV(reader, ATTR_TYPE));
         invoke.setAutoForward(readBooleanAV(reader, ELEM_INVOKE, 
ATTR_AUTOFORWARD));
-        invoke.setPathResolver(configuration.pathResolver);
         readNamespaces(configuration, invoke);
 
         loop : while (reader.hasNext()) {
@@ -1281,12 +1283,35 @@ public final class SCXMLReader {
         else {
             Node body = readNode(reader, configuration, XMLNS_SCXML, 
ELEM_CONTENT, new String[]{});
             if (body.hasChildNodes()) {
+                content.setBody(body);
                 NodeList children = body.getChildNodes();
                 if (children.getLength() == 1 && 
children.item(0).getNodeType() == Node.TEXT_NODE) {
-                    content.setBody(children.item(0).getNodeValue());
+                    try {
+                        
content.setValue(ContentParser.DEFAULT_PARSER.parseContent(children.item(0).getNodeValue()));
+                    }
+                    catch (IOException ioe) {
+                        throw new XMLStreamException(ioe);
+                    }
                 }
                 else {
-                    content.setBody(body);
+                    // find only use first child element
+                    for (int i = 0, size = children.getLength(); i < size; 
i++) {
+                        Node child = children.item(i);
+                        if (child.getNodeType() == Node.ELEMENT_NODE) {
+                            if (contentContainer instanceof Invoke) {
+                                // transform invoke <content/> to string 
upfront as we currently only can handle string input
+                                try {
+                                    
content.setValue(ContentParser.DEFAULT_PARSER.transformXml(child));
+                                } catch (TransformerException e) {
+                                    throw new XMLStreamException(e);
+                                }
+                            }
+                            else {
+                                content.setValue(child);
+                            }
+                            break;
+                        }
+                    }
                 }
             }
         }
@@ -1767,7 +1792,6 @@ public final class SCXMLReader {
         assign.setExpr(readAV(reader, ATTR_EXPR));
         assign.setLocation(readRequiredAV(reader, ELEM_ASSIGN, ATTR_LOCATION));
         assign.setSrc(readAV(reader, ATTR_SRC));
-        assign.setPathResolver(configuration.pathResolver);
         readNamespaces(configuration, assign);
         assign.setParent(executable);
         if (parent != null) {
@@ -2254,9 +2278,10 @@ public final class SCXMLReader {
                 case XMLStreamConstants.CHARACTERS:
                 case XMLStreamConstants.ENTITY_REFERENCE:
                 case XMLStreamConstants.CDATA:
-                case XMLStreamConstants.COMMENT:
                     body.append(reader.getText());
                     break;
+                case XMLStreamConstants.COMMENT:
+                    break;
                 case XMLStreamConstants.END_ELEMENT:
                     break loop;
                 default: // rest is ignored

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java 
b/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
index d0ea429..82a6e48 100644
--- a/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
+++ b/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
@@ -815,6 +815,7 @@ public class SCXMLWriter {
 
         writer.writeStartElement(ELEM_INVOKE);
         writeAV(writer, ATTR_ID, invoke.getId());
+        writeAV(writer, ATTR_IDLOCATION, invoke.getIdlocation());
         writeAV(writer, ATTR_SRC, invoke.getSrc());
         writeAV(writer, ATTR_SRCEXPR, invoke.getSrcexpr());
         writeAV(writer, ATTR_TYPE, invoke.getType());

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/Assign.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Assign.java 
b/src/main/java/org/apache/commons/scxml2/model/Assign.java
index 6677520..f2ca819 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Assign.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Assign.java
@@ -30,7 +30,7 @@ import org.apache.commons.scxml2.io.ContentParser;
  * &lt;assign&gt; SCXML element.
  *
  */
-public class Assign extends Action implements PathResolverHolder {
+public class Assign extends Action {
 
     /**
      * Serial version UID.
@@ -54,11 +54,6 @@ public class Assign extends Action implements 
PathResolverHolder {
     private String expr;
 
     /**
-     * {@link PathResolver} for resolving the "src" result.
-     */
-    private PathResolver pathResolver;
-
-    /**
      * Constructor.
      */
     public Assign() {
@@ -120,24 +115,6 @@ public class Assign extends Action implements 
PathResolverHolder {
     }
 
     /**
-     * Get the {@link PathResolver}.
-     *
-     * @return Returns the pathResolver.
-     */
-    public PathResolver getPathResolver() {
-        return pathResolver;
-    }
-
-    /**
-     * Set the {@link PathResolver}.
-     *
-     * @param pathResolver The pathResolver to set.
-     */
-    public void setPathResolver(final PathResolver pathResolver) {
-        this.pathResolver = pathResolver;
-    }
-
-    /**
      * {@inheritDoc}
      */
     @Override
@@ -148,7 +125,7 @@ public class Assign extends Action implements 
PathResolverHolder {
         ctx.setLocal(getNamespacesKey(), getNamespaces());
         Object data;
         if (src != null && src.trim().length() > 0) {
-            data = getSrcData();
+            data = getSrcData(exctx.getStateMachine().getPathResolver());
         } else {
             data = evaluator.eval(ctx, expr);
         }
@@ -171,7 +148,7 @@ public class Assign extends Action implements 
PathResolverHolder {
      *
      * @return The data the "src" attribute points to.
      */
-    private Object getSrcData() {
+    private Object getSrcData(final PathResolver pathResolver) {
         String resolvedSrc = src;
         if (pathResolver != null) {
             resolvedSrc = pathResolver.resolvePath(src);

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/Content.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Content.java 
b/src/main/java/org/apache/commons/scxml2/model/Content.java
index b0a5928..2df2844 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Content.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Content.java
@@ -18,6 +18,8 @@ package org.apache.commons.scxml2.model;
 
 import java.io.Serializable;
 
+import org.w3c.dom.Node;
+
 /**
  * The class in this SCXML object model that corresponds to the
  * &lt;content&gt; SCXML element.
@@ -36,9 +38,14 @@ public class Content implements Serializable {
     private String expr;
 
     /**
-     * The body of this content, may be null.
+     * The body of this content parsed as Node, may be null.
+     */
+    private Node body;
+
+    /**
+     * The parsed content of the body of this content, may be null.
      */
-    private Object body;
+    private Object value;
 
     /**
      * Get the expression for this content.
@@ -59,15 +66,35 @@ public class Content implements Serializable {
     }
 
     /**
-     * Returns the content body as DocumentFragment
+     * Returns the content body as Node
      *
-     * @return the content body as DocumentFragment
+     * @return the content body as Node
      */
-    public Object getBody() {
+    public Node getBody() {
         return body;
     }
 
-    public void setBody(final Object body) {
+    /**
+     * Sets the content body as Node
+     * @param body the content body as Node
+     */
+    public void setBody(final Node body) {
         this.body = body;
     }
+
+    /**
+     * Returns the parsed content of the body
+     * @return the parsed content of the body
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Sets the parsed content of the body
+     * @param value the parsed content of the body
+     */
+    public void setValue(final Object value) {
+        this.value = value;
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/Invoke.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Invoke.java 
b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
index c14985c..588dace 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Invoke.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
@@ -19,6 +19,8 @@ package org.apache.commons.scxml2.model;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.xml.transform.TransformerException;
+
 import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
@@ -30,15 +32,16 @@ import org.apache.commons.scxml2.TriggerEvent;
 import org.apache.commons.scxml2.EventBuilder;
 import org.apache.commons.scxml2.invoke.Invoker;
 import org.apache.commons.scxml2.invoke.InvokerException;
+import org.apache.commons.scxml2.io.ContentParser;
 import org.apache.commons.scxml2.semantics.ErrorConstants;
-import org.w3c.dom.Node;
+import org.w3c.dom.Element;
 
 /**
  * The class in this SCXML object model that corresponds to the
  * &lt;invoke&gt; SCXML element.
  *
  */
-public class Invoke extends NamelistHolder implements PathResolverHolder, 
ContentContainer {
+public class Invoke extends NamelistHolder implements ContentContainer {
 
     /**
      * Serial version UID.
@@ -92,11 +95,6 @@ public class Invoke extends NamelistHolder implements 
PathResolverHolder, Conten
     private Finalize finalize;
 
     /**
-     * {@link PathResolver} for resolving the "src" or "srcexpr" result.
-     */
-    private PathResolver pathResolver;
-
-    /**
      * The &lt;content/&gt; of this invoke
      */
     private Content content;
@@ -254,24 +252,6 @@ public class Invoke extends NamelistHolder implements 
PathResolverHolder, Conten
     }
 
     /**
-     * Get the {@link PathResolver}.
-     *
-     * @return Returns the pathResolver.
-     */
-    public PathResolver getPathResolver() {
-        return pathResolver;
-    }
-
-    /**
-     * Set the {@link PathResolver}.
-     *
-     * @param pathResolver The pathResolver to set.
-     */
-    public void setPathResolver(final PathResolver pathResolver) {
-        this.pathResolver = pathResolver;
-    }
-
-    /**
      * Enforce identity equality only
      * @param other other object to compare with
      * @return this == other
@@ -375,27 +355,42 @@ public class Invoke extends NamelistHolder implements 
PathResolverHolder, Conten
                 src = (String)eval.eval(ctx, getSrcexpr());
             }
             if (src != null) {
-                PathResolver pr = getPathResolver();
+                PathResolver pr = exctx.getStateMachine().getPathResolver();
                 if (pr != null) {
-                    src = getPathResolver().resolvePath(src);
+                    src = pr.resolvePath(src);
                 }
             }
-            Node srcNode = null;
-            if (src == null && getContent() != null) {
-                Object contentValue;
+            Object contentValue = null;
+            if (src == null && content != null) {
                 if (content.getExpr() != null) {
                     contentValue = eval.eval(ctx, content.getExpr());
-                } else {
-                    contentValue = content.getBody();
-                }
-                if (contentValue instanceof Node) {
-                    srcNode = ((Node)contentValue).cloneNode(true);
+                } else if (content.getValue() != null) {
+                    contentValue = content.getValue();
                 }
-                else if (contentValue != null) {
-                    src = String.valueOf(contentValue);
+                if (contentValue instanceof String) {
+                    // inline content
+                } else if (contentValue instanceof Element) {
+                    // xml based content (must be assigned through data)
+                    Element contentElement = (Element)contentValue;
+                    if (contentElement.getLocalName().equals("scxml")) {
+                        // statemachine definition: transform to string as we 
cannot (yet) pass XML directly to invoker
+                        try {
+                            contentValue = 
ContentParser.DEFAULT_PARSER.transformXml(contentElement);
+                        }
+                        catch (TransformerException e) {
+                            throw new ActionExecutionError("<invoke> for state 
"+parentState.getId() +
+                                    ": invalid <content> definition");
+                        }
+                    } else {
+                        throw new ActionExecutionError("<invoke> for state 
"+parentState.getId() +
+                                ": invalid <content> definition");
+                    }
+                } else {
+                    throw new ActionExecutionError("<invoke> for state 
"+parentState.getId() +
+                            ": invalid <content> definition");
                 }
             }
-            if (src == null && srcNode == null) {
+            if (src == null && contentValue == null) {
                 throw new ActionExecutionError("<invoke> for state 
"+parentState.getId() +
                         ": no src and no content defined");
             }
@@ -406,7 +401,9 @@ public class Invoke extends NamelistHolder implements 
PathResolverHolder, Conten
             if (src != null) {
                 invoker.invoke(src, payloadDataMap);
             }
-            // TODO: } else { invoker.invoke(srcNode, payloadDataMap); }
+            else {
+                invoker.invokeContent((String)contentValue, payloadDataMap);
+            }
             exctx.registerInvoker(this, invoker);
         }
         catch (InvokerException|ActionExecutionError|SCXMLExpressionException 
e) {

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/PathResolverHolder.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/scxml2/model/PathResolverHolder.java 
b/src/main/java/org/apache/commons/scxml2/model/PathResolverHolder.java
deleted file mode 100644
index 629f74e..0000000
--- a/src/main/java/org/apache/commons/scxml2/model/PathResolverHolder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.model;
-
-import org.apache.commons.scxml2.PathResolver;
-
-/**
- * A <code>PathResolverHolder</code> is an entity that holds a
- * {@link PathResolver}.
- *
- */
-public interface PathResolverHolder {
-
-    /**
-     * Set the {@link PathResolver} to use.
-     *
-     * @param pathResolver The path resolver to use.
-     */
-    void setPathResolver(PathResolver pathResolver);
-
-    /**
-     * Get the {@link PathResolver}.
-     *
-     * @return The path resolver in use.
-     */
-    PathResolver getPathResolver();
-
-}
-

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/SCXML.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/SCXML.java 
b/src/main/java/org/apache/commons/scxml2/model/SCXML.java
index f6764ca..fd62f82 100644
--- a/src/main/java/org/apache/commons/scxml2/model/SCXML.java
+++ b/src/main/java/org/apache/commons/scxml2/model/SCXML.java
@@ -22,6 +22,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.scxml2.PathResolver;
+
 /**
  * The class in this SCXML object model that corresponds to the
  * &lt;scxml&gt; root element, and serves as the &quot;document
@@ -110,6 +112,11 @@ public class SCXML implements Serializable, Observable, 
NamespacePrefixesHolder
     private Script globalScript;
 
     /**
+     * used to resolve SCXML context sensitive paths
+     */
+    private PathResolver pathResolver;
+
+    /**
      * The immediate child targets of this SCXML document root.
      */
     private List<EnterableState> children;
@@ -164,6 +171,24 @@ public class SCXML implements Serializable, Observable, 
NamespacePrefixesHolder
     }
 
     /**
+     * Get the {@link PathResolver}.
+     *
+     * @return Returns the pathResolver.
+     */
+    public PathResolver getPathResolver() {
+        return pathResolver;
+    }
+
+    /**
+     * Set the {@link PathResolver}.
+     *
+     * @param pathResolver The pathResolver to set.
+     */
+    public void setPathResolver(final PathResolver pathResolver) {
+        this.pathResolver = pathResolver;
+    }
+
+    /**
      * Get the initial Transition.
      *
      * @return Returns the initial transition for this state machine.

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/main/java/org/apache/commons/scxml2/model/Send.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Send.java 
b/src/main/java/org/apache/commons/scxml2/model/Send.java
index b7ed695..ae00889 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Send.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Send.java
@@ -395,7 +395,10 @@ public class Send extends NamelistHolder implements 
ContentContainer {
             else if (content != null) {
                 if (content.getExpr() != null) {
                     payload = eval.cloneData(eval.eval(ctx, 
content.getExpr()));
-                } else {
+                } else if (content.getValue() != null) {
+                    payload = content.getValue();
+                }
+                else if (content.getBody() != null){
                     payload = eval.cloneData(content.getBody());
                 }
             }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java 
b/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java
index 1a198c1..f828cfa 100644
--- a/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java
+++ b/src/test/java/org/apache/commons/scxml2/invoke/InvokeParamNameTest.java
@@ -34,7 +34,7 @@ public class InvokeParamNameTest {
 
     private SCXMLExecutor exec;
 
-    static String lastSource;
+    static String lastURL;
     static Map<String, Object> lastParams;
     
     @Before
@@ -51,7 +51,7 @@ public class InvokeParamNameTest {
     
     private void trigger() throws ModelException {
         lastParams = null;
-        lastSource = null;
+        lastURL = null;
         exec.triggerEvent(new EventBuilder("test.trigger", 
TriggerEvent.SIGNAL_EVENT).build());
     }
     
@@ -59,7 +59,7 @@ public class InvokeParamNameTest {
     @Test
     public void testNameAndExpr() throws Exception {
         trigger();
-        Assert.assertTrue(lastSource.endsWith("TestSrc"));
+        Assert.assertTrue(lastURL.endsWith("TestSrc"));
         final Map.Entry<String, Object> e =
             lastParams.entrySet().iterator().next();
         Assert.assertEquals("ding", e.getKey());
@@ -81,14 +81,21 @@ public class InvokeParamNameTest {
         private String invokeId;
 
         @Override
-        public void invoke(String source, Map<String, Object> params)
+        public void invoke(String url, Map<String, Object> params)
         throws InvokerException {
-            lastSource = source;
+            lastURL = url;
             lastParams = params;
         }
 
-        public String lastSource() {
-            return lastSource;
+        @Override
+        public void invokeContent(String content, Map<String, Object> params)
+                throws InvokerException {
+            lastURL = null;
+            lastParams = params;
+        }
+
+        public String lastURL() {
+            return lastURL;
         }
 
         public Map<String, Object> lastParams() {

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/4e13be17/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml 
b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
index 82ea402..692df21 100644
--- a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
+++ b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
@@ -96,7 +96,7 @@
   <test id="335" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="336" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="337" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="338" mandatory="true"                    manual="false" 
jexl="false" ecma="false" implemented="false"/>
+  <test id="338" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="339" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="342" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="346" mandatory="true"  profile="minimal" manual="false" 
jexl="true"  ecma="true"/>
@@ -110,7 +110,7 @@
   <test id="183" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="185" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="186" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="187" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="187" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="194" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="198" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="199" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
@@ -118,36 +118,36 @@
   <test id="205" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="521" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="553" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="207" mandatory="true"                    manual="false" 
jexl="false" ecma="false" implemented="false"/>
+  <test id="207" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="208" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="210" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="215" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="215" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="216" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="220" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="223" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="224" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="225" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="220" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="223" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="224" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="225" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="226" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="228" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="229" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="230" mandatory="true"                    manual="true"  
jexl="false" ecma="false" finalState="final"/>
-  <test id="232" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="228" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="229" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="230" mandatory="true"                    manual="true"  
jexl="true"  ecma="true" finalState="final"/>
+  <test id="232" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="233" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
   <test id="234" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="235" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="236" mandatory="true"                    manual="false" 
jexl="false" ecma="false" implemented="false"/>
-  <test id="237" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="239" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="235" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="236" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="237" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="239" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="240" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
   <test id="241" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="242" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="243" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="242" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="243" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="244" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="245" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="247" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="250" mandatory="true"                    manual="true"  
jexl="false" ecma="false"  finalState="final"/>
-  <test id="252" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="253" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="245" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="247" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="250" mandatory="true"                    manual="true"  
jexl="true"  ecma="true" finalState="final"/>
+  <test id="252" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="253" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="530" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
   <test id="554" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
   <test id="436" mandatory="true"  profile="minimal" manual="false"            
               minimal="true"/>
@@ -164,19 +164,19 @@
   <test id="557" mandatory="false" profile="ecma"    manual="false"            
  ecma="false"/>
   <test id="558" mandatory="false" profile="ecma"    manual="false"            
  ecma="false"/>
   <test id="560" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
-  <test id="578" mandatory="false" profile="ecma"    manual="false"            
  ecma="false"/>
+  <test id="578" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="561" mandatory="false" profile="ecma"    manual="false"            
  ecma="false"/>
-  <test id="562" mandatory="false" profile="ecma"    manual="false"            
  ecma="false"/>
+  <test id="562" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="569" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="457" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="459" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="460" mandatory="false" profile="ecma"    manual="false"            
  ecma="true"/>
   <test id="189" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="190" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="191" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
-  <test id="192" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="191" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
+  <test id="192" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="193" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
-  <test id="347" mandatory="true"                    manual="false" 
jexl="false" ecma="false"/>
+  <test id="347" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="348" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="349" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>
   <test id="350" mandatory="true"                    manual="false" 
jexl="true"  ecma="true"/>

Reply via email to