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 <assign> 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,
- * <assign location="Data(hotelbooking,'hotel/rooms')" expr="2" />
- * </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 <script> 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 <data>.
- */
-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 && 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' && 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>