You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2015/11/18 12:06:23 UTC
svn commit: r1714968 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl3/
main/java/org/apache/commons/jexl3/internal/
test/java/org/apache/commons/jexl3/
Author: henrib
Date: Wed Nov 18 11:06:23 2015
New Revision: 1714968
URL: http://svn.apache.org/viewvc?rev=1714968&view=rev
Log:
JEXL:
Added curry method on scripts
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java?rev=1714968&r1=1714967&r2=1714968&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java Wed Nov 18 11:06:23 2015
@@ -123,4 +123,13 @@ public interface JexlScript {
* @since 2.1
*/
Callable<Object> callable(JexlContext context, Object... args);
+
+ /**
+ * Curries this script, returning a script with bound arguments.
+ * <p>If this script does not declare parameters or if all of them are already bound,
+ * no error is generated and this script is returned.</p>
+ * @param args the arguments to bind
+ * @return the curried script or this script if no binding can occur
+ */
+ JexlScript curry(Object... args);
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java?rev=1714968&r1=1714967&r2=1714968&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java Wed Nov 18 11:06:23 2015
@@ -193,7 +193,7 @@ public final class Scope {
arguments[target.intValue()] = arg;
}
}
- return new Frame(this, arguments);
+ return new Frame(this, arguments, 0);
} else {
return null;
}
@@ -280,15 +280,19 @@ public final class Scope {
private final Scope scope;
/** The actual stack frame. */
private final Object[] stack;
+ /** Number of curried parameters. */
+ private int curried = 0;
/**
* Creates a new frame.
* @param s the scope
* @param r the stack frame
+ * @param c the number of curried parameters
*/
- public Frame(Scope s, Object[] r) {
+ public Frame(Scope s, Object[] r, int c) {
scope = s;
stack = r;
+ curried = c;
}
/**
@@ -342,8 +346,9 @@ public final class Scope {
public Frame assign(Object... values) {
if (stack != null && values != null && values.length > 0) {
Object[] copy = stack.clone();
- System.arraycopy(values, 0, copy, 0, Math.min(copy.length, values.length));
- return new Frame(scope, copy);
+ int ncopy = Math.min(copy.length - curried, values.length);
+ System.arraycopy(values, 0, copy, curried, ncopy);
+ return new Frame(scope, copy, curried + ncopy);
}
return this;
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java?rev=1714968&r1=1714967&r2=1714968&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java Wed Nov 18 11:06:23 2015
@@ -22,6 +22,7 @@ import org.apache.commons.jexl3.JexlScri
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.parser.ASTJexlScript;
+import org.apache.commons.jexl3.parser.JexlNode;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -79,15 +80,23 @@ public class Script implements JexlScrip
}
}
- @Override
- public Object evaluate(JexlContext context) {
- if (script.jjtGetNumChildren() < 1) {
- return null;
- }
- checkCacheVersion();
- Scope.Frame frame = script.createFrame((Object[]) null);
- Interpreter interpreter = jexl.createInterpreter(context, frame);
- return interpreter.interpret(script.jjtGetChild(0));
+ /**
+ * Creates this script frame for evaluation.
+ * @param args the arguments to bind to parameters
+ * @return the frame (may be null)
+ */
+ protected Scope.Frame createFrame(Object[] args) {
+ return script.createFrame(args);
+ }
+
+ /**
+ * Creates this script interpreter.
+ * @param context the context
+ * @param frame the calling frame
+ * @return the interpreter
+ */
+ protected Interpreter createInterpreter(JexlContext context, Scope.Frame frame) {
+ return jexl.createInterpreter(context, frame);
}
/**
@@ -167,10 +176,24 @@ public class Script implements JexlScrip
* {@inheritDoc}
*/
@Override
+ public Object evaluate(JexlContext context) {
+ if (script.jjtGetNumChildren() < 1) {
+ return null;
+ }
+ checkCacheVersion();
+ Scope.Frame frame = createFrame((Object[]) null);
+ Interpreter interpreter = createInterpreter(context, frame);
+ return interpreter.interpret(script.jjtGetChild(0));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public Object execute(JexlContext context) {
checkCacheVersion();
- Scope.Frame frame = script.createFrame((Object[]) null);
- Interpreter interpreter = jexl.createInterpreter(context, frame);
+ Scope.Frame frame = createFrame((Object[]) null);
+ Interpreter interpreter = createInterpreter(context, frame);
return interpreter.interpret(script);
}
@@ -180,12 +203,78 @@ public class Script implements JexlScrip
@Override
public Object execute(JexlContext context, Object... args) {
checkCacheVersion();
- Scope.Frame frame = script.createFrame(args != null && args.length > 0 ? args : null);
- Interpreter interpreter = jexl.createInterpreter(context, frame);
+ Scope.Frame frame = createFrame(args != null && args.length > 0 ? args : null);
+ Interpreter interpreter = createInterpreter(context, frame);
return interpreter.interpret(script);
}
/**
+ * A script whose parameters are (partially) bound.
+ */
+ public static class Curried extends Script {
+ /** The evaluation frame. */
+ private final Scope.Frame frame;
+
+ /**
+ * Creates a curried version of this script.
+ * @param base the base script
+ * @param args the arguments
+ */
+ protected Curried(Script base, Object[] args) {
+ super(base.jexl, base.source, base.script);
+ Scope.Frame sf = (base instanceof Curried) ? ((Curried) base).frame : null;
+ if (sf != null) {
+ frame = sf.assign(args);
+ } else {
+ frame = script.createFrame(args);
+ }
+ }
+
+ @Override
+ protected Scope.Frame createFrame(Object[] args) {
+ return frame != null? frame.assign(args) : super.createFrame(args);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public Object execute(JexlContext context) {
+ return execute(context, (Object[])null);
+ }
+
+ @Override
+ public Object execute(JexlContext context, Object... args) {
+ Scope.Frame callFrame = null;
+ if (frame != null) {
+ callFrame = frame.assign(args);
+ }
+ Interpreter interpreter = jexl.createInterpreter(context, callFrame);
+ JexlNode block = script.jjtGetChild(script.jjtGetNumChildren() - 1);
+ return interpreter.interpret(block);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public JexlScript curry(Object... args) {
+ String[] parms = script.getParameters();
+ if (parms == null || parms.length == 0) {
+ return this;
+ }
+ return new Curried(this, args);
+ }
+
+ /**
* Gets this script parameters.
* @return the parameters or null
* @since 3.0
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java?rev=1714968&r1=1714967&r2=1714968&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java Wed Nov 18 11:06:23 2015
@@ -345,6 +345,10 @@ public class ArithmeticOperatorTest exte
public Object arraySet(Date date, String identifier, Object value) throws Exception {
return setDateValue(date, identifier, value);
}
+
+ public Date now() {
+ return new Date(System.currentTimeMillis());
+ }
}
public static class DateContext extends MapContext {
@@ -413,6 +417,14 @@ public class ArithmeticOperatorTest exte
jc.setLocale(Locale.FRANCE);
s0 = expr1.execute(jc, x0, "EEE dd MMM yyyy");
Assert.assertEquals("mer. 20 ao\u00fbt 1969", s0);
+
+ expr1 = jexl.createScript("format(now(), y)", "y");
+ Object n0 = expr1.execute(jc, y0);
+ Assert.assertNotNull(n0);
+ expr1 = jexl.createScript("now().format(y)", "y");
+ Object n1 = expr1.execute(jc, y0);
+ Assert.assertNotNull(n0);
+ Assert.assertEquals(n0, n1);
}
@Test
@@ -444,5 +456,11 @@ public class ArithmeticOperatorTest exte
expr1.evaluate(jc, strw, expr0, 1, 3);
strws = strw.toString();
Assert.assertEquals("6", strws);
+
+ expr0 = jxlt.createTemplate("${now().format(y)}", "y");
+ strw = new StringWriter();
+ expr0.evaluate(jc, strw, y0);
+ strws = strw.toString();
+ Assert.assertNotNull(strws);
}
}
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java?rev=1714968&r1=1714967&r2=1714968&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java Wed Nov 18 11:06:23 2015
@@ -239,4 +239,43 @@ public class LambdaTest extends JexlTest
result = script.execute(null, 42);
Assert.assertEquals(42, result);
}
+
+ @Test
+ public void testCurry1() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlScript script;
+ Object result;
+
+ JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
+ script = base.curry(5);
+ script = script.curry(15);
+ script = script.curry(22);
+ result = script.execute(null);
+ Assert.assertEquals(42, result);
+ }
+
+ @Test
+ public void testCurry2() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlScript script;
+ Object result;
+
+ JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
+ script = base.curry(5, 15);
+ script = script.curry(22);
+ result = script.execute(null);
+ Assert.assertEquals(42, result);
+ }
+
+ @Test
+ public void testCurry3() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlScript script;
+ Object result;
+
+ JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
+ script = base.curry(5, 15);
+ result = script.execute(null, 22);
+ Assert.assertEquals(42, result);
+ }
}