This is an automated email from the ASF dual-hosted git repository.

tzimanyi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new eba7762afc [kie-issues#1841] Date and time related functions as non 
literal not permitted (#6395)
eba7762afc is described below

commit eba7762afc3d2b8d02be32eb4d5eefee355e5372
Author: Yeser Amer <[email protected]>
AuthorDate: Thu Jul 17 14:14:32 2025 +0200

    [kie-issues#1841] Date and time related functions as non literal not 
permitted (#6395)
---
 .../dmn/feel/runtime/functions/RangeFunction.java  |  45 ++-
 .../feel/runtime/functions/RangeFunctionTest.java  | 318 ++++++++-------------
 2 files changed, 151 insertions(+), 212 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RangeFunction.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RangeFunction.java
index 25b39ee75b..45e8ca2c13 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RangeFunction.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RangeFunction.java
@@ -27,10 +27,9 @@ import java.time.OffsetDateTime;
 import java.time.OffsetTime;
 import java.time.ZonedDateTime;
 import java.time.chrono.ChronoPeriod;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.function.Predicate;
 
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -61,13 +60,16 @@ public class RangeFunction extends BaseFEELFunction {
     private static EvaluationContext STUBBED;
     private static final Range DEFAULT_VALUE = new 
RangeImpl(Range.RangeBoundary.OPEN, BigDecimal.ZERO, BigDecimal.ZERO, 
Range.RangeBoundary.OPEN);
 
-    private static final List<Predicate<BaseNode>> ALLOWED_NODES = 
Arrays.asList(baseNode -> baseNode instanceof NullNode,
-            baseNode -> baseNode instanceof NumberNode,
-            baseNode -> baseNode instanceof StringNode,
-            baseNode -> baseNode instanceof AtLiteralNode,
-            baseNode -> baseNode instanceof FunctionInvocationNode);
+    private static final Set<String> ALLOWED_FUNCTIONS = Set.of("date", 
"time", "date and time", "duration");
 
-    private static final List<Predicate<Object>> ALLOWED_TYPES = Arrays.asList(
+    private static final Set<Predicate<BaseNode>> ALLOWED_NODES = Set.of(
+            AtLiteralNode.class::isInstance,
+            NumberNode.class::isInstance,
+            NullNode.class::isInstance,
+            RangeFunction::isAllowedFunctionInvocationNode,
+            StringNode.class::isInstance);
+
+    private static final Set<Predicate<Object>> ALLOWED_TYPES = Set.of(
             ChronoPeriod.class::isInstance,
             Duration.class::isInstance,
             LocalDate.class::isInstance,
@@ -170,6 +172,24 @@ public class RangeFunction extends BaseFEELFunction {
         return ALLOWED_TYPES.stream().anyMatch(objectPredicate -> 
objectPredicate.test(value));
     }
 
+    /**
+    * Checks if the function invocation node is allowed as a range endpoint.
+     * From DMN 1.6 specification:
+     * 67. range endpoint = numeric literal | string literal | date time 
literal
+     * 60. date time literal = at literal | function invocation
+     * In rule 60 ("date time literal"), for the "function invocation" 
alternative,
+     * the only permitted functions are the
+     * builtins date, time, date and time, and duration.
+     *
+     * @param baseNode the base node to check
+     * @return true if the function invocation node is allowed, false otherwise
+     */
+    static boolean isAllowedFunctionInvocationNode(BaseNode baseNode) {
+        return baseNode instanceof FunctionInvocationNode 
functionInvocationNode &&
+                
ALLOWED_FUNCTIONS.contains(functionInvocationNode.getName().getText()) &&
+                
functionInvocationNode.getParams().getElements().stream().noneMatch(FunctionInvocationNode.class::isInstance);
+    }
+
     /**
      * @param leftObject
      * @param rightObject
@@ -190,13 +210,13 @@ public class RangeFunction extends BaseFEELFunction {
     /**
      * @param leftValue
      * @param rightValue
-     * @return It checks if the leftValueis lower or equals to rightValue, 
false otherwise. If one of the endpoints is null,
+     * @return It checks if the leftValue is lower or equals to rightValue, 
false otherwise. If one of the endpoints is null,
      * or undefined, the endpoint range is considered as an ascending interval.
      */
     @SuppressWarnings("unchecked")
     protected boolean nodesValuesRangeAreAscending(Object leftValue, Object 
rightValue) {
-        boolean atLeastOneEndpointIsNullOrUndefined = leftValue == null || 
rightValue == null;
-        return atLeastOneEndpointIsNullOrUndefined ||
+        boolean atLeastOneEndpointIsNull = leftValue == null || rightValue == 
null;
+        return atLeastOneEndpointIsNull ||
                 ((Comparable<Object>) leftValue).compareTo(rightValue) <= 0;
     }
 
@@ -212,8 +232,7 @@ public class RangeFunction extends BaseFEELFunction {
         FEEL_1_1Parser parser = FEELParser.parse(null, input, 
Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList(), 
Collections.emptyList(), null);
         ParseTree tree = parser.expression();
         ASTBuilderVisitor v = new ASTBuilderVisitor(Collections.emptyMap(), 
null);
-        BaseNode expr = v.visit(tree);
-        return expr;
+        return v.visit(tree);
     }
 
     private EvaluationContext getStubbed() {
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/RangeFunctionTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/RangeFunctionTest.java
index f9de3acd92..ae875523b0 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/RangeFunctionTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/RangeFunctionTest.java
@@ -221,14 +221,16 @@ class RangeFunctionTest {
 
     @Test
     void invoke_WithOneFunctionNode() {
-        String from = "[number(\"1\", \",\", \".\")\"..2]";
+        String from = "[duration(\"P1D\")..@\"P2D\"]";
         FunctionTestUtil.assertResult(rangeFunction.invoke(from),
-                                      new 
RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.ONE, BigDecimal.valueOf(2)
+                                      new 
RangeImpl(Range.RangeBoundary.CLOSED, Duration.parse("PT24H"), 
Duration.parse("PT48H")
                                               , Range.RangeBoundary.CLOSED),
                                       from);
-        from = "[\"a\"..lower case(\"Z\")]";
+        from = "[@\"1970-01-01T00:00:00\"..date and 
time(\"1970-01-02T00:00:00\")]";
         FunctionTestUtil.assertResult(rangeFunction.invoke(from),
-                                      new 
RangeImpl(Range.RangeBoundary.CLOSED, "a", "z", Range.RangeBoundary.CLOSED),
+                                      new RangeImpl(Range.RangeBoundary.CLOSED,
+                                              LocalDateTime.of(1970, 1, 1, 0, 
0),
+                                              LocalDateTime.of(1970, 1, 2, 0, 
0), Range.RangeBoundary.CLOSED),
                                       from);
     }
 
@@ -254,7 +256,9 @@ class RangeFunctionTest {
         assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isTrue();
         node = getAtLiteralNode();
         assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isTrue();
-        node = getFunctionInvocationNodeA();
+        node = getFunctionInvocationNodeA("duration(\"P2DT20H14M\")");
+        assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isTrue();
+        node = getFunctionInvocationNodeA("date(\"1982-04-04\")");
         assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isTrue();
     }
 
@@ -266,6 +270,12 @@ class RangeFunctionTest {
         assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isFalse();
         node = rangeFunction.getNullNode();
         assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.CLOSED)).withFailMessage(node.getText()).isFalse();
+        node = getFunctionInvocationNodeA("string(\"\")");
+        assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isFalse();
+        node = getFunctionInvocationNodeA("duration(string(\"P1D\"))");
+        assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isFalse();
+        node = getFunctionInvocationNodeA("date(string(\"1982-04-04\"))");
+        assertThat(rangeFunction.nodeIsAllowed(node, 
Range.RangeBoundary.OPEN)).withFailMessage(node.getText()).isFalse();
     }
 
     @Test
@@ -456,7 +466,7 @@ class RangeFunctionTest {
     void evaluateWithValidFunctionInvocationNode() {
         Object[][] data = validFunctionInvocationNodeData();
         Arrays.stream(data).forEach(objects -> {
-            String expression = String.format("[%1$s..%1$s]", objects[0]);
+            String expression = String.format("[%1$s..%2$s]", objects[0], 
objects[1]);
             FEELFnResult<Range> retrieved = rangeFunction.invoke(expression);
             assertThat(retrieved.isRight())
                     .withFailMessage(() -> String.format("Expected 
'retrieved.isRight()' from, %s", expression))
@@ -468,7 +478,9 @@ class RangeFunctionTest {
     void evaluateWithInvalidFunctionInvocationNode() {
         Object[][] data = invalidFunctionInvocationNodeData();
         Arrays.stream(data).forEach(objects -> {
-            String expression = String.format("[%1$s..%1$s]", objects[0]);
+            Object firstEndPoint = objects[0];
+            Object secondEndPoint = objects.length == 2 ? objects[1] : 
objects[0];
+            String expression = String.format("[%1$s..%2$s]", firstEndPoint, 
secondEndPoint);
             FEELFnResult<Range> retrieved = rangeFunction.invoke(expression);
             assertThat(retrieved.isLeft())
                     .withFailMessage(() -> String.format("Expected 
'retrieved.isLeft()' from, %s", expression))
@@ -526,208 +538,116 @@ class RangeFunctionTest {
         return (AtLiteralNode) rangeFunction.parse("@\"2019-01-01\"");
     }
 
-    private FunctionInvocationNode getFunctionInvocationNodeA() {
-        return (FunctionInvocationNode) 
rangeFunction.parse("duration(\"P2DT20H14M\")");
+    private FunctionInvocationNode getFunctionInvocationNodeA(String input) {
+        return (FunctionInvocationNode) rangeFunction.parse(input);
     }
 
-    // 10.3.2.7 Endpoints can be either a literal or a qualified name of the 
following types: number, string, date,
-    // time, date and
-    //time, or duration.
+    // 10.3.2.7 Endpoints can be either a literal or a qualified name of the 
following types:
+    // number, string, date time, date and time, or duration.
     private static Object[][] validFunctionInvocationNodeData() {
-        // Subset of FEELFunctionsTest.data
         return new Object[][]{
-                // constants
-                {"string(1.1)", "1.1"},
-                {"replace( \"  foo   bar zed  \", 
\"^(\\s)+|(\\s)+$|\\s+(?=\\s)\", \"\" )", "foo bar zed"},
-                {"string(null)", null},
-                {"string(date(\"2016-08-14\"))", "2016-08-14"},
-                {"string(\"Happy %.0fth birthday, Mr %s!\", 38, \"Doe\")", 
"Happy 38th birthday, Mr Doe!"},
-                {"number(null, \",\", \".\")", null},
-                {"number(\"1,000.05\", \",\", \".\")", new 
BigDecimal("1000.05")},
-                {"number(\"1.000,05\", \".\", \",\")", new 
BigDecimal("1000.05")},
-                {"number(\"1000,05\", null, \",\")", new 
BigDecimal("1000.05")},
-                {"number(\"1,000.05e+12\", \",\", \".\")", new 
BigDecimal("1000.05e+12")},
-                {"number(\"1.000,05e+12\", \".\", \",\")", new 
BigDecimal("1000.05e+12")},
-                {"number(\"1000,05e+12\", null, \",\")", new 
BigDecimal("1000.05e+12")},
-                {"substring(\"foobar\", 3)", "obar"},
-                {"substring(\"foobar\", 3, 3)", "oba"},
-                {"substring(\"foobar\", -2, 1)", "a"},
-                {"substring(\"foobar\", -2, 5)", "ar"},
-                {"substring(\"foobar\", 15, 5)", null},
-                {"string length(\"foobar\")", BigDecimal.valueOf(6)},
-                {"string length(null)", null},
-                {"upper case(\"aBc4\")", "ABC4"},
-                {"upper case(null)", null},
-                {"lower case(\"aBc4\")", "abc4"},
-                {"lower case(null)", null},
-                {"substring before( \"foobar\", \"bar\")", "foo"},
-                {"substring before( \"foobar\", \"xyz\")", ""},
-                {"substring before( \"foobar\", \"foo\")", ""},
-                {"substring after( \"foobar\", \"foo\")", "bar"},
-                {"substring after( \"foobar\", \"xyz\")", ""},
-                {"substring after( \"foobar\", \"bar\")", ""},
-                {"replace(\"banana\",\"a\",\"o\")", "bonono"},
-                {"replace(\"banana\",\"(an)+\", \"**\")", "b**a"},
-                {"replace(\"banana\",\"[aeiouy]\",\"[$0]\")", "b[a]n[a]n[a]"},
-                {"replace(\"0123456789\",\"(\\d{3})(\\d{3})(\\d{4})\",\"($1) 
$2-$3\")", "(012) 345-6789"},
-                {"count([1, 2, 3])", BigDecimal.valueOf(3)},
-                {"count( 1, 2, 3 )", BigDecimal.valueOf(3)},
-                {"min( \"a\", \"b\", \"c\" )", "a"},
-                {"min([ \"a\", \"b\", \"c\" ])", "a"},
-                {"max( 1, 2, 3 )", BigDecimal.valueOf(3)},
-                {"max([ 1, 2, 3 ])", BigDecimal.valueOf(3)},
-                {"max(duration(\"PT1H6M\"), duration(\"PT1H5M\"))", 
Duration.parse("PT1H6M")},
-                {"max(duration(\"P6Y\"), duration(\"P5Y\"))", 
ComparablePeriod.parse("P6Y")},
-                {"sum( 1, 2, 3 )", BigDecimal.valueOf(6)},
-                {"sum([ 1, 2, 3 ])", BigDecimal.valueOf(6)},
-                {"sum([])", null},
-                {"product( 2, 3, 4 )", BigDecimal.valueOf(24)},
-                {"product([ 2, 3, 4 ])", BigDecimal.valueOf(24)},
-                {"product([])", null},
-                {"mean( 1, 2, 3 )", BigDecimal.valueOf(2)},
-                {"mean([ 1, 2, 3 ])", BigDecimal.valueOf(2)},
-                {"decimal( 1/3, 2 )", new BigDecimal("0.33")},
-                {"decimal( 1.5, 0 )", new BigDecimal("2")},
-                {"decimal( 2.5, 0 )", new BigDecimal("2")},
-                {"decimal( null, 0 )", null},
-                {"floor( 1.5 )", new BigDecimal("1")},
-                {"floor( -1.5 )", new BigDecimal("-2")},
-                {"floor( null )", null},
-                {"ceiling( 1.5 )", new BigDecimal("2")},
-                {"ceiling( -1.5 )", new BigDecimal("-1")},
-                {"ceiling( null )", null},
-                {"ceiling( n : 1.5 )", new BigDecimal("2")},
-                {"abs( 10 )", new BigDecimal("10")},
-                {"abs( -10 )", new BigDecimal("10")},
-                {"abs( n: -10 )", new BigDecimal("10")},
-                {"abs(@\"PT5H\")", Duration.parse("PT5H")},
-                {"abs(@\"-PT5H\")", Duration.parse("PT5H")},
-                {"abs(n: @\"-PT5H\")", Duration.parse("PT5H")},
-                {"abs(duration(\"P1Y\"))", ComparablePeriod.parse("P1Y")},
-                {"abs(duration(\"-P1Y\"))", ComparablePeriod.parse("P1Y")},
-
-                {"day of year( date(2019, 9, 17) )", BigDecimal.valueOf(260)},
-                {"day of week( date(2019, 9, 17) )", "Tuesday"},
-                {"month of year( date(2019, 9, 17) )", "September"},
-                {"week of year( date(2019, 9, 17) )", BigDecimal.valueOf(38)},
-                {"week of year( date(2003, 12, 29) )", BigDecimal.valueOf(1)}, 
// ISO defs.
-                {"week of year( date(2004, 1, 4) )", BigDecimal.valueOf(1)},
-                {"week of year( date(2005, 1, 3) )", BigDecimal.valueOf(1)},
-                {"week of year( date(2005, 1, 9) )", BigDecimal.valueOf(1)},
-                {"week of year( date(2005, 1, 1) )", BigDecimal.valueOf(53)},
-                {"median( 8, 2, 5, 3, 4 )", new BigDecimal("4")},
-                {"median( [6, 1, 2, 3] )", new BigDecimal("2.5")},
-                {"median( [ ] ) ", null}, // DMN spec, Table 69: Semantics of 
list functions
+                {"@\"1970-01-01\"", "@\"1970-01-02\""},
+                {"@\"1970-01-01T00:00:00\"", "@\"1970-01-02T00:00:00\""},
+                {"@\"00:00:00\"", "@\"00:00:00\""},
+                {"@\"P1D\"", "@\"P2D\""},
+                {"@\"P1Y\"", "@\"P2Y\""},
+                {"date(\"1978-09-12\")", "date(\"1978-10-13\")"},
+                {"date(\"1978-09-12\")", "@\"1980-01-01\""},
+                {"@\"1978-01-01\"", "date(\"1978-09-12\")"},
+                {"time(\"00:00:00\")", "time(\"23:00:00\")"},
+                {"time(\"00:00:00\")", "@\"23:00:00\""},
+                {"@\"00:00:00\"", "time(\"23:00:00\")"},
+                {"date and time(\"1978-09-12T00:00:00\")", "date and 
time(\"1978-10-13T00:00:00\")"},
+                {"date and time(\"1978-09-12T00:00:00\")", 
"@\"1980-01-02T00:00:00\""},
+                {"@\"1970-01-01T00:00:00\"", "date and 
time(\"1978-10-13T00:00:00\")"},
+                {"duration(\"P2DT20H14M\")", "duration(\"P3DT20H14M\")"},
+                {"duration(\"P1Y6M\")", "duration(\"P1Y10M\")"},
+                {"duration(\"P1D\")", "@\"P2D\""},
+                {"@\"P1D\"",  "duration(\"P3D\")"},
         };
     }
 
-    // 10.3.2.7 Endpoints can be either a literal or a qualified name of the 
following types: number, string, date,
-    // time, date and
-    //time, or duration.
+    // 10.3.2.7 Endpoints can be either a literal or a qualified name of the 
following types:
+    // number, string, date time, date and time, or duration.
     private static Object[][] invalidFunctionInvocationNodeData() {
         // Subset of FEELFunctionsTest.data
         return new Object[][]{
-                // constants
-                {"contains(\"foobar\", \"ob\")", Boolean.TRUE},
-                {"contains(\"foobar\", \"of\")", Boolean.FALSE},
-                {"starts with(\"foobar\", \"of\")", Boolean.FALSE},
-                {"starts with(\"foobar\", \"fo\")", Boolean.TRUE},
-                {"ends with(\"foobar\", \"of\")", Boolean.FALSE},
-                {"ends with(\"foobar\", \"bar\")", Boolean.TRUE},
-                {"matches(\"foo\", \"[a-z]{3}\")", Boolean.TRUE},
-                {"matches(\"banana\", \"[a-z]{3}\")", Boolean.TRUE},
-                {"matches(\"two \\n lines\", \"two.*lines\")", Boolean.FALSE},
-                {"matches(\"two \\n lines\", \"two.*lines\", \"s\")", 
Boolean.TRUE}, // DOT_ALL flag set by "s"
-                {"matches(\"one\\ntwo\\nthree\", \"^two$\")", Boolean.FALSE},
-                {"matches(\"one\\ntwo\\nthree\", \"^two$\", \"m\")", 
Boolean.TRUE}, // MULTILINE flag set by "m"
-                {"matches(\"FoO\", \"foo\")", Boolean.FALSE},
-                {"matches(\"FoO\", \"foo\", \"i\")", Boolean.TRUE}, // 
CASE_INSENSITIVE flag set by "i"
-                {"list contains([1, 2, 3], 2)", Boolean.TRUE},
-                {"list contains([1, 2, 3], 5)", Boolean.FALSE},
-                {"sublist( [1, 2, 3, 4, 5 ], 3, 2 )", 
Arrays.asList(BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"sublist( [1, 2, 3, 4, 5 ], -2, 1 )", 
Collections.singletonList(BigDecimal.valueOf(4))},
-                {"sublist( [1, 2, 3, 4, 5 ], -5, 3 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                     
BigDecimal.valueOf(3))},
-                {"sublist( [1, 2, 3, 4, 5 ], 1, 3 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                    
BigDecimal.valueOf(3))},
-                {"append( [1, 2], 3, 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                         
BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"append( [], 3, 4 )", Arrays.asList(BigDecimal.valueOf(3), 
BigDecimal.valueOf(4))},
-                {"append( [1, 2] )", Arrays.asList(BigDecimal.valueOf(1), 
BigDecimal.valueOf(2))},
-                {"append( [1, 2], null, 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2), null,
-                                                            
BigDecimal.valueOf(4))},
-                {"append( 0, 1, 2 )", Arrays.asList(BigDecimal.valueOf(0), 
BigDecimal.valueOf(1),
-                                                    BigDecimal.valueOf(2))},
-                {"concatenate( [1, 2], [3] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                             
BigDecimal.valueOf(3))},
-                {"concatenate( [1, 2], 3, [4] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                
BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"insert before( [1, 2, 3], 1, 4 )", 
Arrays.asList(BigDecimal.valueOf(4), BigDecimal.valueOf(1),
-                                                                   
BigDecimal.valueOf(2), BigDecimal.valueOf(3))},
-                {"insert before( [1, 2, 3], 3, 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                   
BigDecimal.valueOf(4), BigDecimal.valueOf(3))},
-                {"insert before( [1, 2, 3], 3, null )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                      null, 
BigDecimal.valueOf(3))},
-                {"insert before( [1, 2, 3], -3, 4 )", 
Arrays.asList(BigDecimal.valueOf(4), BigDecimal.valueOf(1),
-                                                                    
BigDecimal.valueOf(2), BigDecimal.valueOf(3))},
-                {"insert before( [1, 2, 3], -1, 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                    
BigDecimal.valueOf(4), BigDecimal.valueOf(3))},
-                {"remove( [1, 2, 3], 1 )", 
Arrays.asList(BigDecimal.valueOf(2), BigDecimal.valueOf(3))},
-                {"remove( [1, 2, 3], 3 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2))},
-                {"remove( [1, 2, 3], -1 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2))},
-                {"remove( [1, 2, 3], -3 )", 
Arrays.asList(BigDecimal.valueOf(2), BigDecimal.valueOf(3))},
-                {"reverse( [1, 2, 3] )", Arrays.asList(BigDecimal.valueOf(3), 
BigDecimal.valueOf(2),
-                                                       BigDecimal.valueOf(1))},
-                {"index of( [1, 2, 3, 2], 2 )", 
Arrays.asList(BigDecimal.valueOf(2), BigDecimal.valueOf(4))},
-                {"index of( [1, 2, null, null], null )", 
Arrays.asList(BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"index of( [1, 2, null, null], 1 )", 
Collections.singletonList(BigDecimal.valueOf(1))},
-                {"union( [1, 2, 1], [2, 3], 2, 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                   
BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"union( [1, 2, null], 4 )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2), null,
-                                                           
BigDecimal.valueOf(4))},
-                {"union( null, 4 )", Arrays.asList(null, 
BigDecimal.valueOf(4))},
-                {"distinct values( [1, 2, 3, 2, 4] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                     
BigDecimal.valueOf(3), BigDecimal.valueOf(4))},
-                {"distinct values( [1, 2, null, 2, 4] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                        null, 
BigDecimal.valueOf(4))},
-                {"distinct values( 1 )", 
Collections.singletonList(BigDecimal.valueOf(1))},
-                {"sort( [3, 1, 4, 5, 2], function(x,y) x < y )", 
Arrays.asList(BigDecimal.valueOf(1),
-                                                                               
BigDecimal.valueOf(2),
-                                                                               
BigDecimal.valueOf(3),
-                                                                               
BigDecimal.valueOf(4),
-                                                                               
BigDecimal.valueOf(5))},
-                {"sort( [3, 1, 4, 5, 2] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                          
BigDecimal.valueOf(3),
-                                                          
BigDecimal.valueOf(4), BigDecimal.valueOf(5))},
-                {"sort( list : [3, 1, 4, 5, 2] )", 
Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2),
-                                                                 
BigDecimal.valueOf(3),
-                                                                 
BigDecimal.valueOf(4), BigDecimal.valueOf(5))},
-                {"sort( [\"c\", \"e\", \"d\", \"a\", \"b\"], function(x,y) x < 
y )", Arrays.asList("a", "b", "c", "d"
-                        , "e")},
-                {"sort( list : [\"c\", \"e\", \"d\", \"a\", \"b\"], precedes : 
function(x,y) x < y )", Arrays.asList(
-                        "a", "b", "c", "d", "e")},
-                {"sort( precedes : function(x,y) x < y, list : [\"c\", \"e\", 
\"d\", \"a\", \"b\"] )", Arrays.asList(
-                        "a", "b", "c", "d", "e")},
-                {"all( true )", true},
-                {"all( false )", false},
-                {"all( [true] )", true},
-                {"all( [false] )", false},
-                {"all( true, false )", false},
-                {"all( true, true )", true},
-                {"all( [true, false] )", false},
-                {"all( [true, true] )", true},
-                {"all( [false,null,true] )", false},
-                {"all( [] )", true},
-                {"any( true )", true},
-                {"any( false )", false},
-                {"any( [true] )", true},
-                {"any( [false] )", false},
-                {"any( true, false )", true},
-                {"any( true, true )", true},
-                {"any( [true, false] )", true},
-                {"any( [true, true] )", true},
-                {"any( [false,null,true] )", true},
-                {"any( [] )", false},
+                {"number(\"1\")", 2},
+                {"a", "lower case(\"Z\")"},
+                {"string(\"11.1\")"},
+                {"duration(string(\"P1D\"))"},
+                {"contains(\"foobar\", \"ob\")"},
+                {"contains(\"foobar\", \"of\")"},
+                {"starts with(\"foobar\", \"of\")"},
+                {"starts with(\"foobar\", \"fo\")"},
+                {"ends with(\"foobar\", \"of\")"},
+                {"ends with(\"foobar\", \"bar\")"},
+                {"matches(\"foo\", \"[a-z]{3}\")"},
+                {"matches(\"banana\", \"[a-z]{3}\")"},
+                {"matches(\"two \\n lines\", \"two.*lines\")"},
+                {"matches(\"two \\n lines\", \"two.*lines\", \"s\")"}, // 
DOT_ALL flag set by "s"
+                {"matches(\"one\\ntwo\\nthree\", \"^two$\")"},
+                {"matches(\"one\\ntwo\\nthree\", \"^two$\", \"m\")"}, // 
MULTILINE flag set by "m"
+                {"matches(\"FoO\", \"foo\")"},
+                {"matches(\"FoO\", \"foo\", \"i\")"}, // CASE_INSENSITIVE flag 
set by "i"
+                {"list contains([1, 2, 3], 2)"},
+                {"list contains([1, 2, 3], 5)"},
+                {"sublist( [1, 2, 3, 4, 5 ], 3, 2 )"},
+                {"sublist( [1, 2, 3, 4, 5 ], -2, 1 )"},
+                {"sublist( [1, 2, 3, 4, 5 ], -5, 3 )"},
+                {"sublist( [1, 2, 3, 4, 5 ], 1, 3 )"},
+                {"append( [1, 2], 3, 4 )"},
+                {"append( [], 3, 4 )"},
+                {"append( [1, 2] )"},
+                {"append( [1, 2], null, 4 )"},
+                {"append( 0, 1, 2 )"},
+                {"concatenate( [1, 2], [3] )"},
+                {"concatenate( [1, 2], 3, [4] )"},
+                {"insert before( [1, 2, 3], 1, 4 )"},
+                {"insert before( [1, 2, 3], 3, 4 )"},
+                {"insert before( [1, 2, 3], 3, null )"},
+                {"insert before( [1, 2, 3], -3, 4 )"},
+                {"insert before( [1, 2, 3], -1, 4 )"},
+                {"remove( [1, 2, 3], 1 )"},
+                {"remove( [1, 2, 3], 3 )"},
+                {"remove( [1, 2, 3], -1 )"},
+                {"remove( [1, 2, 3], -3 )"},
+                {"reverse( [1, 2, 3] )"},
+                {"index of( [1, 2, 3, 2], 2 )"},
+                {"index of( [1, 2, null, null], null )"},
+                {"index of( [1, 2, null, null], 1 )"},
+                {"union( [1, 2, 1], [2, 3], 2, 4 )"},
+                {"union( [1, 2, null], 4 )"},
+                {"union( null, 4 )"},
+                {"distinct values( [1, 2, 3, 2, 4] )"},
+                {"distinct values( [1, 2, null, 2, 4] )"},
+                {"distinct values( 1 )"},
+                {"sort( [3, 1, 4, 5, 2], function(x,y) x < y )"},
+                {"sort( [3, 1, 4, 5, 2] )"},
+                {"sort( list : [3, 1, 4, 5, 2] )"},
+                {"sort( [\"c\", \"e\", \"d\", \"a\", \"b\"], function(x,y) x < 
y )"},
+                {"sort( list : [\"c\", \"e\", \"d\", \"a\", \"b\"], precedes : 
function(x,y) x < y )"},
+                {"sort( precedes : function(x,y) x < y, list : [\"c\", \"e\", 
\"d\", \"a\", \"b\"] )"},
+                {"all( true )"},
+                {"all( false )"},
+                {"all( [true] )"},
+                {"all( [false] )"},
+                {"all( true, false )"},
+                {"all( true, true )"},
+                {"all( [true, false] )"},
+                {"all( [true, true] )"},
+                {"all( [false,null,true] )"},
+                {"all( [] )"},
+                {"any( true )"},
+                {"any( false )"},
+                {"any( [true] )"},
+                {"any( [false] )"},
+                {"any( true, false )"},
+                {"any( true, true )"},
+                {"any( [true, false] )"},
+                {"any( [true, true] )"},
+                {"any( [false,null,true] )"},
+                {"any( [] )"},
         };
     }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to