Skip to content

Commit c827f8e

Browse files
committed
Issue #11: Support of static functions with varargs
Validating vararg-functions allow dynamic parameter count and invoking vararg-functions uses the existing parameter-resolution which already supports varargs.
1 parent 13cf093 commit c827f8e

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

src/main/java/org/glassfish/expressly/Messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ error.property.notfound=Property ''{1}'' not found on {0}
5151
error.fnMapper.null=Expression uses functions, but no FunctionMapper was provided
5252
error.fnMapper.method=Function ''{0}'' not found
5353
error.fnMapper.paramcount=Function ''{0}'' specifies {1} params, but {2} were supplied
54+
error.fnMapper.minparamcount=Function ''{0}'' requires at least {1} params, but {2} were supplied
5455

5556
# **ExpressionImpl
5657
error.context.null=ELContext was null

src/main/java/org/glassfish/expressly/lang/ExpressionBuilder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,12 @@ public void visit(Node node) throws ELException {
240240

241241
int parameterCount = functionMethod.getParameterCount();
242242
int argumentCount = ((AstMethodArguments) node.jjtGetChild(0)).getParameterCount();
243-
if (argumentCount != parameterCount) {
243+
if(functionMethod.isVarArgs()) {
244+
// last param of the method is the vararg -> 0..n vararg-arguments allowed
245+
if (argumentCount < parameterCount - 1) {
246+
throw new ELException(MessageFactory.get("error.fnMapper.minparamcount", funcNode.getOutputName(), parameterCount - 1, argumentCount));
247+
}
248+
} else if (argumentCount != parameterCount) {
244249
throw new ELException(MessageFactory.get("error.fnMapper.paramcount", funcNode.getOutputName(), parameterCount, argumentCount));
245250
}
246251
} else if (node instanceof AstIdentifier && varMapper != null) {

src/main/java/org/glassfish/expressly/parser/AstFunction.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.glassfish.expressly.lang.EvaluationContext;
2424
import org.glassfish.expressly.util.MessageFactory;
25+
import org.glassfish.expressly.util.ReflectionUtil;
2526

2627
import jakarta.el.ELClass;
2728
import jakarta.el.ELException;
@@ -167,12 +168,11 @@ public Object getValue(EvaluationContext ctx) throws ELException {
167168
Class<?>[] paramTypes = functionMethod.getParameterTypes();
168169
Object[] params = ((AstMethodArguments) this.children[0]).getParameters(ctx);
169170
Object result = null;
170-
for (int i = 0; i < params.length; i++) {
171-
try {
172-
params[i] = ctx.convertToType(params[i], paramTypes[i]);
173-
} catch (ELException ele) {
174-
throw new ELException(MessageFactory.get("error.function", this.getOutputName()), ele);
175-
}
171+
try {
172+
params = ReflectionUtil.buildParameters(ctx, paramTypes, functionMethod.isVarArgs(), params);
173+
}
174+
catch(ELException ele) {
175+
throw new ELException(MessageFactory.get("error.function", this.getOutputName()), ele);
176176
}
177177

178178
try {

src/test/java/org/glassfish/el/test/ELProcessorTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626

2727
import jakarta.el.ELProcessor;
2828
import jakarta.el.ELManager;
29+
import jakarta.el.ELException;
2930
import jakarta.el.ExpressionFactory;
3031
import jakarta.el.MethodExpression;
3132
import jakarta.el.ELContext;
3233
import java.lang.reflect.Method;
34+
import java.util.Arrays;
3335

3436
public class ELProcessorTest {
3537

@@ -160,6 +162,55 @@ public void defineFuncTest() {
160162
}
161163
assertTrue(caught);
162164
}
165+
166+
@Test
167+
public void defineVarargFuncTest()
168+
{
169+
Class<?> c = MyBean.class;
170+
Method meth = null;
171+
Method meth2 = null;
172+
try {
173+
meth = c.getMethod("getSum", new Class<?>[] {int[].class});
174+
meth2 = c.getMethod("getSumOffset", new Class<?>[] {int.class, int[].class});
175+
} catch(Exception e) {
176+
System.out.printf("Exception: ", e);
177+
}
178+
try {
179+
elp.defineFunction("xx", "", meth);
180+
Integer sum = elp.eval("xx:getSum()");
181+
assertEquals(0, sum.intValue());
182+
sum = elp.eval("xx:getSum(10)");
183+
assertEquals(10, sum.intValue());
184+
sum = elp.eval("xx:getSum(10, 20)");
185+
assertEquals(30, sum.intValue());
186+
} catch(NoSuchMethodException ex) {
187+
188+
}
189+
190+
boolean caught = false;
191+
try {
192+
elp.defineFunction("xx", "", meth2);
193+
Integer sum = elp.eval("xx:getSumOffset()");
194+
assertEquals(0, sum.intValue());
195+
} catch (ELException ex) {
196+
caught = true;
197+
} catch (NoSuchMethodException ex) {
198+
199+
}
200+
assertTrue(caught);
201+
202+
try {
203+
elp.defineFunction("xx", "", meth2);
204+
Integer sum = elp.eval("xx:getSumOffset(10)");
205+
assertEquals(10, sum.intValue());
206+
sum = elp.eval("xx:getSumOffset(10, 20)");
207+
assertEquals(30, sum.intValue());
208+
sum = elp.eval("xx:getSumOffset(10, 20, 30)");
209+
assertEquals(60, sum.intValue());
210+
} catch(NoSuchMethodException ex) {
211+
212+
}
213+
}
163214
/*
164215
@Test
165216
public void testBean() {
@@ -200,6 +251,12 @@ public int getFoo(int i) {
200251
public static int getBar() {
201252
return 64;
202253
}
254+
public static int getSum(int... args) {
255+
return Arrays.stream(args).sum();
256+
}
257+
public static int getSumOffset(int offset, int... args) {
258+
return offset + getSum(args);
259+
}
203260
}
204261
}
205262

0 commit comments

Comments
 (0)