Author: woonsan Date: Fri Oct 18 22:40:50 2013 New Revision: 1533656 URL: http://svn.apache.org/r1533656 Log: SCXML-114: Upgrading JEXL to 2.1.1 - Applied Henri Biestro's patch with some small additional work (e.g, J6 generics, renaming, javadocs, unit test) - Many thanks to Henri Biestro!
Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java Modified: commons/proper/scxml/trunk/pom.xml commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlContext.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlContextTest.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlEvaluatorTest.java Modified: commons/proper/scxml/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/pom.xml?rev=1533656&r1=1533655&r2=1533656&view=diff ============================================================================== --- commons/proper/scxml/trunk/pom.xml (original) +++ commons/proper/scxml/trunk/pom.xml Fri Oct 18 22:40:50 2013 @@ -156,9 +156,9 @@ <optional>true</optional> </dependency> <dependency> - <groupId>commons-jexl</groupId> + <groupId>org.apache.commons</groupId> <artifactId>commons-jexl</artifactId> - <version>1.1</version> + <version>2.1.1</version> <optional>true</optional> </dependency> <dependency> Added: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java?rev=1533656&view=auto ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java (added) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java Fri Oct 18 22:40:50 2013 @@ -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.jexl; + +import java.util.Map; +import java.util.Set; + +import org.apache.commons.scxml2.Builtin; +import org.apache.commons.scxml2.model.TransitionTarget; + +/** + * Global JEXL namespace functor, implements Data() and In() operators. + * Cooperates with JexlContext. + */ +public final class JexlBuiltin { + /** + * The context currently in use for evaluation. + */ + private final JexlContext context; + + /** + * Creates a new instance, wraps the context. + * @param ctxt the context in use + */ + public JexlBuiltin(final JexlContext 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); + } +} Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlContext.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlContext.java?rev=1533656&r1=1533655&r2=1533656&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlContext.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlContext.java Fri Oct 18 22:40:50 2013 @@ -18,7 +18,6 @@ package org.apache.commons.scxml2.env.je import java.util.Map; -import org.apache.commons.scxml2.Builtin; import org.apache.commons.scxml2.Context; import org.apache.commons.scxml2.env.SimpleContext; @@ -27,17 +26,22 @@ import org.apache.commons.scxml2.env.Sim * */ public class JexlContext extends SimpleContext - implements org.apache.commons.jexl.JexlContext { + implements org.apache.commons.jexl2.JexlContext { /** Serial version UID. */ 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 JexlContext() { super(); - getVars().put("_builtin", new Builtin()); } /** @@ -47,7 +51,6 @@ public class JexlContext extends SimpleC */ public JexlContext(final Map<String, Object> initialVars) { super(initialVars); - getVars().put("_builtin", new Builtin()); } /** @@ -57,34 +60,22 @@ public class JexlContext extends SimpleC */ public JexlContext(final Context parent) { super(parent); - getVars().put("_builtin", new Builtin()); } /** - * Set the variables map. - * - * @param vars The new variables map. - * - * @see org.apache.commons.jexl.JexlContext#setVars(Map) - * @see org.apache.commons.scxml2.env.SimpleContext#setVars(Map) + * Returns the internal flag to indicate whether it is to evaluate a location + * that returns a Node within an XML data tree. */ - @Override - @SuppressWarnings("unchecked") - // Accomodate legacy signature org.apache.commons.jexl.JexlContext#setVars(Map) - public void setVars(final Map vars) { - super.setVars(vars); - getVars().put("_builtin", new Builtin()); + public boolean isEvaluatingLocation() { + return evaluatingLocation; } /** - * Clear this Context. - * - * @see org.apache.commons.scxml2.Context#reset() + * Sets the internal flag to indicate whether it is to evaluate a location + * that returns a Node within an XML data tree. */ - @Override - public void reset() { - super.reset(); - getVars().put("_builtin", new Builtin()); + public void setEvaluatingLocation(boolean evaluatingLocation) { + this.evaluatingLocation = evaluatingLocation; } } 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=1533656&r1=1533655&r2=1533656&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 Fri Oct 18 22:40:50 2013 @@ -18,15 +18,14 @@ package org.apache.commons.scxml2.env.je import java.io.Serializable; import java.util.AbstractMap; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; -import org.apache.commons.jexl.Expression; -import org.apache.commons.jexl.ExpressionFactory; -import org.apache.commons.jexl.Script; -import org.apache.commons.jexl.ScriptFactory; +import org.apache.commons.jexl2.Expression; +import org.apache.commons.jexl2.JexlEngine; +import org.apache.commons.jexl2.Script; import org.apache.commons.scxml2.Context; import org.apache.commons.scxml2.Evaluator; import org.apache.commons.scxml2.SCXMLExpressionException; @@ -44,12 +43,19 @@ 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.jexl.JexlContext"; + + "expression, Context must be a org.apache.commons.jexl2.JexlContext"; - /** Pattern for recognizing the SCXML In() special predicate. */ - private static Pattern inFct = Pattern.compile("In\\("); - /** Pattern for recognizing the Commons SCXML Data() builtin function. */ - private static Pattern dataFct = Pattern.compile("Data\\("); + /** The JexlEngine instance to use. */ + private static final transient JexlEngine jexlEngine; + static { + jexlEngine = new JexlEngine(); + Map<String, Object> top = new HashMap<String, Object>(); + // With null prefix, define top-level user defined functions. + // See javadoc of org.apache.commons.jexl2.JexlEngine#setFunctions(Map<String,Object> funcs) for detail. + top.put(null, JexlBuiltin.class); + jexlEngine.setFunctions(top); + jexlEngine.setCache(256); + } /** Constructor. */ public JexlEvaluator() { @@ -78,12 +84,9 @@ public class JexlEvaluator implements Ev } Expression exp = null; try { - String evalExpr = inFct.matcher(expr). - replaceAll("_builtin.isMember(_ALL_STATES, "); - evalExpr = dataFct.matcher(evalExpr). - replaceAll("_builtin.data(_ALL_NAMESPACES, "); - exp = ExpressionFactory.createExpression(evalExpr); - return exp.evaluate(getEffectiveContext(jexlCtx)); + final JexlContext effective = getEffectiveContext(jexlCtx); + exp = jexlEngine.createExpression(expr); + return exp.evaluate(effective); } catch (Exception e) { throw new SCXMLExpressionException("eval('" + expr + "'):" + e.getMessage(), e); @@ -106,13 +109,10 @@ public class JexlEvaluator implements Ev } Expression exp = null; try { - String evalExpr = inFct.matcher(expr). - replaceAll("_builtin.isMember(_ALL_STATES, "); - evalExpr = dataFct.matcher(evalExpr). - replaceAll("_builtin.data(_ALL_NAMESPACES, "); - exp = ExpressionFactory.createExpression(evalExpr); - return (Boolean) exp.evaluate(getEffectiveContext(jexlCtx)); - } catch (Exception e) {e.printStackTrace(); + final JexlContext effective = getEffectiveContext(jexlCtx); + exp = jexlEngine.createExpression(expr); + return (Boolean) exp.evaluate(effective); + } catch (Exception e) { throw new SCXMLExpressionException("evalCond('" + expr + "'):" + e.getMessage(), e); } @@ -134,14 +134,10 @@ public class JexlEvaluator implements Ev } Expression exp = null; try { - String evalExpr = inFct.matcher(expr). - replaceAll("_builtin.isMember(_ALL_STATES, "); - evalExpr = dataFct.matcher(evalExpr). - replaceFirst("_builtin.dataNode(_ALL_NAMESPACES, "); - evalExpr = dataFct.matcher(evalExpr). - replaceAll("_builtin.data(_ALL_NAMESPACES, "); - exp = ExpressionFactory.createExpression(evalExpr); - return (Node) exp.evaluate(getEffectiveContext(jexlCtx)); + final JexlContext effective = getEffectiveContext(jexlCtx); + effective.setEvaluatingLocation(true); + exp = jexlEngine.createExpression(expr); + return (Node) exp.evaluate(effective); } catch (Exception e) { throw new SCXMLExpressionException("evalLocation('" + expr + "'):" + e.getMessage(), e); @@ -151,7 +147,7 @@ public class JexlEvaluator implements Ev /** * @see Evaluator#evalScript(Context, String) */ - public Object evalScript(Context ctx, String script) + public Object evalScript(final Context ctx, final String script) throws SCXMLExpressionException { if (script == null) { return null; @@ -164,12 +160,10 @@ public class JexlEvaluator implements Ev } Script jexlScript = null; try { - String scriptStr = inFct.matcher(script). - replaceAll("_builtin.isMember(_ALL_STATES, "); - scriptStr = dataFct.matcher(scriptStr). - replaceAll("_builtin.data(_ALL_NAMESPACES, "); - jexlScript = ScriptFactory.createScript(scriptStr); - return jexlScript.execute(getEffectiveContext(jexlCtx)); + final JexlContext effective = getEffectiveContext(jexlCtx); + effective.setEvaluatingLocation(true); + jexlScript = jexlEngine.createScript(script); + return jexlScript.execute(effective); } catch (Exception e) { throw new SCXMLExpressionException("evalScript('" + script + "'):" + e.getMessage(), e); @@ -209,10 +203,10 @@ public class JexlEvaluator implements Ev private static final class EffectiveContextMap extends AbstractMap<String, Object> { /** The {@link Context} for the current state. */ - final Context leaf; + private final Context leaf; /** Constructor. */ - public EffectiveContextMap(JexlContext ctx) { + public EffectiveContextMap(final JexlContext ctx) { super(); this.leaf = ctx; } @@ -235,7 +229,7 @@ public class JexlEvaluator implements Ev * {@inheritDoc} */ @Override - public Object put(String key, Object value) { + public Object put(final String key, final Object value) { Object old = leaf.get(key); if (leaf.has(key)) { leaf.set(key, value); @@ -249,7 +243,7 @@ public class JexlEvaluator implements Ev * {@inheritDoc} */ @Override - public Object get(Object key) { + public Object get(final Object key) { Context current = leaf; while (current != null) { if (current.getVars().containsKey(key)) { Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java?rev=1533656&r1=1533655&r2=1533656&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/SCInstanceTest.java Fri Oct 18 22:40:50 2013 @@ -19,7 +19,7 @@ package org.apache.commons.scxml2; import java.util.HashSet; import java.util.Set; -import org.apache.commons.jexl.JexlContext; +import org.apache.commons.jexl2.JexlContext; import org.apache.commons.scxml2.env.SimpleContext; import org.apache.commons.scxml2.env.jexl.JexlEvaluator; import org.apache.commons.scxml2.model.History; Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlContextTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlContextTest.java?rev=1533656&r1=1533655&r2=1533656&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlContextTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlContextTest.java Fri Oct 18 22:40:50 2013 @@ -19,7 +19,6 @@ package org.apache.commons.scxml2.env.je import java.util.HashMap; import java.util.Map; -import org.apache.commons.scxml2.Builtin; import org.junit.Assert; import org.junit.Test; @@ -29,8 +28,6 @@ public class JexlContextTest { public void testNew() { JexlContext ctx = new JexlContext(); Assert.assertNotNull(ctx); - Assert.assertEquals(1, ctx.getVars().size()); - Assert.assertTrue(ctx.get("_builtin") instanceof Builtin); } @Test @@ -39,24 +36,19 @@ public class JexlContextTest { m.put("foo", "bar"); JexlContext ctx = new JexlContext(m); Assert.assertNotNull(ctx); - Assert.assertEquals(2, ctx.getVars().size()); - Assert.assertTrue(ctx.get("_builtin") instanceof Builtin); + Assert.assertEquals(1, ctx.getVars().size()); String fooValue = (String) ctx.get("foo"); Assert.assertEquals("bar", fooValue); } @Test public void testSetVars() { - JexlContext ctx = new JexlContext(); - Assert.assertNotNull(ctx); - Assert.assertEquals(1, ctx.getVars().size()); - Assert.assertTrue(ctx.get("_builtin") instanceof Builtin); Map<String, Object> m = new HashMap<String, Object>(); m.put("foo", "bar"); - ctx.setVars(m); - Assert.assertEquals(2, ctx.getVars().size()); + JexlContext ctx = new JexlContext(m); + Assert.assertNotNull(ctx); + Assert.assertEquals(1, ctx.getVars().size()); String fooValue = (String) ctx.get("foo"); - Assert.assertTrue(ctx.get("_builtin") instanceof Builtin); Assert.assertEquals("bar", fooValue); } Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlEvaluatorTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlEvaluatorTest.java?rev=1533656&r1=1533655&r2=1533656&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlEvaluatorTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/env/jexl/JexlEvaluatorTest.java Fri Oct 18 22:40:50 2013 @@ -30,10 +30,24 @@ public class JexlEvaluatorTest { @Test public void testPristine() throws SCXMLExpressionException { Evaluator eval = new JexlEvaluator(); - Assert.assertNotNull(eval); Assert.assertTrue(((Boolean) eval.eval(ctx, "1+1 eq 2")).booleanValue()); } - + + @Test + public void testScript() throws SCXMLExpressionException { + Evaluator eval = new JexlEvaluator(); + 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 JexlEvaluator();