diff --git a/src/main/java/com/dashjoin/jsonata/Jsonata.java b/src/main/java/com/dashjoin/jsonata/Jsonata.java index 5cc6a7e..8caae48 100644 --- a/src/main/java/com/dashjoin/jsonata/Jsonata.java +++ b/src/main/java/com/dashjoin/jsonata/Jsonata.java @@ -2184,9 +2184,20 @@ public static class JFunction implements JFunctionCallable, JFunctionSignatureVa Signature signature; Method method; Object methodInstance; + int numberOfArgs; public JFunction(JFunctionCallable function, String signature) { + this(null, function, signature); + } + + public JFunction(String functionName, JFunctionCallable function, String signature) { + this(functionName, function, signature, 0); + } + + public JFunction(String functionName, JFunctionCallable function, String signature, int numberOfArgs) { + this.functionName = functionName; this.function = function; + this.numberOfArgs = numberOfArgs; if (signature!=null) // use classname as default, gets overwritten once the function is registered this.signature = new Signature(signature, function.getClass().getName()); @@ -2231,7 +2242,7 @@ public Object validate(Object args, Object context) { } public int getNumberOfArgs() { - return method != null ? method.getParameterTypes().length : 0; + return method != null ? method.getParameterTypes().length : numberOfArgs; } } diff --git a/src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java b/src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java index 3005e06..e889936 100644 --- a/src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java +++ b/src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java @@ -58,6 +58,48 @@ public Object call(Object input, List args) throws Throwable { Assertions.assertEquals("abc", expression.evaluate(Map.of("a", "a", "b", "b", "c", "c"))); } + @Test + public void testFunctionWithInputData() { + JFunction addWithFactor = new JFunction("addWithFactor", (input, args) -> { + var inputMap = (Map)input; + String factor = inputMap.get("factor").toString(); + int factorInt = Integer.parseInt(factor); + return ((Integer) args.get(0) + (Integer) args.get(1)) * factorInt; + }, null); + + var expression = Jsonata.jsonata("$addWithFactor(1, 2)"); + expression.registerFunction(addWithFactor.functionName, addWithFactor); + Assertions.assertEquals(9, expression.evaluate(Map.of("factor", "3"))); + } + + @Test + public void testFunctionWithInputData2() { + JFunction addWithFactor = new JFunction("multiply", (input, args) -> { + Object first = args.get(0); + Object second; + if (args.size() > 1) { + second = args.get(1); + } else { + var inputMap = (Map)input; + String factor = inputMap.get("factor").toString(); + second = Integer.parseInt(factor); + } + return (Integer) first * (Integer) second; + }, null, 2); + + var expression = Jsonata.jsonata("$multiply(3) ~> $multiply(?, 2)"); + expression.registerFunction(addWithFactor.functionName, addWithFactor); + Assertions.assertEquals(18, expression.evaluate(Map.of("factor", "3"))); + } + + @Test + public void testCustomFunctionPipe() { + JFunction add = new JFunction("add", (input, args) -> (Integer) args.get(0) + (Integer) args.get(1), null, 2); + var expression = Jsonata.jsonata("$add(1, 2) ~> $add(?, 3)"); + expression.registerFunction(add.functionName, add); + Assertions.assertEquals(6, expression.evaluate(null)); + } + /** * Lambdas use no signature - in case of an error, a ClassCastException is thrown */