diff --git a/core/src/main/java/com/schibsted/spt/data/jslt/impl/BuiltinFunctions.java b/core/src/main/java/com/schibsted/spt/data/jslt/impl/BuiltinFunctions.java index b903cbe..68898d4 100644 --- a/core/src/main/java/com/schibsted/spt/data/jslt/impl/BuiltinFunctions.java +++ b/core/src/main/java/com/schibsted/spt/data/jslt/impl/BuiltinFunctions.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SimpleTimeZone; @@ -1291,15 +1292,42 @@ public JsonNode call(JsonNode input, JsonNode[] arguments) { public static class Min extends AbstractFunction { public Min() { - super("min", 2, 2); + super("min", 0, 1_000); } public JsonNode call(JsonNode input, JsonNode[] arguments) { - // this works because null is the smallest of all values - if (ComparisonOperator.compare(arguments[0], arguments[1], null) < 0) - return arguments[0]; - else - return arguments[1]; + if (null == arguments || arguments.length == 0) { + return NullNode.instance; + } + + JsonNode minNode = arguments[0]; + if (1 == arguments.length) { + if (!minNode.isArray()) { + return minNode; + } + JsonNode nodes = minNode; + if (nodes.isEmpty()) { + return NullNode.instance; + } + minNode = nodes.get(0); + if (1 == nodes.size()) { + return minNode; + } + Iterator it = nodes.elements(); + minNode = it.next(); + while (it.hasNext()) { + JsonNode node = it.next(); + minNode = ComparisonOperator.compare(minNode, node, null) < 0 ? minNode : node; + } + + return minNode; + } + + for (JsonNode node : arguments) { + minNode = ComparisonOperator.compare(minNode, node, null) < 0 ? minNode : node; + } + + return minNode; } } @@ -1307,16 +1335,42 @@ public JsonNode call(JsonNode input, JsonNode[] arguments) { public static class Max extends AbstractFunction { public Max() { - super("max", 2, 2); + super("max", 0, 1_000); } public JsonNode call(JsonNode input, JsonNode[] arguments) { - if (arguments[0].isNull() || arguments[1].isNull()) + if (null == arguments || arguments.length == 0) { return NullNode.instance; - else if (ComparisonOperator.compare(arguments[0], arguments[1], null) > 0) - return arguments[0]; - else - return arguments[1]; + } + + JsonNode maxNode = arguments[0]; + if (1 == arguments.length) { + if (!maxNode.isArray()) { + return maxNode; + } + JsonNode nodes = maxNode; + if (nodes.isEmpty()) { + return NullNode.instance; + } + maxNode = nodes.get(0); + if (1 == nodes.size()) { + return maxNode; + } + Iterator it = nodes.elements(); + maxNode = it.next(); + while (it.hasNext()) { + JsonNode node = it.next(); + maxNode = ComparisonOperator.compare(maxNode, node, null) > 0 ? maxNode : node; + } + + return maxNode; + } + + for (JsonNode node : arguments) { + maxNode = ComparisonOperator.compare(maxNode, node, null) > 0 ? maxNode : node; + } + + return maxNode; } } diff --git a/core/src/main/java/com/schibsted/spt/data/jslt/impl/ComparisonOperator.java b/core/src/main/java/com/schibsted/spt/data/jslt/impl/ComparisonOperator.java index 3c3d632..91ca682 100644 --- a/core/src/main/java/com/schibsted/spt/data/jslt/impl/ComparisonOperator.java +++ b/core/src/main/java/com/schibsted/spt/data/jslt/impl/ComparisonOperator.java @@ -40,7 +40,7 @@ public static double compare(JsonNode v1, JsonNode v2, Location location) { } else if (v1.isTextual() && v2.isTextual()) { String s1 = v1.asText(); String s2 = v2.asText(); - return (double) s1.compareTo(s2); + return s1.compareTo(s2); } else if (v1.isNull() || v2.isNull()) { // null is equal to itself, and considered the smallest of all diff --git a/core/src/test/resources/function-tests.json b/core/src/test/resources/function-tests.json index 83ffa7f..948ce96 100644 --- a/core/src/test/resources/function-tests.json +++ b/core/src/test/resources/function-tests.json @@ -1227,6 +1227,21 @@ "input" : "null", "output": "\"00000000-0000-0000-0000-000000000000\"" }, + { + "query": "min()", + "input" : "null", + "output": "null" + }, + { + "query": "min(null)", + "input" : "null", + "output": "null" + }, + { + "query": "min(1)", + "input" : "null", + "output": "1" + }, { "query": "min(1, 2)", "input" : "null", @@ -1247,6 +1262,41 @@ "input" : "null", "output": "null" }, + { + "query": "min(99)", + "input" : "null", + "output": "99" + }, + { + "query": "min([])", + "input" : "null", + "output": "null" + }, + { + "query": "min([99])", + "input" : "null", + "output": "99" + }, + { + "query": "min([-99, 37, -234])", + "input" : "null", + "output": "-234" + }, + { + "query": "max()", + "input" : "null", + "output": "null" + }, + { + "query": "max(null)", + "input" : "null", + "output": "null" + }, + { + "query": "max(1)", + "input" : "null", + "output": "1" + }, { "query": "max(1, 2)", "input" : "null", @@ -1265,8 +1315,28 @@ { "query": "max(null, 0)", "input" : "null", + "output": "0" + }, + { + "query": "max(99)", + "input" : "null", + "output": "99" + }, + { + "query": "max([])", + "input" : "null", "output": "null" }, + { + "query": "max([99])", + "input" : "null", + "output": "99" + }, + { + "query": "max([99, 37, -234])", + "input" : "null", + "output": "99" + }, { "query" : "hash-int(.)", "input" : "\"\"", diff --git a/functions.md b/functions.md index 3065ce0..1e0806c 100644 --- a/functions.md +++ b/functions.md @@ -70,30 +70,42 @@ fallback(.not_existing_key, .another_not_existing, 1) => 1 fallback(null, [], {}, "value") => "value" ``` -### _min(arg1, arg2) -> value_ +### _min(args) -> value_ -Returns the argument that compares as the smallest. If one argument is -`null` the result is `null`. +`args` can be `null`, 1 or more items of the same kind, such as numbers, characters or Strings. +It can even be an array of items of the same kind. + +Returns the lowest item, or `null`. +`null` is considered the lowest value, regardless of the other items. Examples: ``` -min(10, 1) -> 1 -min("a", "b") -> "a" -min(10, null) -> null +min(10, 1) -> 1 +min("a", "b") -> "a" +min(10, null) -> null +min(10) -> 10 +min([7]) -> 7 +max([5,6,7,8]) -> 5 ``` -### _max(arg1, arg2) -> value_ +### _max(args) -> value_ + +`args` can be `null`, 1 or more items of the same kind, such as numbers, characters or Strings. +It can even be an array of items of the same kind. -Returns the argument that compares as the largest. If one argument is -`null` the result is `null`. +Returns the largest item. +`null` is considered the lowest value, regardless of the other items. Examples: ``` -max(10, 1) -> 10 -max("a", "b") -> "b" -max(10, null) -> null +max(10, 1) -> 10 +max("a", "b") -> "b" +max(10, null) -> 10 +max(17) -> 17 +max([26]) -> 26 +max([1,2,3,4]) -> 4 ```