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

[2/2] commons-scxml git commit: SCXML-242: Providing JSON base datamodel as replacement for XML/XPath See: https://issues.apache.org/jira/browse/SCXML-242 - adding FasterXML Jackson as (default) json parser - adding new ContentParser to encapsulate Data

SCXML-242: Providing JSON base datamodel as replacement for XML/XPath
See: https://issues.apache.org/jira/browse/SCXML-242
- adding FasterXML Jackson as (default) json parser
- adding new ContentParser to encapsulate Data (content) parsing logic
- adding new AbstractBaseEvaluator for common new cloneData method
- replace all XML based datamodel examples with JSON and dropping all Data() and Location() usages
- dropping Data() and Location() implementations and related XPathBuiltin for Jexl, Javascript and Groovy languages
- deleting no longer relevant XPath based unit-tests


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

Branch: refs/heads/master
Commit: 6af929eb622b07742d4eeac3b754c60ad6a60a3d
Parents: 7b3a237
Author: Ate Douma <at...@apache.org>
Authored: Sat Dec 26 18:49:34 2015 +0100
Committer: Ate Douma <at...@apache.org>
Committed: Sat Dec 26 18:49:34 2015 +0100

----------------------------------------------------------------------
 pom.xml                                         |  22 +-
 .../org/apache/commons/scxml2/Evaluator.java    |   6 +
 .../org/apache/commons/scxml2/SCInstance.java   |  16 +-
 .../org/apache/commons/scxml2/XPathBuiltin.java |  93 -------
 .../scxml2/env/AbstractBaseEvaluator.java       |  82 ++++++
 .../scxml2/env/groovy/GroovyEvaluator.java      |  30 +--
 .../scxml2/env/groovy/GroovySCXMLScript.java    |  27 +-
 .../scxml2/env/javascript/JSEvaluator.java      |  78 +++---
 .../scxml2/env/javascript/JSFunctions.java      |  25 +-
 .../commons/scxml2/env/jexl/JexlBuiltin.java    |  25 +-
 .../commons/scxml2/env/jexl/JexlEvaluator.java  |  30 +--
 .../scxml2/env/minimal/MinimalEvaluator.java    |   5 +
 .../scxml2/env/xpath/XPathEvaluator.java        |   4 +-
 .../apache/commons/scxml2/io/ContentParser.java | 217 ++++++++++++++++
 .../apache/commons/scxml2/io/SCXMLReader.java   |  25 +-
 .../org/apache/commons/scxml2/model/Assign.java |  31 +--
 .../org/apache/commons/scxml2/model/Data.java   |  53 ++--
 .../scxml2/NamespacePrefixedXPathsTest.java     |  89 -------
 .../commons/scxml2/env/groovy/datamodel-01.xml  |  84 ++++++
 .../commons/scxml2/env/groovy/datamodel-05.xml  |  80 ++++++
 .../scxml2/env/javascript/JSEvaluatorTest.java  |  65 +++--
 .../scxml2/env/javascript/datamodel-01.xml      |  84 ++++++
 .../scxml2/env/javascript/datamodel-05.xml      |  80 ++++++
 .../scxml2/env/javascript/example-01.xml        |  39 +--
 .../commons/scxml2/env/jexl/datamodel-01.xml    |  56 +---
 .../commons/scxml2/env/jexl/datamodel-02.xml    |  90 -------
 .../commons/scxml2/env/jexl/datamodel-03.xml    | 255 -------------------
 .../commons/scxml2/env/jexl/datamodel-04.xml    |  48 ----
 .../commons/scxml2/env/jexl/datamodel-05.xml    |  66 +++--
 .../commons/scxml2/env/jexl/eventdata-03.xml    |  11 +-
 .../scxml2/invoke/InvokeParamNameTest.java      |  13 +-
 .../apache/commons/scxml2/invoke/invoker-04.xml |   8 +-
 .../commons/scxml2/io/ContentParserTest.java    |  79 ++++++
 .../commons/scxml2/model/DatamodelTest.java     |  57 +++--
 .../commons/scxml2/model/ParallelTest.java      |  14 +-
 .../apache/commons/scxml2/model/SendTest.java   |   4 +-
 .../apache/commons/scxml2/model/assign-src.json |  25 ++
 .../apache/commons/scxml2/model/assign-src.xml  |  21 --
 .../commons/scxml2/model/assign-test-01.xml     |  29 +--
 .../commons/scxml2/model/assign-test-02.xml     |  23 +-
 .../commons/scxml2/model/cancel-test-01.xml     |  11 +-
 .../commons/scxml2/model/cancel-test-02.xml     |  11 +-
 .../apache/commons/scxml2/model/parallel-03.xml |  34 ++-
 .../commons/scxml2/model/send-test-01.xml       |  11 +-
 44 files changed, 1085 insertions(+), 1071 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index e4cdb5f..fbe52ce 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,6 +143,21 @@
       <version>1.1.3</version>
     </dependency>
     <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+      <version>2.6.4</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>2.6.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.11</version>
@@ -170,12 +185,6 @@
       <artifactId>commons-beanutils</artifactId>
       <version>1.9.2</version>
     </dependency>
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.4</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <distributionManagement>
@@ -211,6 +220,7 @@
         <directory>src/test/java</directory>
         <includes>
           <include>**/*.xml</include>
+          <include>**/*.json</include>
           <include>**/*.xsl</include>
           <include>**/*.gif</include>
         </includes>

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/Evaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/Evaluator.java b/src/main/java/org/apache/commons/scxml2/Evaluator.java
index ae2e744..0d7cad7 100644
--- a/src/main/java/org/apache/commons/scxml2/Evaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/Evaluator.java
@@ -76,6 +76,12 @@ public interface Evaluator {
     String getSupportedDatamodel();
 
     /**
+     * @param data data to be cloned
+     * @return A deep clone of the data
+     */
+    Object cloneData(Object data);
+
+    /**
      * Evaluate an expression returning a data value
      *
      * @param ctx variable context

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/SCInstance.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCInstance.java b/src/main/java/org/apache/commons/scxml2/SCInstance.java
index 6b0e5b8..1260fa4 100644
--- a/src/main/java/org/apache/commons/scxml2/SCInstance.java
+++ b/src/main/java/org/apache/commons/scxml2/SCInstance.java
@@ -299,15 +299,14 @@ public class SCInstance implements Serializable {
                 // earlier or externally defined 'initial' value found: do not overwrite
                 continue;
             }
-            Node datumNode = datum.getNode();
-            Node valueNode = null;
-            if (datumNode != null) {
-                valueNode = datumNode.cloneNode(true);
-            }
+            /*
+            TODO: external data.src support (not yet implemented), including late-binding thereof
             // prefer "src" over "expr" over "inline"
             if (datum.getSrc() != null) {
                 ctx.setLocal(datum.getId(), valueNode);
-            } else if (datum.getExpr() != null) {
+            } else
+            */
+            if (datum.getExpr() != null) {
                 Object value;
                 try {
                     ctx.setLocal(Context.NAMESPACES_KEY, datum.getNamespaces());
@@ -345,8 +344,9 @@ public class SCInstance implements Serializable {
                 else {
                     ctx.setLocal(datum.getId(), value);
                 }
-            } else {
-                ctx.setLocal(datum.getId(), valueNode);
+            }
+            else {
+                ctx.setLocal(datum.getId(), evaluator.cloneData(datum.getValue()));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/XPathBuiltin.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/XPathBuiltin.java b/src/main/java/org/apache/commons/scxml2/XPathBuiltin.java
deleted file mode 100644
index faba709..0000000
--- a/src/main/java/org/apache/commons/scxml2/XPathBuiltin.java
+++ /dev/null
@@ -1,93 +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;
-
-import org.apache.commons.scxml2.env.xpath.XPathEvaluator;
-
-/**
- * Implementation and support of Commons SCXML builtin predicates to support XPath based datamodel operations
- * for non-XPath languages.
- *
- * These static builtin functions delegate to a static {@link }XPathEvaluator} instance.
- */
-public class XPathBuiltin {
-
-    private static XPathEvaluator evaluator = new XPathEvaluator();
-
-    /**
-     * Optional static setter to change and override the default {@link XPathEvaluator}
-     * @param evaluator A custom evaluator to be used
-     */
-    public static void setEvaluator(XPathEvaluator evaluator) {
-        XPathBuiltin.evaluator = evaluator;
-    }
-
-    /**
-     * Evaluate an xpath expression returning a data value
-     *
-     * @param ctx variable context
-     * @param expression xpath expression
-     * @return the result of the evaluation
-     * @throws SCXMLExpressionException A malformed expression exception
-     * @see Evaluator#eval(Context, String)
-     */
-    public static Object eval(Context ctx, String expression) throws SCXMLExpressionException {
-        return evaluator.eval(ctx, expression);
-    }
-
-    /**
-     * Evaluate an xpath location that returns a data assignable reference or list of references.
-     * Manifests as "location" attributes of &lt;assign&gt; element.
-     *
-     * @param ctx variable context
-     * @param expression expression
-     * @return The location result.
-     * @throws SCXMLExpressionException A malformed expression exception
-     * @see Evaluator#evalLocation(Context, String)
-     */
-    public static Object evalLocation(Context ctx, String expression) throws SCXMLExpressionException {
-        return evaluator.evalLocation(ctx, expression);
-    }
-
-    /**
-     * Determine if an {@link Evaluator#evalLocation(Context, String)} returned result represents an XPath location
-     * @param ctx variable context
-     * @param data result data from {@link Evaluator#evalLocation(Context, String)}
-     * @return true if the data represents an XPath location
-     * @see XPathEvaluator#isXPathLocation(Context, Object)
-     */
-    public static boolean isXPathLocation(Context ctx, Object data) {
-        return evaluator.isXPathLocation(ctx, data);
-    }
-
-    /**
-     * Assigns data to a location
-     *
-     * @param ctx variable context
-     * @param location location expression
-     * @param data the data to assign.
-     * @param type the type of assignment to perform, null assumes {@link Evaluator.AssignType#REPLACE_CHILDREN}
-     * @param attr the name of the attribute to add when using type {@link Evaluator.AssignType#ADD_ATTRIBUTE}
-     * @throws SCXMLExpressionException A malformed expression exception
-     * @see Evaluator#evalAssign(Context, String, Object, Evaluator.AssignType, String)
-     * @see XPathEvaluator#assign(Context, Object, Object, Evaluator.AssignType, String)
-     */
-    public static void assign(Context ctx, Object location, Object data, Evaluator.AssignType type, String attr)
-            throws SCXMLExpressionException {
-        evaluator.assign(ctx, location, data, type, attr);
-    }
-}

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/AbstractBaseEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/AbstractBaseEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/AbstractBaseEvaluator.java
new file mode 100644
index 0000000..abd96a4
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/env/AbstractBaseEvaluator.java
@@ -0,0 +1,82 @@
+/*
+ * 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.env;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.scxml2.Evaluator;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Base Evaluator providing common functionality for most Evaluator implementations
+ */
+public abstract class AbstractBaseEvaluator implements Evaluator, Serializable {
+
+    @Override
+    public Object cloneData(final Object data) {
+        if (data != null) {
+            if (data instanceof String || data instanceof Number || data instanceof Boolean) {
+                return data;
+            }
+            if (data instanceof Node) {
+                return ((Node)data).cloneNode(true);
+            }
+            else if (data instanceof NodeList) {
+                NodeList nodeList = (NodeList)data;
+                ArrayList<Node> list = new ArrayList<>();
+                for (int i = 0, size = nodeList.getLength(); i < size; i++) {
+                    list.add(nodeList.item(i).cloneNode(true));
+                }
+                return list;
+            }
+            else if (data instanceof List) {
+                ArrayList<Object> list = new ArrayList<>();
+                for (Object v : (List)data) {
+                    list.add(cloneData(v));
+                }
+                return list;
+            }
+            else if (data instanceof Map) {
+                Map<?,?> dataMap = (Map<?,?>)data;
+                HashMap<Object, Object> map = new LinkedHashMap<>();
+                for (Map.Entry<?,?> entry : dataMap.entrySet()) {
+                    map.put(cloneData(entry.getKey()), cloneData(entry.getValue()));
+                }
+                return map;
+            }
+            else {
+                return cloneUnknownDataType(data);
+            }
+        }
+        return data;
+    }
+
+    /**
+     * Returns cloned value of data of unknown type, to be overridden as desired by specialized Evaluators
+     * @param data data object of unknown type (not of type String, Number, Boolean, Node, NodeList, List or Map)
+     * @return toString() value of data of unknown type
+     */
+    protected Object cloneUnknownDataType(final Object data) {
+        return data.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
index f67e7d1..c82d2d7 100644
--- a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
@@ -18,7 +18,6 @@ package org.apache.commons.scxml2.env.groovy;
 
 import groovy.lang.Script;
 
-import java.io.Serializable;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -31,7 +30,7 @@ import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.EvaluatorProvider;
 import org.apache.commons.scxml2.SCXMLExpressionException;
 import org.apache.commons.scxml2.SCXMLSystemContext;
-import org.apache.commons.scxml2.XPathBuiltin;
+import org.apache.commons.scxml2.env.AbstractBaseEvaluator;
 import org.apache.commons.scxml2.env.EffectiveContextMap;
 import org.apache.commons.scxml2.model.SCXML;
 
@@ -41,7 +40,7 @@ import org.apache.commons.scxml2.model.SCXML;
  * This implementation itself is thread-safe, so you can keep singleton for efficiency.
  * </P>
  */
-public class GroovyEvaluator implements Evaluator, Serializable {
+public class GroovyEvaluator extends AbstractBaseEvaluator {
 
     /** Serial version UID. */
     private static final long serialVersionUID = 1L;
@@ -256,26 +255,13 @@ public class GroovyEvaluator implements Evaluator, Serializable {
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
                            final String attr) throws SCXMLExpressionException {
-
-        final Object loc = evalLocation(ctx, location);
-        if (loc != null) {
-
-            if (XPathBuiltin.isXPathLocation(ctx, loc)) {
-                XPathBuiltin.assign(ctx, loc, data, type, attr);
-            }
-            else {
-                final StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
-                try {
-                    ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
-                    eval(ctx, sb.toString());
-                }
-                finally {
-                    ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
-                }
-            }
+        final StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
+        try {
+            ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
+            eval(ctx, sb.toString());
         }
-        else {
-            throw new SCXMLExpressionException("evalAssign - cannot resolve location: '" + location + "'");
+        finally {
+            ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java
index 29407ef..5980211 100644
--- a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java
+++ b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java
@@ -25,13 +25,10 @@ import java.util.Collection;
 import java.util.Map;
 
 import org.apache.commons.scxml2.Builtin;
-import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.XPathBuiltin;
 
 /**
- * Groovy {@link Script} base class for SCXML, providing the standard 'builtin' functions {@link #In(String)},
- * {@link #Data(String)} and {@link #Location(String)}, as well as JEXL like convenience functions
- * {@link #empty(Object)} and {@link #var(String)}.
+ * Groovy {@link Script} base class for SCXML, providing the standard 'builtin' function {@link #In(String)},
+ * as well as JEXL like convenience functions {@link #empty(Object)} and {@link #var(String)}.
  */
 public abstract class GroovySCXMLScript extends Script {
 
@@ -59,26 +56,6 @@ public abstract class GroovySCXMLScript extends Script {
     }
 
     /**
-     * Implements the Data() predicate for SCXML documents.
-     * @param expression the XPath expression
-     * @return the data matching the expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Data(final String expression) throws SCXMLExpressionException {
-        return XPathBuiltin.eval(context, expression);
-    }
-
-    /**
-     * Implements the Location() predicate for SCXML documents.
-     * @param location the XPath expression
-     * @return the location list for the location expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Location(final String location) throws SCXMLExpressionException {
-        return XPathBuiltin.evalLocation(context, location);
-    }
-
-    /**
      * The var function can be used to check if a variable is defined,
      * <p>
      * In the Groovy language (implementation) you cannot check for an undefined variable directly:

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
index 9fee8ea..ca0d8eb 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
@@ -29,23 +29,17 @@ import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.EvaluatorProvider;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.XPathBuiltin;
+import org.apache.commons.scxml2.env.AbstractBaseEvaluator;
 import org.apache.commons.scxml2.env.EffectiveContextMap;
 import org.apache.commons.scxml2.model.SCXML;
 
 /**
  * Embedded JavaScript expression evaluator for SCXML expressions. This
  * implementation is a just a 'thin' wrapper around the Javascript engine in
- * JDK 6 (based on on Mozilla Rhino 1.6.2).
- * <p>
- * Mozilla Rhino 1.6.2 does not support E4X so accessing the SCXML data model
- * is implemented in the same way as the JEXL expression evaluator i.e. using
- * the Data() function, for example,
- * &lt;assign location="Data(hotelbooking,'hotel/rooms')" expr="2" /&gt;
- * </p>
+ * JDK 8.
  */
 
-public class JSEvaluator implements Evaluator {
+public class JSEvaluator extends AbstractBaseEvaluator {
 
     /**
      * Unique context variable name used for temporary reference to assign data (thus must be a valid variable name)
@@ -78,14 +72,10 @@ public class JSEvaluator implements Evaluator {
 
     /** Pattern for recognizing the SCXML In() special predicate. */
     private static final Pattern IN_FN = Pattern.compile("In\\(");
-    /** Pattern for recognizing the Commons SCXML Data() builtin function. */
-    private static final Pattern DATA_FN = Pattern.compile("Data\\(");
-    /** Pattern for recognizing the Commons SCXML Location() builtin function. */
-    private static final Pattern LOCATION_FN = Pattern.compile("Location\\(");
 
     // INSTANCE VARIABLES
 
-    private ScriptEngineManager factory;
+    private transient ScriptEngineManager factory;
 
     // CONSTRUCTORS
 
@@ -98,12 +88,32 @@ public class JSEvaluator implements Evaluator {
 
     // INSTANCE METHODS
 
+    protected ScriptEngineManager getFactory() {
+        if (factory == null) {
+            factory = new ScriptEngineManager();
+        }
+        return factory;
+    }
+
     @Override
     public String getSupportedDatamodel() {
         return SUPPORTED_DATA_MODEL;
     }
 
     /**
+     * @return Returns JavaScript "undefined" for null, otherwise inherited behavior
+     */
+    @Override
+    public Object cloneData(final Object data) {
+        if (data == null) {
+            ScriptEngine engine = getFactory().getEngineByName("JavaScript");
+            Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
+            return bindings.get("undefined");
+        }
+        return super.cloneData(data);
+    }
+
+    /**
      * Creates a child context.
      *
      * @return Returns a new child JSContext.
@@ -117,8 +127,8 @@ public class JSEvaluator implements Evaluator {
     /**
      * Evaluates the expression using a new Javascript engine obtained from
      * factory instantiated in the constructor. The engine is supplied with
-     * a new JSBindings that includes the SCXML Context and
-     * <code>Data()</code> functions are replaced with an equivalent internal
+     * a new JSBindings that includes the SCXML Context and SCXML builtin
+     * <code>In()</code> function is replaced with an equivalent internal
      * Javascript function.
      *
      * @param context    SCXML context.
@@ -142,13 +152,11 @@ public class JSEvaluator implements Evaluator {
             JSContext effectiveContext = getEffectiveContext((JSContext) context);
 
             // ... initialize
-            ScriptEngine engine = factory.getEngineByName("JavaScript");
+            ScriptEngine engine = getFactory().getEngineByName("JavaScript");
             Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
 
             // ... replace built-in functions
             String jsExpression = IN_FN.matcher(expression).replaceAll("_builtin.In(");
-            jsExpression = DATA_FN.matcher(jsExpression).replaceAll("_builtin.Data(");
-            jsExpression = LOCATION_FN.matcher(jsExpression).replaceAll("_builtin.Location(");
 
             // ... evaluate
             JSBindings jsBindings = new JSBindings(effectiveContext, bindings);
@@ -196,8 +204,8 @@ public class JSEvaluator implements Evaluator {
     /**
      * Evaluates a location expression using a new Javascript engine obtained from
      * factory instantiated in the constructor. The engine is supplied with
-     * a new JSBindings that includes the SCXML Context and
-     * <code>Data()</code> functions are replaced with an equivalent internal
+     * a new JSBindings that includes the SCXML Context and SCXML builtin
+     * <code>In()</code> function is replaced with an equivalent internal
      * Javascript function.
      *
      * @param context    FSM context.
@@ -221,32 +229,20 @@ public class JSEvaluator implements Evaluator {
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
                            final String attr) throws SCXMLExpressionException {
-
-        Object loc = evalLocation(ctx, location);
-
-        if (loc != null) {
-            if (XPathBuiltin.isXPathLocation(ctx, loc)) {
-                XPathBuiltin.assign(ctx, loc, data, type, attr);
-            } else {
-                StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
-
-                try {
-                    ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
-                    eval(ctx, sb.toString());
-                } finally {
-                    ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
-                }
-            }
-        } else {
-            throw new SCXMLExpressionException("evalAssign - cannot resolve location: '" + location + "'");
+        StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
+        try {
+            ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
+            eval(ctx, sb.toString());
+        } finally {
+            ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
         }
     }
 
     /**
      * Executes the script using a new Javascript engine obtained from
      * factory instantiated in the constructor. The engine is supplied with
-     * a new JSBindings that includes the SCXML Context and
-     * <code>Data()</code> functions are replaced with an equivalent internal
+     * a new JSBindings that includes the SCXML Context and SCXML builtin
+     * <code>In()</code> function is replaced with an equivalent internal
      * Javascript function.
      *
      * @param ctx    SCXML context.

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
index bf99ee7..45771a0 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
@@ -20,12 +20,9 @@ import java.io.Serializable;
 
 import org.apache.commons.scxml2.Builtin;
 import org.apache.commons.scxml2.Context;
-import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.XPathBuiltin;
 
 /**
- * Custom Javascript engine function providing the SCXML In() predicate and the Commons SCXML extensions
- * for Data() and Location() to support XPath datamodel access.
+ * Custom Javascript engine function providing the SCXML In() predicate .
  */
 public class JSFunctions implements Serializable {
 
@@ -50,24 +47,4 @@ public class JSFunctions implements Serializable {
     public boolean In(final String state) {
         return Builtin.isMember(ctx, state);
     }
-
-    /**
-     * Provides the Commons SCXML Data() predicate extension for SCXML documents.
-     * @param expression the XPath expression
-     * @return the data matching the expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Data(String expression) throws SCXMLExpressionException {
-        return XPathBuiltin.eval(ctx, expression);
-    }
-
-    /**
-     * Provides the Commons SCXML Location() predicate extension for SCXML documents.
-     * @param expression the XPath expression
-     * @return the location matching the expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Location(String expression) throws SCXMLExpressionException {
-        return XPathBuiltin.evalLocation(ctx, expression);
-    }
 }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java
index b1ece86..cddd0f5 100644
--- a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java
+++ b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java
@@ -17,12 +17,9 @@
 package org.apache.commons.scxml2.env.jexl;
 
 import org.apache.commons.scxml2.Builtin;
-import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.XPathBuiltin;
 
 /**
- * Global JEXL namespace functor, providing the standard SCXML In() operator and the Commons SCXML extensions
- * for Data() and Location() to support XPath datamodel access.
+ * Global JEXL namespace functor, providing the standard SCXML In() predicate.
  */
 public final class JexlBuiltin {
     /**
@@ -46,24 +43,4 @@ public final class JexlBuiltin {
     public boolean In(final String state) {
         return Builtin.isMember(context, state);
     }
-
-    /**
-     * Provides the Commons SCXML Data() predicate extension for SCXML documents.
-     * @param expression the XPath expression
-     * @return the data matching the expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Data(final String expression) throws SCXMLExpressionException {
-        return XPathBuiltin.eval(context, expression);
-    }
-
-    /**
-     * Provides the Commons SCXML Location() predicate extension for SCXML documents.
-     * @param expression the XPath expression
-     * @return the location matching the expression
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    public Object Location(final String expression) throws SCXMLExpressionException {
-        return XPathBuiltin.evalLocation(context, expression);
-    }
 }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
index 3dd0088..d08946c 100644
--- a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.scxml2.env.jexl;
 
-import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
@@ -28,7 +27,7 @@ import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.EvaluatorProvider;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.XPathBuiltin;
+import org.apache.commons.scxml2.env.AbstractBaseEvaluator;
 import org.apache.commons.scxml2.env.EffectiveContextMap;
 import org.apache.commons.scxml2.model.SCXML;
 
@@ -40,7 +39,7 @@ import org.apache.commons.scxml2.model.SCXML;
  * for efficiency of the internal <code>JexlEngine</code> member.
  * </P>
  */
-public class JexlEvaluator implements Evaluator, Serializable {
+public class JexlEvaluator extends AbstractBaseEvaluator {
 
     /** Serial version UID. */
     private static final long serialVersionUID = 1L;
@@ -222,26 +221,13 @@ public class JexlEvaluator implements Evaluator, Serializable {
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
                            final String attr) throws SCXMLExpressionException {
-
-        Object loc = evalLocation(ctx, location);
-        if (loc != null) {
-
-            if (XPathBuiltin.isXPathLocation(ctx, loc)) {
-                XPathBuiltin.assign(ctx, loc, data, type, attr);
-            }
-            else {
-                StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
-                try {
-                    ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
-                    eval(ctx, sb.toString());
-                }
-                finally {
-                    ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
-                }
-            }
+        StringBuilder sb = new StringBuilder(location).append("=").append(ASSIGN_VARIABLE_NAME);
+        try {
+            ctx.getVars().put(ASSIGN_VARIABLE_NAME, data);
+            eval(ctx, sb.toString());
         }
-        else {
-            throw new SCXMLExpressionException("evalAssign - cannot resolve location: '" + location + "'");
+        finally {
+            ctx.getVars().remove(ASSIGN_VARIABLE_NAME);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
index 401df4e..66c18e5 100644
--- a/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
@@ -62,6 +62,11 @@ public class MinimalEvaluator implements Evaluator, Serializable {
     }
 
     @Override
+    public Object cloneData(final Object data) {
+        return data;
+    }
+
+    @Override
     public Object eval(final Context ctx, final String expr) throws SCXMLExpressionException {
         return expr;
     }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
index 763f090..0da7103 100644
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.scxml2.env.xpath;
 
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -34,6 +33,7 @@ import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.EvaluatorProvider;
 import org.apache.commons.scxml2.SCXMLExpressionException;
+import org.apache.commons.scxml2.env.AbstractBaseEvaluator;
 import org.apache.commons.scxml2.env.EffectiveContextMap;
 import org.apache.commons.scxml2.model.SCXML;
 import org.w3c.dom.Attr;
@@ -48,7 +48,7 @@ import org.w3c.dom.NodeList;
  * <p>Does not support the &lt;script&gt; module, throws
  * {@link UnsupportedOperationException} if attempted.</p>
  */
-public class XPathEvaluator implements Evaluator, Serializable {
+public class XPathEvaluator extends AbstractBaseEvaluator {
 
     /** Serial version UID. */
     private static final long serialVersionUID = -3578920670869493294L;

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/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
new file mode 100644
index 0000000..eb044eb
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/io/ContentParser.java
@@ -0,0 +1,217 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.commons.io.IOUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+/**
+ * The ContentParser provides utility methods for cleaning content strings and parsing them into "raw" content model Objects
+ */
+public class ContentParser {
+
+    public static final ContentParser DEFAULT_PARSER = new ContentParser();
+
+    /**
+     * Jackson JSON ObjectMapper
+     */
+    private ObjectMapper jsonObjectMapper;
+
+    /**
+     * Default constructor initializing a Jackson ObjectMapper allowing embedded comments, including YAML style
+     */
+    public ContentParser() {
+        this.jsonObjectMapper = new ObjectMapper();
+        jsonObjectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
+        jsonObjectMapper.configure(JsonParser.Feature.ALLOW_YAML_COMMENTS, true);
+    }
+
+    /**
+     * Constructor with a custom configured Jackson ObjectMapper
+     * @param jsonObjectMapper custom configured Jackson ObjectMapper
+     */
+    public ContentParser(final ObjectMapper jsonObjectMapper) {
+        this.jsonObjectMapper = jsonObjectMapper;
+    }
+
+    /**
+     * Trim pre/post-fixed whitespace from content string
+     * @param content content to trim
+     * @return trimmed content
+     */
+    public static String trimContent(final String content) {
+        if (content != null) {
+            int start = 0;
+            int length = content.length();
+            while (start < length && isWhiteSpace(content.charAt(start))) {
+                start++;
+            }
+            while (length > start && isWhiteSpace(content.charAt(length - 1))) {
+                length--;
+            }
+            if (start == length) {
+                return "";
+            }
+            return content.substring(start, length);
+        }
+        return null;
+    }
+
+    /**
+     * Space normalize content string, trimming pre/post-fixed whitespace and collapsing embedded whitespaces to
+     * single space.
+     * @param content content to space-normalize
+     * @return space-normalized content
+     */
+    public static String spaceNormalizeContent(final String content) {
+        if (content != null) {
+            int index = 0;
+            int length = content.length();
+            StringBuilder buffer = new StringBuilder(length);
+            boolean whiteSpace = false;
+            while (index < length) {
+                if (isWhiteSpace(content.charAt(index))) {
+                    if (!whiteSpace && buffer.length() > 0) {
+                        buffer.append(' ');
+                        whiteSpace = true;
+                    }
+                }
+                else {
+                    buffer.append(content.charAt(index));
+                    whiteSpace = false;
+                }
+                index++;
+            }
+            if (whiteSpace) {
+                buffer.setLength(buffer.length()-1);
+            }
+            return buffer.toString();
+        }
+        return null;
+    }
+
+    /**
+     * Check if a character is whitespace (space, tab, newline, cr) or not
+     * @param c character to check
+     * @return true if character is whitespace
+     */
+    public static boolean isWhiteSpace(final char c) {
+        return c==' ' || c=='\n' || c=='\t' || c=='\r';
+    }
+
+    /**
+     * Check if content starts with JSON object '{' or array '[' marker
+     * @param content text to check
+     * @return true if content start with '{' or '[' character
+     */
+    public static boolean hasJsonSignature(final String content) {
+        final char c = content.length() > 0 ? content.charAt(0) : 0;
+        return c == '{' || c == '[';
+    }
+
+    /**
+     * Check if content indicates its an XML document
+     * @param content content to check
+     * @return true if content indicates its an XML document
+     */
+    public static boolean hasXmlSignature(final String content) {
+        return content != null && content.startsWith("<?xml ");
+    }
+
+    /**
+     * Parse and map JSON string to 'raw' Java Objects: object -> LinkedHashMap, array -> ArrayList
+     * @param jsonString JSON string to parse
+     * @return 'raw' mapped Java Object for JSON string
+     * @throws IOException In case of parsing exceptions
+     */
+    public Object parseJson(final String jsonString) throws IOException {
+        return jsonObjectMapper.readValue(jsonString, Object.class);
+    }
+
+    /**
+     * Parse an XML String and return the document element
+     * @param xmlString XML String to parse
+     * @return document element
+     * @throws IOException
+     */
+    public Node parseXml(final String xmlString) throws IOException {
+        Document doc = null;
+        try {
+            doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlString);
+        } catch (SAXException e) {
+            throw new IOException(e);
+        } catch (ParserConfigurationException e) {
+            throw new IOException(e);
+        }
+        return doc != null ? doc.getDocumentElement() : null;
+    }
+
+    /**
+     * Parse a string into a content object, following the SCXML rules as specified for the ECMAscript (section B.2.1) Data Model
+     * <ul>
+     *   <li>if the content can be interpreted as JSON, it will be parsed as JSON into an 'raw' object model</li>
+     *   <li>if the content can be interpreted as XML, it will be parsed into a XML DOM element</li>
+     *   <li>otherwise the content will be treated (cleaned) as a space-normalized string literal</li>
+     * </ul>
+     * @param content the content to parse
+     * @return the parsed content object
+     * @throws IOException In case of parsing exceptions
+     */
+    public Object parseContent(final String content) throws IOException {
+        if (content != null) {
+            String src = trimContent(content);
+            if (hasJsonSignature(src)) {
+                return parseJson(src);
+            }
+            else if (hasXmlSignature(src)) {
+                return parseXml(src);
+            }
+            return spaceNormalizeContent(src);
+        }
+        return null;
+    }
+
+    /**
+     * Load a resource (URL) as an UTF-8 encoded content string to be parsed into a content object through {@link #parseContent(String)}
+     * @param resourceURL Resource URL to load content from
+     * @return the parsed content object
+     * @throws IOException In case of loading or parsing exceptions
+     */
+    public Object parseResource(final String resourceURL) throws IOException {
+        InputStream in = null;
+        try {
+            in = new URL(resourceURL).openStream();
+            String content = IOUtils.toString(in, "UTF-8");
+            return parseContent(content);
+        }
+        finally {
+            IOUtils.closeQuietly(in);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/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 d4d2715..2bb0a0e 100644
--- a/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
+++ b/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
@@ -1096,7 +1096,27 @@ public final class SCXMLReader {
         datum.setId(readRequiredAV(reader, ELEM_DATA, ATTR_ID));
         datum.setExpr(readAV(reader, ATTR_EXPR));
         readNamespaces(configuration, datum);
-        datum.setNode(readNode(reader, configuration, XMLNS_SCXML, ELEM_DATA, new String[]{"id"}));
+        Node node = readNode(reader, configuration, XMLNS_SCXML, ELEM_DATA, new String[]{"id"});
+        datum.setNode(node);
+        if (node.hasChildNodes()) {
+            NodeList children = node.getChildNodes();
+            if (children.getLength() == 1 && children.item(0).getNodeType() == Node.TEXT_NODE) {
+                String text = configuration.contentParser.trimContent(children.item(0).getNodeValue());
+                if (configuration.contentParser.hasJsonSignature(text)) {
+                    try {
+                        datum.setValue(configuration.contentParser.parseJson(text));
+                    } catch (IOException e) {
+                        throw new ModelException(e);
+                    }
+                }
+                else {
+                    datum.setValue(configuration.contentParser.spaceNormalizeContent(text));
+                }
+            }
+        }
+        if (datum.getValue() == null) {
+            datum.setValue(node);
+        }
         dm.addData(datum);
     }
 
@@ -2700,6 +2720,8 @@ public final class SCXMLReader {
          */
         boolean strict;
 
+        ContentParser contentParser;
+
         /*
          * Public constructors
          */
@@ -2872,6 +2894,7 @@ public final class SCXMLReader {
             this.namespaces = new HashMap<String, Stack<String>>();
             this.silent = silent;
             this.strict = strict;
+            this.contentParser = new ContentParser();
         }
 
         /*

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/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 172aa85..6d07b3e 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Assign.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Assign.java
@@ -17,19 +17,13 @@
 package org.apache.commons.scxml2.model;
 
 import java.io.IOException;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.PathResolver;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.w3c.dom.*;
-import org.xml.sax.SAXException;
+import org.apache.commons.scxml2.io.ContentParser;
 
 /**
  * The class in this SCXML object model that corresponds to the
@@ -180,7 +174,7 @@ public class Assign extends Action implements PathResolverHolder {
         ctx.setLocal(getNamespacesKey(), getNamespaces());
         Object data;
         if (src != null && src.trim().length() > 0) {
-            data = getSrcNode();
+            data = getSrcData();
         } else {
             data = evaluator.eval(ctx, expr);
         }
@@ -192,41 +186,28 @@ public class Assign extends Action implements PathResolverHolder {
         // TODO: introduce a optional 'trace.change' setting or something alike to enable .change events,
        //        but don't do this by default as it can interfere with transitions not expecting such events
         /*
-        if ((Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel()) && location.startsWith("$") && ctx.has(location.substring(1))
-                || ctx.has(location))) {
             TriggerEvent ev = new TriggerEvent(location + ".change", TriggerEvent.CHANGE_EVENT);
             exctx.getInternalIOProcessor().addEvent(ev);
-        }
         */
         ctx.setLocal(getNamespacesKey(), null);
     }
 
     /**
-     * Get the {@link Node} the "src" attribute points to.
+     * Get the data the "src" attribute points to.
      *
-     * @return The node the "src" attribute points to.
+     * @return The data the "src" attribute points to.
      */
-    private Node getSrcNode() {
+    private Object getSrcData() {
         String resolvedSrc = src;
         if (pathResolver != null) {
             resolvedSrc = pathResolver.resolvePath(src);
         }
-        Document doc = null;
         try {
-            doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(resolvedSrc);
-        } catch (FactoryConfigurationError t) {
-            logError(t);
-        } catch (SAXException e) {
-            logError(e);
+            return ContentParser.DEFAULT_PARSER.parseResource(resolvedSrc);
         } catch (IOException e) {
             logError(e);
-        } catch (ParserConfigurationException e) {
-            logError(e);
-        }
-        if (doc == null) {
             return null;
         }
-        return doc.getDocumentElement();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/main/java/org/apache/commons/scxml2/model/Data.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Data.java b/src/main/java/org/apache/commons/scxml2/model/Data.java
index be5efd0..0771bf5 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Data.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Data.java
@@ -40,7 +40,7 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     private String id;
 
     /**
-     * The URL to get the XML data tree from.
+     * The URL to get the data from.
      */
     private String src;
 
@@ -50,12 +50,17 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     private String expr;
 
     /**
-     * The child XML data tree, parsed as a Node, cloned per execution
+     * The child XML data tree, parsed as a Node
      * instance.
      */
     private Node node;
 
     /**
+     * The parsed value for the child XML data tree or the external src (with early-binding), to be cloned before usage
+     */
+    private Object value;
+
+    /**
      * The current XML namespaces in the SCXML document for this action node,
      * preserved for deferred XPath evaluation. Easier than to scrape node
      * above, given the Builtin API.
@@ -63,16 +68,6 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     private Map<String, String> namespaces;
 
     /**
-     * Constructor.
-     */
-    public Data() {
-        this.id = null;
-        this.src = null;
-        this.expr = null;
-        this.node = null;
-    }
-
-    /**
      * Get the id.
      *
      * @return String An identifier.
@@ -91,7 +86,7 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     }
 
     /**
-     * Get the URL where the XML data tree resides.
+     * Get the URL for external data.
      *
      * @return String The URL.
      */
@@ -100,7 +95,7 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     }
 
     /**
-     * Set the URL where the XML data tree resides.
+     * Set the URL for external data.
      *
      * @param src The source URL.
      */
@@ -127,24 +122,46 @@ public class Data implements NamespacePrefixesHolder, Serializable {
     }
 
     /**
-     * Get the XML data tree.
+     * Get the child XML data tree.
      *
-     * @return Node The XML data tree, parsed as a <code>Node</code>.
+     * @return Node The child XML data tree, parsed as a standalone DocumentFragment <code>Node</code>.
      */
     public final Node getNode() {
         return node;
     }
 
     /**
-     * Set the XML data tree.
+     * Set the child XML data tree.
      *
-     * @param node The XML data tree, parsed as a <code>Node</code>.
+     * @param node The child XML data tree, parsed as a standalone DocumentFragment <code>Node</code>.
      */
     public final void setNode(final Node node) {
         this.node = node;
     }
 
     /**
+     * Get the parsed value for the child XML data tree or the external src (with early-binding), to be cloned before usage.
+     * @see #setValue(Object)
+     * @return The parsed Data value
+     */
+    public final Object getValue() {
+        return value;
+    }
+
+    /**
+     * Sets the parsed value for the child XML data tree or the external src (with early-binding), to be cloned before usage.
+     * @param value a serializable object:
+     * <ul>
+     *   <li>"Raw" JSON mapped object tree (array->ArrayList, object->LinkedHashMap based)</li>
+     *   <li>XML Node (equals {@link #getNode()})</li>
+     *   <li>space-normalized String</li>
+     * </ul>
+     */
+    public final void setValue(final Object value) {
+        this.value = value;
+    }
+
+    /**
      * Get the XML namespaces at this action node in the SCXML document.
      *
      * @return Returns the map of namespaces.

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/NamespacePrefixedXPathsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/NamespacePrefixedXPathsTest.java b/src/test/java/org/apache/commons/scxml2/NamespacePrefixedXPathsTest.java
deleted file mode 100644
index c0164b4..0000000
--- a/src/test/java/org/apache/commons/scxml2/NamespacePrefixedXPathsTest.java
+++ /dev/null
@@ -1,89 +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;
-
-import java.util.Set;
-
-import org.apache.commons.scxml2.model.EnterableState;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit tests for namespace prefixes in XPaths pointing bits in a &lt;data&gt;.
- */
-public class NamespacePrefixedXPathsTest {
-
-    /**
-     * Test the XPath evaluation
-     */
-    // JEXL
-    @Test
-    public void testNamespacePrefixedXPathsJexl() throws Exception {
-        SCXMLExecutor exec = SCXMLTestHelper.getExecutor("org/apache/commons/scxml2/env/jexl/datamodel-03.xml");
-        exec.go();
-        runtest(exec);
-    }
-
-    // Same test, since same documents (different expression languages)
-    private void runtest(SCXMLExecutor exec) throws Exception {
-        // must be in state "ten" at the onset
-        Set<EnterableState> currentStates = exec.getStatus().getStates();
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("ten", currentStates.iterator().next().getId());
-
-        // should move to "twenty"
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.ten");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("twenty", currentStates.iterator().next().getId());
-
-        // This is set while exiting "ten"
-        Double retval = (Double) exec.getGlobalContext().get("retval");
-        Assert.assertEquals(Double.valueOf("11"), retval);
-
-        // On to "thirty"
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.twenty");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("thirty", currentStates.iterator().next().getId());
-        exec = SCXMLTestHelper.testInstanceSerializability(exec);
-
-        // Tests XPath on SCXML actions, set while exiting "twenty"
-        String retvalstr = (String) exec.getGlobalContext().get("retval");
-        Assert.assertEquals("Equal to 20", retvalstr);
-
-        // and so on ...
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.thirty");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("forty", currentStates.iterator().next().getId());
-
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.forty");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("fifty", currentStates.iterator().next().getId());
-
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.fifty");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("sixty", (currentStates.iterator().
-            next()).getId());
-
-        currentStates = SCXMLTestHelper.fireEvent(exec, "done.state.sixty");
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("seventy", currentStates.iterator().next().getId());
-
-        // done
-        Assert.assertTrue(exec.getStatus().isFinal());
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-01.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-01.xml b/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-01.xml
new file mode 100644
index 0000000..4edc4df
--- /dev/null
+++ b/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-01.xml
@@ -0,0 +1,84 @@
+<?xml version="1.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.
+-->
+<!-- A fictitious state machine used by test cases.
+     Meant to illustrate the usage of SCXML <datamodel> element -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+       version="1.0"
+       datamodel="groovy"
+       initial="main">
+
+    <!-- Root or document datamodel -->
+    <datamodel>
+        <data id="docdata">{ "root" : { "foo" : { "bar" : "alpha" } } }</data>
+    </datamodel>
+
+    <state id="main">
+
+        <initial>
+            <transition target="ten"/>
+        </initial>
+
+        <!-- datamodel scoped to state "main" -->
+        <datamodel>
+            <!-- Degenerate usage, similar to the <var> element -->
+            <data id="mainvar" expr="0" />
+            <!-- Usage where the value is an JSON model -->
+            <data id="maindata">{ "root" : { "a" : { "b" : { "c" : "beta", "d" : 123, "e" : 456.789 } } } }</data>
+        </datamodel>
+
+        <state id="ten">
+            <onentry>
+                <assign location="mainvar" expr="10" />
+            </onentry>
+            <transition event="done.state.ten"
+             cond="mainvar eq 10 and maindata.root.a.b.c eq 'beta'"
+             target="twenty" />
+            <onexit>
+                <assign location="maindata.root.a.b.c" expr="'gamma'" />
+            </onexit>
+        </state>
+
+        <state id="twenty">
+            <onentry>
+                <assign location="mainvar" expr="20" />
+            </onentry>
+            <transition event="done.state.twenty"
+             cond="maindata.root.a.b.c eq 'gamma' and mainvar eq 20"
+             target="thirty" />
+            <onexit>
+                <assign location="docdata.root.foo"
+                        expr="maindata.root" />
+            </onexit>
+        </state>
+
+        <state id="thirty">
+            <!-- Arithmetic operations.
+                 Note that data "docdata"
+                 did not have data at 'root.foo.a.b.d' to begin with,
+                 the data model was manipulated by the <assign> above -->
+            <transition event="done.state.thirty"
+             cond="docdata.root.foo.a.b.d + docdata.root.foo.a.b.e eq 579.789"
+             target="forty" />
+        </state>
+
+        <final id="forty"/>
+
+    </state>
+
+</scxml>
+

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-05.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-05.xml b/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-05.xml
new file mode 100644
index 0000000..55f5b9e
--- /dev/null
+++ b/src/test/java/org/apache/commons/scxml2/env/groovy/datamodel-05.xml
@@ -0,0 +1,80 @@
+<?xml version="1.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.
+-->
+<!-- A fictitious state machine used by test cases. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+       version="1.0"
+       datamodel="groovy"
+       initial="start">
+
+    <datamodel>
+
+      <data id="airline">
+        {
+          "flight" :
+          {
+            "origin" : null,
+            "destination" : null,
+            "trip" : "round",
+            "class" : "economy",
+            "meal" : null,
+            "dates" :
+            [
+              {
+                "startdate" : "01/01/2009",
+                "enddate" : "01/05/2009"
+              },
+              {
+                "startdate" : "01/26/2009",
+                "enddate" : "01/31/2009"
+              }
+            ]
+          }
+        }
+      </data>
+
+      <data id="hotel">
+        {
+          "hotel" :
+          {
+            "stay" :
+            {
+              "delete" : "foo"
+            },
+            "adults" : 1,
+            "children" : 0,
+            "rooms" : 1,
+            "rate" : null
+          }
+        }
+      </data>
+
+    </datamodel>
+
+    <state id="start">
+        <onentry>
+            <log label="subtree copy - delete (should be foo)" expr="hotel.hotel.stay['delete']"/>
+            <assign location="hotel.hotel.stay" expr="airline.flight.dates[1]"/>
+            <log label="subtree copy - delete (should be null)" expr="hotel.hotel.stay['delete']"/>
+        </onentry>
+        <transition cond="hotel.hotel.stay.startdate eq '01/26/2009'" target="end" />
+    </state>
+
+    <final id="end"/>
+
+</scxml>
+

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
index 28d923e..2f8b403 100644
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
@@ -18,6 +18,7 @@
 package org.apache.commons.scxml2.env.javascript;
 
 import java.io.StringReader;
+import java.util.Map;
 
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
@@ -52,25 +53,25 @@ public class JSEvaluatorTest {
 
     private static final String BAD_EXPRESSION = ">";
     private static final String SCRIPT         = "<?xml version='1.0'?>" +
-                                                 "<scxml xmlns        = 'http://www.w3.org/2005/07/scxml' " +
-                                                        "xmlns:scxml  = 'http://commons.apache.org/scxml' " +
-                                                        "datamodel = 'ecmascript' " +
-                                                        "initial = 'start' "  +
-                                                        "version      = '1.0'>" +
-                                                  "<datamodel>"           +
-                                                  "<data id='forest'>"  +
-                                                   "<tree xmlns=''>"      +
-                                                   "<branch>"             +
-                                                   "<twig>leaf</twig>"    +
-                                                   "</branch>"            +
-                                                   "</tree>"              +
-                                                  "</data>"               +
-                                                  "</datamodel>"          +
-                                                  "<state id='start'>"              +
-                                                  "<transition target='end' />"     +
-                                                  "</state>"                        +
-                                                  "<state id='end' final='true' />" +
-                                                  "</scxml>";
+                                                 "<scxml xmlns = 'http://www.w3.org/2005/07/scxml'" +
+                                                 "       xmlns:scxml = 'http://commons.apache.org/scxml'" +
+                                                 "       datamodel = 'ecmascript'" +
+                                                 "       initial = 'start'"  +
+                                                 "       version = '1.0'>" +
+                                                 "  <datamodel>" +
+                                                 "    <data id='forest'>" +
+                                                 "      { \"tree\" :" +
+                                                 "        { \"branch\" :" +
+                                                 "          { \"twig\" : \"leaf\" }" +
+                                                 "        }" +
+                                                 "      }" +
+                                                 "    </data>" +
+                                                 "  </datamodel>" +
+                                                 "  <state id='start'>" +
+                                                 "    <transition target='end'/>" +
+                                                 "  </state>" +
+                                                 "  <state id='end' final='true'/>" +
+                                                 "</scxml>";
 
     private static final TestItem[] SIMPLE_EXPRESSIONS = {
             new TestItem("'FIB: ' + (1 + 1 + 2 + 3 + 5)",new String("FIB: 12")),
@@ -241,9 +242,9 @@ public class JSEvaluatorTest {
      */    
     @Test
     public void testDataModelExpressions() throws Exception {
-        Assert.assertEquals("Invalid result: " + "Data('string($forest/tree/branch/twig)')",
+        Assert.assertEquals("Invalid result: " + "forest.tree.branch.twig",
                      "leaf",
-                     evaluator.eval(context,"Data('string($forest/tree/branch/twig)')"));
+                     evaluator.eval(context,"forest.tree.branch.twig"));
     }
 
     /**
@@ -255,8 +256,8 @@ public class JSEvaluatorTest {
         Assert.assertNull(context.get("forestx"));
 
         try {
-            evaluator.eval(context,"Data(forestx,'string($forestx/tree/branch/twig)')");
-            Assert.fail          ("Evaluated invalid Data() expression: " + "Data('string($forestx/tree/branch/twig)')");
+            evaluator.eval(context,"forestx.tree.branch.twig");
+            Assert.fail          ("Evaluated invalid DataModel expression: " + "forestx.tree.branch.twig");
 
         } catch (SCXMLExpressionException x) {
             // expected, ignore
@@ -269,17 +270,11 @@ public class JSEvaluatorTest {
      */    
     @Test
     public void testDataModelLocations() throws Exception {
-            Assert.assertNotNull(context.get("forest"));
-            XPath  xpath = XPathFactory.newInstance().newXPath();
-            Node   node  = (Node)   context.get("forest");
-            Node   twig  = (Node)   xpath.evaluate("tree/branch/twig", node, XPathConstants.NODE);
-
-            Assert.assertTrue  ("Invalid result: " + "Data(forest,'$forest/tree/branch/twig')",
-                          evaluator.eval(context,"Data('$forest/tree/branch/twig')") instanceof Element);
+        Assert.assertTrue("Invalid result: forest instanceof Map",
+                evaluator.eval(context, "forest") instanceof Map);
 
-            Assert.assertSame ("Incorrect node returned: " + "Data('$forest/tree/branch/twig')",
-                         twig,
-                         evaluator.eval(context,"Data('$forest/tree/branch/twig')"));
+        Assert.assertTrue("Invalid result: forest.tree.branch.twig instanceof String",
+                evaluator.eval(context, "forest.tree.branch.twig") instanceof String);
     }
 
     /**
@@ -289,8 +284,8 @@ public class JSEvaluatorTest {
     @Test
     public void testInvalidDataModelLocations() throws Exception {
             Assert.assertNotNull(context.get("forest"));
-            Assert.assertNull("Invalid result: " + "Data('$forest/tree/branch/twigx')",
-                       evaluator.eval(context,"Data('$forest/tree/branch/twigx')"));
+            Assert.assertNull("Invalid result: " + "forest.tree.branch.twigx",
+                       evaluator.eval(context,"forest.tree.branch.twigx"));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-01.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-01.xml b/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-01.xml
new file mode 100644
index 0000000..3234099
--- /dev/null
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-01.xml
@@ -0,0 +1,84 @@
+<?xml version="1.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.
+-->
+<!-- A fictitious state machine used by test cases.
+     Meant to illustrate the usage of SCXML <datamodel> element -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+       version="1.0"
+       datamodel="ecmascript"
+       initial="main">
+
+    <!-- Root or document datamodel -->
+    <datamodel>
+        <data id="docdata">{ "root" : { "foo" : { "bar" : "alpha" } } }</data>
+    </datamodel>
+
+    <state id="main">
+
+        <initial>
+            <transition target="ten"/>
+        </initial>
+
+        <!-- datamodel scoped to state "main" -->
+        <datamodel>
+            <!-- Degenerate usage, similar to the <var> element -->
+            <data id="mainvar" expr="0" />
+            <!-- Usage where the value is an JSON model -->
+            <data id="maindata">{ "root" : { "a" : { "b" : { "c" : "beta", "d" : 123, "e" : 456.789 } } } }</data>
+        </datamodel>
+
+        <state id="ten">
+            <onentry>
+                <assign location="mainvar" expr="10" />
+            </onentry>
+            <transition event="done.state.ten"
+             cond="mainvar == 10 &amp;&amp; maindata.root.a.b.c == 'beta'"
+             target="twenty" />
+            <onexit>
+                <assign location="maindata.root.a.b.c" expr="'gamma'" />
+            </onexit>
+        </state>
+
+        <state id="twenty">
+            <onentry>
+                <assign location="mainvar" expr="20" />
+            </onentry>
+            <transition event="done.state.twenty"
+             cond="maindata.root.a.b.c == 'gamma' &amp;&amp; mainvar == 20"
+             target="thirty" />
+            <onexit>
+                <assign location="docdata.root.foo"
+                        expr="maindata.root" />
+            </onexit>
+        </state>
+
+        <state id="thirty">
+            <!-- Arithmetic operations.
+                 Note that data "docdata"
+                 did not have data at 'root.foo.a.b.d' to begin with,
+                 the data model was manipulated by the <assign> above -->
+            <transition event="done.state.thirty"
+             cond="docdata.root.foo.a.b.d + docdata.root.foo.a.b.e == 579.789"
+             target="forty" />
+        </state>
+
+        <final id="forty"/>
+
+    </state>
+
+</scxml>
+

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-05.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-05.xml b/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-05.xml
new file mode 100644
index 0000000..75817f0
--- /dev/null
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/datamodel-05.xml
@@ -0,0 +1,80 @@
+<?xml version="1.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.
+-->
+<!-- A fictitious state machine used by test cases. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+       version="1.0"
+       datamodel="ecmascript"
+       initial="start">
+
+    <datamodel>
+
+      <data id="airline">
+        {
+          "flight" :
+          {
+            "origin" : null,
+            "destination" : null,
+            "trip" : "round",
+            "class" : "economy",
+            "meal" : null,
+            "dates" :
+            [
+              {
+                "startdate" : "01/01/2009",
+                "enddate" : "01/05/2009"
+              },
+              {
+                "startdate" : "01/26/2009",
+                "enddate" : "01/31/2009"
+              }
+            ]
+          }
+        }
+      </data>
+
+      <data id="hotel">
+        {
+          "hotel" :
+          {
+            "stay" :
+            {
+              "delete" : "foo"
+            },
+            "adults" : 1,
+            "children" : 0,
+            "rooms" : 1,
+            "rate" : null
+          }
+        }
+      </data>
+
+    </datamodel>
+
+    <state id="start">
+        <onentry>
+            <log label="subtree copy - delete (should be foo)" expr="hotel.hotel.stay['delete']"/>
+            <assign location="hotel.hotel.stay" expr="airline.flight.dates[1]"/>
+            <log label="subtree copy - delete (should be null)" expr="hotel.hotel.stay['delete']"/>
+        </onentry>
+        <transition cond="hotel.hotel.stay.startdate == '01/26/2009'" target="end" />
+    </state>
+
+    <final id="end"/>
+
+</scxml>
+

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/javascript/example-01.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/example-01.xml b/src/test/java/org/apache/commons/scxml2/env/javascript/example-01.xml
index 5fbd7a7..72898d5 100644
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/example-01.xml
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/example-01.xml
@@ -27,16 +27,21 @@
 
   <datamodel>
     <data id='jungle'>
-      <animals xmlns=''>
-        <lion>
-          <name>Simba</name>
-          <age>12</age>
-        </lion>
-        <tiger>
-          <name>Sher Khan</name>
-          <age>13</age>
-        </tiger>
-      </animals>
+      {
+        "animals" :
+        {
+          "lion" :
+          {
+            "name" : "Simba",
+            "age" : 12
+          },
+          "tiger" :
+          {
+            "name" : "Sher Khan",
+            "age" : 13
+          }
+        }
+      }
     </data>
   </datamodel>
 
@@ -88,11 +93,11 @@
 
     <state id='javascript.datamodel'>
       <onentry>
-        <log expr='"Lion : " + Data("string(jungle/animals/lion/name)")  + "," + Data("string(jungle/animals/lion/age)")'  />
-        <log expr='"Tiger: " + Data("string(jungle/animals/tiger/name)") + "," + Data("string(jungle/animals/tiger/age)")' />
-        <assign location='Location("jungle/animals/lion/age")' expr='Data("jungle/animals/tiger/age")' type="replace"/>
-        <log expr='"Lion : " + Data("string(jungle/animals/lion/name)")  + "," + Data("string(jungle/animals/lion/age)")'  />
-        <log expr='"Tiger: " + Data("string(jungle/animals/tiger/name)") + "," + Data("string(jungle/animals/tiger/age)")' />
+        <log expr='"Lion : " + jungle.animals.lion.name  + "," + jungle.animals.lion.age'  />
+        <log expr='"Tiger: " + jungle.animals.tiger.name  + "," + jungle.animals.tiger.age'  />
+        <assign location='jungle.animals.lion.age' expr='jungle.animals.tiger.age'/>
+        <log expr='"Lion : " + jungle.animals.lion.name  + "," + jungle.animals.lion.age'  />
+        <log expr='"Tiger: " + jungle.animals.tiger.name  + "," + jungle.animals.tiger.age'  />
       </onentry>
       <transition target='javascript.functions.inline' />
     </state>
@@ -128,11 +133,11 @@
     <state id='javascript.functions.print'>
       <onentry>
         <log expr='function debug(msg)
-                        { println("** " + msg + " **");
+                        { print("** " + msg + " **");
                           return "ok"
                         }
 
-               debug("This is the Javascript println() function")' />
+               debug("This is the Javascript print() function")' />
       </onentry>
       <transition target='javascript.eventdatamap.example' />
     </state>

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/6af929eb/src/test/java/org/apache/commons/scxml2/env/jexl/datamodel-01.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/jexl/datamodel-01.xml b/src/test/java/org/apache/commons/scxml2/env/jexl/datamodel-01.xml
index d6b4e7c..5e87087 100644
--- a/src/test/java/org/apache/commons/scxml2/env/jexl/datamodel-01.xml
+++ b/src/test/java/org/apache/commons/scxml2/env/jexl/datamodel-01.xml
@@ -16,8 +16,7 @@
  * limitations under the License.
 -->
 <!-- A fictitious state machine used by test cases.
-     Meant to illustrate the usage of SCXML <datamodel> element
-     and the Commons SCXML Data() function -->
+     Meant to illustrate the usage of SCXML <datamodel> element -->
 <scxml xmlns="http://www.w3.org/2005/07/scxml"
        version="1.0"
        datamodel="jexl"
@@ -25,13 +24,7 @@
 
     <!-- Root or document datamodel -->
     <datamodel>
-        <data id="docdata">
-            <root xmlns="">
-                <foo>
-                    <bar>alpha</bar>
-                </foo>
-            </root>
-        </data>
+        <data id="docdata">{ "root" : { "foo" : { "bar" : "alpha" } } }</data>
     </datamodel>
 
     <state id="main">
@@ -44,37 +37,19 @@
         <datamodel>
             <!-- Degenerate usage, similar to the <var> element -->
             <data id="mainvar" expr="0" />
-            <!-- Usage where the value is an XML data tree -->
-            <data id="maindata">
-                <root xmlns="">
-                    <a>
-                        <b>
-                            <c>beta</c>
-                            <d>123</d>
-                            <e>456.789</e>
-                        </b>
-                    </a>
-                </root>
-            </data>
+            <!-- Usage where the value is an JSON model -->
+            <data id="maindata">{ "root" : { "a" : { "b" : { "c" : "beta", "d" : 123, "e" : 456.789 } } } }</data>
         </datamodel>
 
         <state id="ten">
             <onentry>
-                <!-- Assign Usage 1: location is previously defined
-                      <var> or degenerate <data> (as in this case) -->
                 <assign location="mainvar" expr="10" />
             </onentry>
-            <!-- Commons SCXML defines a Data() function to use in conjunction
-                 with the Commons JEXL expression language. The
-                 argument is the XPath expression to a node whose value is to be
-                 examined  -->
             <transition event="done.state.ten"
-             cond="mainvar eq 10 and Data('string($maindata/root/a/b/c)') eq 'beta'"
+             cond="mainvar eq 10 and maindata.root.a.b.c eq 'beta'"
              target="twenty" />
             <onexit>
-                <!-- Assign Usage 2: location must point to an existing
-                      node  -->
-                <assign location="Location('$maindata/root/a/b/c')" expr="'gamma'" />
+                <assign location="maindata.root.a.b.c" expr="'gamma'" />
             </onexit>
         </state>
 
@@ -83,24 +58,21 @@
                 <assign location="mainvar" expr="20" />
             </onentry>
             <transition event="done.state.twenty"
-             cond="Data('string(maindata/root/a/b/c)') eq 'gamma' and mainvar eq 20"
+             cond="maindata.root.a.b.c eq 'gamma' and mainvar eq 20"
              target="thirty" />
             <onexit>
-                <!-- Assign Usage 3: location points to an existing
-                      node, and expr points to an existing node.
-                      In this case, location adopts expr's child nodes.  -->
-                <assign location="Location('$docdata/root/foo')"
-                        expr="Data('$maindata/root/*')" />
+                <assign location="docdata.root.foo"
+                        expr="maindata.root" />
             </onexit>
         </state>
 
         <state id="thirty">
-            <!-- Arithmetic operations are possible with results from
-                 the Data() function. Note that data "docdata"
-                 did not have a node at 'root/foo/a/b/d' to begin with,
-                 the XML tree was manipulated by the <assign> above -->
+            <!-- Arithmetic operations.
+                 Note that data "docdata"
+                 did not have data at 'root.foo.a.b.d' to begin with,
+                 the data model was manipulated by the <assign> above -->
             <transition event="done.state.thirty"
-             cond="Data('number($docdata/root/foo/a/b/d)') + Data('number($docdata/root/foo/a/b/e)') eq 579.789"
+             cond="docdata.root.foo.a.b.d + docdata.root.foo.a.b.e eq 579.789"
              target="forty" />
         </state>