From 2d27508207220beeef49b7de3ad064e204098614 Mon Sep 17 00:00:00 2001 From: "sanket.1" Date: Wed, 29 Mar 2023 14:38:29 +0530 Subject: [PATCH] Multiplication & Division functions --- README.md | 30 ++++++------- .../function/PathFunctionFactory.java | 8 ++-- .../internal/function/numeric/Divide.java | 23 ++++++++++ .../internal/function/numeric/Multiply.java | 15 +++++++ .../function/NumericPathFunctionTest.java | 42 +++++++++++++++++++ 5 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Divide.java create mode 100644 json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Multiply.java diff --git a/README.md b/README.md index 61193ae73..3f98b6386 100644 --- a/README.md +++ b/README.md @@ -85,20 +85,22 @@ Functions Functions can be invoked at the tail end of a path - the input to a function is the output of the path expression. The function output is dictated by the function itself. -| Function | Description | Output type | -|:----------|:-------------------------------------------------------------------------------------|:---------------------| -| min() | Provides the min value of an array of numbers | Double | -| max() | Provides the max value of an array of numbers | Double | -| avg() | Provides the average value of an array of numbers | Double | -| stddev() | Provides the standard deviation value of an array of numbers | Double | -| length() | Provides the length of an array | Integer | -| sum() | Provides the sum value of an array of numbers | Double | -| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set` | -| concat(X) | Provides a concatinated version of the path output with a new item | like input | -| append(X) | add an item to the json path output array | like input | -| first() | Provides the first item of an array | Depends on the array | -| last() | Provides the last item of an array | Depends on the array | -| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array | +| Function | Description | Output type | +|:----------------------------|:-------------------------------------------------------------------------------------|:---------------------| +| min() | Provides the min value of an array of numbers | Double | +| max() | Provides the max value of an array of numbers | Double | +| avg() | Provides the average value of an array of numbers | Double | +| stddev() | Provides the standard deviation value of an array of numbers | Double | +| length() | Provides the length of an array | Integer | +| sum() | Provides the sum value of an array of numbers | Double | +| mul() | Provides the multiplication value of an array of numbers | Double | +| div(numerator, denominator) | Provides the division value of parameters | Double | +| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set` | +| concat(X) | Provides a concatinated version of the path output with a new item | like input | +| append(X) | add an item to the json path output array | like input | +| first() | Provides the first item of an array | Depends on the array | +| last() | Provides the last item of an array | Depends on the array | +| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array | Filter Operators ----------------- diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java b/json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java index 3a31151f2..63b16a628 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java @@ -3,11 +3,7 @@ import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.internal.function.json.Append; import com.jayway.jsonpath.internal.function.json.KeySetFunction; -import com.jayway.jsonpath.internal.function.numeric.Average; -import com.jayway.jsonpath.internal.function.numeric.Max; -import com.jayway.jsonpath.internal.function.numeric.Min; -import com.jayway.jsonpath.internal.function.numeric.StandardDeviation; -import com.jayway.jsonpath.internal.function.numeric.Sum; +import com.jayway.jsonpath.internal.function.numeric.*; import com.jayway.jsonpath.internal.function.sequence.First; import com.jayway.jsonpath.internal.function.sequence.Index; import com.jayway.jsonpath.internal.function.sequence.Last; @@ -40,6 +36,8 @@ public class PathFunctionFactory { map.put("sum", Sum.class); map.put("min", Min.class); map.put("max", Max.class); + map.put("mul", Multiply.class); + map.put("div", Divide.class); // Text Functions map.put("concat", Concatenate.class); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Divide.java b/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Divide.java new file mode 100644 index 000000000..40a3ffce7 --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Divide.java @@ -0,0 +1,23 @@ +package com.jayway.jsonpath.internal.function.numeric; + +import com.jayway.jsonpath.JsonPathException; +import com.jayway.jsonpath.internal.EvaluationContext; +import com.jayway.jsonpath.internal.PathRef; +import com.jayway.jsonpath.internal.function.Parameter; +import com.jayway.jsonpath.internal.function.PathFunction; + +import java.util.List; + +public class Divide implements PathFunction { + @Override + public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List parameters) { + if (parameters != null && parameters.size() == 2) { + List numbers = Parameter.toList(Number.class, ctx, parameters); + if (numbers.get(1).doubleValue() == 0d) { + throw new JsonPathException("Arithmetic error: Divide by zero"); + } + return numbers.get(0).doubleValue()/numbers.get(1).doubleValue(); + } + throw new JsonPathException("Exactly 2 parameters are expected for divide operator"); + } +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Multiply.java b/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Multiply.java new file mode 100644 index 000000000..dbca0011e --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Multiply.java @@ -0,0 +1,15 @@ +package com.jayway.jsonpath.internal.function.numeric; + +public class Multiply extends AbstractAggregation { + private Double multiplication = 1d; + + @Override + protected void next(Number value) { + multiplication *= value.doubleValue(); + } + + @Override + protected Number getValue() { + return multiplication; + } +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java b/json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java index 54814091b..a3d196077 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java @@ -104,6 +104,48 @@ public void testStdDevOfDouble() { verifyMathFunction(conf, "$.numbers.stddev()", 2.8722813232690143d); } + @Test + public void testMultiplication() { + verifyMathFunction(conf, "$.numbers.mul()", 3628800d); + } + + @Test + public void testMultiplicationEmptyListNegative() { + try { + verifyMathFunction(conf, "$.empty.mul()", null); + } catch (JsonPathException e) { + assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array"); + } + } + + @Test + public void testMultiplicationParameter() { + verifyFunction(conf, "mul($.left, $.right)", "{\"left\": 3, \"right\": 4}",12d); + } + + @Test + public void testDivideNoParamsNegative() { + try { + verifyMathFunction(conf, "$.numbers.div()", null); + } catch (JsonPathException e) { + assertEquals(e.getMessage(), "Exactly 2 parameters are expected for divide operator"); + } + } + + @Test + public void testDivide() { + verifyFunction(conf, "div($.num, $.den)", "{\"num\": 1, \"den\": 2}", 0.5d); + } + + @Test + public void testDivideByZeroNegative() { + try { + verifyFunction(conf, "div($.num, $.den)", "{\"num\": 1, \"den\": 0}", 0.5d); + } catch (JsonPathException e){ + assertEquals(e.getMessage(), "Arithmetic error: Divide by zero"); + } + } + @Test public void testStddevOfEmptyListNegative() { try {