You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by wo...@apache.org on 2014/01/04 01:45:45 UTC
svn commit: r1555303 - in /commons/proper/scxml/trunk: ./
src/main/java/org/apache/commons/scxml2/env/groovy/
src/main/java/org/apache/commons/scxml2/env/jexl/
src/test/java/org/apache/commons/scxml2/env/groovy/
Author: woonsan
Date: Sat Jan 4 00:45:45 2014
New Revision: 1555303
URL: http://svn.apache.org/r1555303
Log:
SCXML-186: adding an optional groovy evaluator support
- evaluator operations
- effective context of the chaining of contexts
- SCXML built-in functions support by using closures
Added:
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBinding.java
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBuiltin.java
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/package.html
commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/
commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluatorTest.java
Modified:
commons/proper/scxml/trunk/pom.xml
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
Modified: commons/proper/scxml/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/pom.xml?rev=1555303&r1=1555302&r2=1555303&view=diff
==============================================================================
--- commons/proper/scxml/trunk/pom.xml (original)
+++ commons/proper/scxml/trunk/pom.xml Sat Jan 4 00:45:45 2014
@@ -168,6 +168,12 @@
<optional>true</optional>
</dependency>
<dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ <version>2.2.1</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.3.0</version>
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBinding.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBinding.java?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBinding.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBinding.java Sat Jan 4 00:45:45 2014
@@ -0,0 +1,103 @@
+/*
+ * 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.groovy;
+
+import groovy.lang.Binding;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.scxml2.Context;
+
+/**
+ * Wrapper class for the Groovy Binding class that extends the
+ * wrapped Binding to search the SCXML context for variables and predefined
+ * functions that do not exist in the wrapped Binding.
+ */
+public class GroovyBinding extends Binding {
+
+ private Context context;
+ private Binding binding;
+
+ /**
+ * Initialises the internal Bindings delegate and SCXML context.
+ * @param context SCXML Context to use for script variables.
+ * @param binding GroovyShell bindings for variables.
+ * @throws IllegalArgumentException Thrown if either <code>context</code>
+ * or <code>binding</code> is <code>null</code>.
+ */
+ public GroovyBinding(Context context, Binding binding) {
+ if (context == null) {
+ throw new IllegalArgumentException("Invalid SCXML context");
+ }
+
+ if (binding == null) {
+ throw new IllegalArgumentException("Invalid GroovyShell Binding");
+ }
+
+ this.context = context;
+ this.binding = binding;
+ }
+
+ @Override
+ public Object getVariable(String name) {
+ if (context.has(name)) {
+ return context.get(name);
+ }
+
+ return binding.getVariable(name);
+ }
+
+ @Override
+ public void setVariable(String name, Object value) {
+ if (context.has(name)) {
+ context.set(name, value);
+ } else if (binding.hasVariable(name)) {
+ binding.setVariable(name, value);
+ } else {
+ context.setLocal(name, value);
+ }
+ }
+
+ @Override
+ public boolean hasVariable(String name) {
+ if (context.has(name)) {
+ return true;
+ }
+
+ return binding.hasVariable(name);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public Map getVariables() {
+ Map<String, Object> variables = new LinkedHashMap<String, Object>(binding.getVariables());
+ variables.putAll(context.getVars());
+ return variables;
+ }
+
+ @Override
+ public Object getProperty(String property) {
+ return binding.getProperty(property);
+ }
+
+ @Override
+ public void setProperty(String property, Object newValue) {
+ binding.setProperty(property, newValue);
+ }
+
+}
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBuiltin.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBuiltin.java?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBuiltin.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyBuiltin.java Sat Jan 4 00:45:45 2014
@@ -0,0 +1,83 @@
+/*
+ * 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.groovy;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.scxml2.Builtin;
+import org.apache.commons.scxml2.model.TransitionTarget;
+
+/**
+ * Global Groovy namespace functor, implements Data() and In() operators.
+ * Cooperates with GroovyContext.
+ */
+public final class GroovyBuiltin {
+ /**
+ * The context currently in use for evaluation.
+ */
+ private final GroovyContext context;
+
+ /**
+ * Creates a new instance, wraps the context.
+ * @param ctxt the context in use
+ */
+ public GroovyBuiltin(final GroovyContext ctxt) {
+ context = ctxt;
+ }
+
+ /**
+ * Gets the ALL_NAMESPACES map from context.
+ * @return the ALL_NAMESPACES map
+ */
+ private Map<String, String> getNamespaces() {
+ return (Map<String, String>) context.get("_ALL_NAMESPACES");
+ }
+
+ /**
+ * Gets the ALL_STATES set from context.
+ * @return the ALL_STATES set
+ */
+ private Set<TransitionTarget> getAllStates() {
+ return (Set<TransitionTarget>) context.get("_ALL_STATES");
+ }
+
+ /**
+ * Implements the Data() predicate for SCXML documents ( see Builtin#data ).
+ * @param data the context node
+ * @param path the XPath expression
+ * @return the first node matching the path
+ */
+ public Object Data(final Object data, final String path) {
+ // first call maps delegates to dataNode(), subsequent ones to data()
+ if (context.isEvaluatingLocation()) {
+ context.setEvaluatingLocation(false);
+ return Builtin.dataNode(getNamespaces(), data, path);
+ } else {
+ return Builtin.data(getNamespaces(), data, path);
+ }
+ }
+
+ /**
+ * Implements the In() predicate for SCXML documents ( see Builtin#isMember )
+ * @param state The State ID to compare with
+ * @return Whether this State belongs to this Set
+ */
+ public boolean In(final String state) {
+ return Builtin.isMember(getAllStates(), state);
+ }
+}
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java Sat Jan 4 00:45:45 2014
@@ -0,0 +1,78 @@
+/*
+ * 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.groovy;
+
+import java.util.Map;
+
+import org.apache.commons.scxml2.Context;
+import org.apache.commons.scxml2.env.SimpleContext;
+
+/**
+ * Groovy Context implementation for Commons SCXML.
+ */
+public class GroovyContext extends SimpleContext {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Internal flag to indicate whether it is to evaluate a location
+ * that returns a Node within an XML data tree.
+ */
+ private boolean evaluatingLocation = false;
+
+ /**
+ * Constructor.
+ */
+ public GroovyContext() {
+ super();
+ }
+
+ /**
+ * Constructor with initial vars.
+ *
+ * @param initialVars The initial set of variables.
+ */
+ public GroovyContext(final Map<String, Object> initialVars) {
+ super(initialVars);
+ }
+
+ /**
+ * Constructor with parent context.
+ *
+ * @param parent The parent context.
+ */
+ public GroovyContext(final Context parent) {
+ super(parent);
+ }
+
+ /**
+ * Returns the internal flag to indicate whether it is to evaluate a location
+ * that returns a Node within an XML data tree.
+ */
+ public boolean isEvaluatingLocation() {
+ return evaluatingLocation;
+ }
+
+ /**
+ * Sets the internal flag to indicate whether it is to evaluate a location
+ * that returns a Node within an XML data tree.
+ */
+ public void setEvaluatingLocation(boolean evaluatingLocation) {
+ this.evaluatingLocation = evaluatingLocation;
+ }
+
+}
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java Sat Jan 4 00:45:45 2014
@@ -0,0 +1,265 @@
+/*
+ * 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.groovy;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+
+import java.io.Serializable;
+import java.util.AbstractMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.scxml2.Context;
+import org.apache.commons.scxml2.Evaluator;
+import org.apache.commons.scxml2.SCXMLExpressionException;
+import org.codehaus.groovy.runtime.MethodClosure;
+import org.w3c.dom.Node;
+
+/**
+ * Evaluator implementation enabling use of Groovy expressions in
+ * SCXML documents.
+ * <P>
+ * This implementation itself is thread-safe, so you can keep singleton for efficiency.
+ * </P>
+ */
+public class GroovyEvaluator implements Evaluator, Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 1L;
+
+ /** Error message if evaluation context is not a GroovyContext. */
+ private static final String ERR_CTX_TYPE = "Error evaluating Groovy "
+ + "expression, Context must be a org.apache.commons.scxml2.env.groovy.GroovyContext";
+
+ /** Constructor. */
+ public GroovyEvaluator() {
+ super();
+ }
+
+ /**
+ * Evaluate an expression.
+ *
+ * @param ctx variable context
+ * @param expr expression
+ * @return a result of the evaluation
+ * @throws SCXMLExpressionException For a malformed expression
+ * @see Evaluator#eval(Context, String)
+ */
+ public Object eval(final Context ctx, final String expr) throws SCXMLExpressionException {
+ if (expr == null) {
+ return null;
+ }
+
+ GroovyContext groovyCtx = null;
+
+ if (ctx instanceof GroovyContext) {
+ groovyCtx = (GroovyContext) ctx;
+ } else {
+ throw new SCXMLExpressionException(ERR_CTX_TYPE);
+ }
+
+ try {
+ final GroovyContext effective = getEffectiveContext(groovyCtx);
+ GroovyShell shell = createGroovyShell(effective);
+ return shell.evaluate(expr);
+ } catch (Exception e) {
+ throw new SCXMLExpressionException("eval('" + expr + "'):" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @see Evaluator#evalCond(Context, String)
+ */
+ public Boolean evalCond(final Context ctx, final String expr) throws SCXMLExpressionException {
+ if (expr == null) {
+ return null;
+ }
+
+ GroovyContext groovyCtx = null;
+
+ if (ctx instanceof GroovyContext) {
+ groovyCtx = (GroovyContext) ctx;
+ } else {
+ throw new SCXMLExpressionException(ERR_CTX_TYPE);
+ }
+
+ try {
+ final GroovyContext effective = getEffectiveContext(groovyCtx);
+ GroovyShell shell = createGroovyShell(effective);
+ return (Boolean) shell.evaluate(expr);
+ } catch (Exception e) {
+ throw new SCXMLExpressionException("evalCond('" + expr + "'):" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @see Evaluator#evalLocation(Context, String)
+ */
+ public Node evalLocation(final Context ctx, final String expr) throws SCXMLExpressionException {
+ if (expr == null) {
+ return null;
+ }
+
+ GroovyContext groovyCtx = null;
+
+ if (ctx instanceof GroovyContext) {
+ groovyCtx = (GroovyContext) ctx;
+ } else {
+ throw new SCXMLExpressionException(ERR_CTX_TYPE);
+ }
+
+ try {
+ final GroovyContext effective = getEffectiveContext(groovyCtx);
+ effective.setEvaluatingLocation(true);
+ GroovyShell shell = createGroovyShell(effective);
+ return (Node) shell.evaluate(expr);
+ } catch (Exception e) {
+ throw new SCXMLExpressionException("evalLocation('" + expr + "'):" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @see Evaluator#evalScript(Context, String)
+ */
+ public Object evalScript(final Context ctx, final String script) throws SCXMLExpressionException {
+ if (script == null) {
+ return null;
+ }
+
+ GroovyContext groovyCtx = null;
+
+ if (ctx instanceof GroovyContext) {
+ groovyCtx = (GroovyContext) ctx;
+ } else {
+ throw new SCXMLExpressionException(ERR_CTX_TYPE);
+ }
+
+ try {
+ final GroovyContext effective = getEffectiveContext(groovyCtx);
+ effective.setEvaluatingLocation(true);
+ GroovyShell shell = createGroovyShell(effective);
+ return shell.evaluate(script);
+ } catch (Exception e) {
+ throw new SCXMLExpressionException("evalScript('" + script + "'):" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Create a new child context.
+ *
+ * @param parent parent context
+ * @return new child context
+ * @see Evaluator#newContext(Context)
+ */
+ public Context newContext(final Context parent) {
+ return new GroovyContext(parent);
+ }
+
+ /**
+ * Create a GroovyShell instance.
+ * @param context
+ * @return
+ */
+ protected GroovyShell createGroovyShell(GroovyContext groovyContext) {
+ Binding binding = new Binding();
+ GroovyBuiltin builtin = new GroovyBuiltin(groovyContext);
+ MethodClosure dataClosure = new MethodClosure(builtin, "Data");
+ MethodClosure inClosure = new MethodClosure(builtin, "In");
+ binding.setProperty("Data", dataClosure);
+ binding.setProperty("In", inClosure);
+ GroovyBinding groovyBinding = new GroovyBinding(groovyContext, binding);
+ GroovyShell shell = new GroovyShell(groovyBinding);
+ return shell;
+ }
+
+ /**
+ * Create a new context which is the summation of contexts from the
+ * current state to document root, child has priority over parent
+ * in scoping rules.
+ *
+ * @param nodeCtx The GroovyContext for this state.
+ * @return The effective GroovyContext for the path leading up to
+ * document root.
+ */
+ private GroovyContext getEffectiveContext(final GroovyContext nodeCtx) {
+ return new GroovyContext(new EffectiveContextMap(nodeCtx));
+ }
+
+ /**
+ * The map that will back the effective context for the
+ * {@link GroovyEvaluator}. The effective context enables the chaining of
+ * {@link Context}s all the way from the current state node to the root.
+ *
+ */
+ private static final class EffectiveContextMap extends AbstractMap<String, Object> {
+
+ /** The {@link Context} for the current state. */
+ private final Context leaf;
+
+ /** Constructor. */
+ public EffectiveContextMap(final GroovyContext ctx) {
+ super();
+ this.leaf = ctx;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<Map.Entry<String, Object>> entrySet() {
+ Set<Map.Entry<String, Object>> entrySet = new HashSet<Map.Entry<String, Object>>();
+ Context current = leaf;
+ while (current != null) {
+ entrySet.addAll(current.getVars().entrySet());
+ current = current.getParent();
+ }
+ return entrySet;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object put(final String key, final Object value) {
+ Object old = leaf.get(key);
+ if (leaf.has(key)) {
+ leaf.set(key, value);
+ } else {
+ leaf.setLocal(key, value);
+ }
+ return old;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object get(final Object key) {
+ Context current = leaf;
+ while (current != null) {
+ if (current.getVars().containsKey(key)) {
+ return current.getVars().get(key);
+ }
+ current = current.getParent();
+ }
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/package.html
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/package.html?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/package.html (added)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/package.html Sat Jan 4 00:45:45 2014
@@ -0,0 +1,26 @@
+<html>
+<!--
+ * 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.
+-->
+<head>
+</head>
+<body>
+
+ <p>A collection of classes that allow Groovy to be used in expressions
+ within SCXML documents.</p>
+
+</body>
+</html>
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java?rev=1555303&r1=1555302&r2=1555303&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java Sat Jan 4 00:45:45 2014
@@ -46,7 +46,7 @@ public class JexlEvaluator implements Ev
/** Error message if evaluation context is not a JexlContext. */
private static final String ERR_CTX_TYPE = "Error evaluating JEXL "
- + "expression, Context must be a org.apache.commons.jexl2.JexlContext";
+ + "expression, Context must be a org.apache.commons.scxml2.env.jexl.JexlContext";
/** The internal JexlEngine instance to use. */
private transient volatile JexlEngine jexlEngine;
Added: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluatorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluatorTest.java?rev=1555303&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluatorTest.java (added)
+++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluatorTest.java Sat Jan 4 00:45:45 2014
@@ -0,0 +1,95 @@
+/*
+ * 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.groovy;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.scxml2.Context;
+import org.apache.commons.scxml2.Evaluator;
+import org.apache.commons.scxml2.SCXMLExpressionException;
+import org.apache.commons.scxml2.model.State;
+import org.apache.commons.scxml2.model.TransitionTarget;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GroovyEvaluatorTest {
+
+ private String BAD_EXPRESSION = ">";
+ private Context ctx;
+
+ @Before
+ public void before() {
+ ctx = new GroovyContext();
+ }
+
+ @Test
+ public void testEval() throws SCXMLExpressionException {
+ Evaluator eval = new GroovyEvaluator();
+ Assert.assertEquals(new Integer(2), eval.eval(ctx, "1 + 1"));
+ }
+
+ @Test
+ public void testPristine() throws SCXMLExpressionException {
+ Evaluator eval = new GroovyEvaluator();
+ Assert.assertTrue(eval.evalCond(ctx, "1 + 1 == 2"));
+ }
+
+ @Test
+ public void testBuiltInFunctions() throws SCXMLExpressionException {
+ Evaluator eval = new GroovyEvaluator();
+
+ Set<TransitionTarget> allStates = new HashSet<TransitionTarget>();
+ State state1 = new State();
+ state1.setId("state1");
+ allStates.add(state1);
+
+ ctx.setLocal("_ALL_STATES", allStates);
+
+ Assert.assertTrue(eval.evalCond(ctx, "In('state1')"));
+ }
+
+ @Test
+ public void testScript() throws SCXMLExpressionException {
+ Evaluator eval = new GroovyEvaluator();
+ ctx.set("x", 3);
+ ctx.set("y", 0);
+ String script =
+ "if ((x * 2) == 5) {" +
+ "y = 1;\n" +
+ "} else {\n" +
+ "y = 2;\n" +
+ "}";
+ Assert.assertEquals(2, eval.evalScript(ctx, script));
+ Assert.assertEquals(2, ctx.get("y"));
+ }
+
+ @Test
+ public void testErrorMessage() {
+ Evaluator eval = new GroovyEvaluator();
+ Assert.assertNotNull(eval);
+ try {
+ eval.eval(ctx, BAD_EXPRESSION);
+ Assert.fail("GroovyEvaluator should throw SCXMLExpressionException");
+ } catch (SCXMLExpressionException e) {
+ Assert.assertTrue("GroovyEvaluator: Incorrect error message",
+ e.getMessage().startsWith("eval('" + BAD_EXPRESSION + "'):"));
+ }
+ }
+
+}