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

gitgabrio 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 682b4bb2b3 [kie-issues#2017] `range()` function shouldn't allow 
descendant range endpoints (#6389)
682b4bb2b3 is described below

commit 682b4bb2b39a3f3288c3af6d268f8ea5f11bd33c
Author: Yeser Amer <[email protected]>
AuthorDate: Mon Jul 7 13:37:26 2025 +0200

    [kie-issues#2017] `range()` function shouldn't allow descendant range 
endpoints (#6389)
    
    * Fir range endpoints ascendant ordering
    
    * Minor changes
    
    * CR
    
    * CR
    
    * CR
    
    * CR
    
    * CR
    
    * CR
    
    * CR
---
 .../dmn/feel/runtime/functions/RangeFunction.java  |  43 +++++--
 .../feel/runtime/functions/RangeFunctionTest.java  | 127 ++++++++++++++++++++-
 2 files changed, 156 insertions(+), 14 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 309e8699cc..25b39ee75b 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
@@ -67,17 +67,18 @@ public class RangeFunction extends BaseFEELFunction {
             baseNode -> baseNode instanceof AtLiteralNode,
             baseNode -> baseNode instanceof FunctionInvocationNode);
 
-    private static final List<Predicate<Object>> ALLOWED_TYPES = 
Arrays.asList(Objects::isNull,
-            object -> object instanceof String,
-            object -> object instanceof Number,
-            object -> object instanceof Duration,
-            object -> object instanceof ChronoPeriod,
-            object -> object instanceof ZonedDateTime,
-            object -> object instanceof OffsetDateTime,
-            object -> object instanceof LocalDateTime,
-            object -> object instanceof LocalDate,
-            object -> object instanceof OffsetTime,
-            object -> object instanceof LocalTime);
+    private static final List<Predicate<Object>> ALLOWED_TYPES = Arrays.asList(
+            ChronoPeriod.class::isInstance,
+            Duration.class::isInstance,
+            LocalDate.class::isInstance,
+            LocalDateTime.class::isInstance,
+            LocalTime.class::isInstance,
+            Number.class::isInstance,
+            Objects::isNull,
+            OffsetDateTime.class::isInstance,
+            OffsetTime.class::isInstance,
+            String.class::isInstance,
+            ZonedDateTime.class::isInstance);
 
     private RangeFunction() {
         super("range");
@@ -135,6 +136,11 @@ public class RangeFunction extends BaseFEELFunction {
         if (!nodesReturnsSameType(left, right)) {
             return FEELFnResult.ofError(new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, "from", "endpoints must be of 
equivalent types"));
         }
+
+        if (!nodesValuesRangeAreAscending(left, right)) {
+            return FEELFnResult.ofError(new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, "from", "range endpoints must 
be in ascending order"));
+        }
+
         Range toReturn = getReturnedValue(left, right, startBoundary, 
endBoundary);
         // Boundary values need to be always defined in range string. They can 
be undefined only in unary test, that
         // represents range, e.g. (<10).
@@ -166,7 +172,7 @@ public class RangeFunction extends BaseFEELFunction {
 
     /**
      * @param leftObject
-     * @param leftObject
+     * @param rightObject
      * @return
      */
     protected boolean nodesReturnsSameType(Object leftObject, Object 
rightObject) {
@@ -181,6 +187,19 @@ 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,
+     * 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 ||
+                ((Comparable<Object>) leftValue).compareTo(rightValue) <= 0;
+    }
+
     protected BaseNode parse(String input) {
         return input.isEmpty() || input.isBlank() ? getNullNode() : 
parseNotEmptyInput(input);
     }
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 7da85c9505..f9de3acd92 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
@@ -198,9 +198,9 @@ class RangeFunctionTest {
                                       new 
RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.ONE, BigDecimal.valueOf(2)
                                               , Range.RangeBoundary.CLOSED),
                                       from);
-        from = "[2..1]";
+        from = "[1..2]";
         FunctionTestUtil.assertResult(rangeFunction.invoke(from),
-                                      new 
RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.valueOf(2), BigDecimal.ONE
+                                      new 
RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.ONE, BigDecimal.valueOf(2)
                                               , Range.RangeBoundary.CLOSED),
                                       from);
         from = "[\"a\"..\"z\"]";
@@ -329,6 +329,129 @@ class RangeFunctionTest {
                 .isFalse();
     }
 
+    @Test
+    void nodesEndpointsAscendant_True() {
+        Object left = "a";
+        Object right = "y";
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("a - y")
+                .isTrue();
+        left = "m";
+        right = "m";
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("m - m")
+                .isTrue();
+        left = 1;
+        right = 2;
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("1 - 2 (integer)")
+                .isTrue();
+        left  = 2;
+        right = 2;
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2 - 2 (integer)")
+                .isTrue();
+        left = new BigDecimal("1");
+        right = new BigDecimal("2");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("1 - 2 (BigDecimal)")
+                .isTrue();
+        left  = new BigDecimal("2");
+        right = new BigDecimal("2");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2 - 2 (BigDecimal)")
+                .isTrue();
+        left = DateTimeFormatter.ISO_DATE.parse("1982-10-13", LocalDate::from);
+        right = DateTimeFormatter.ISO_DATE.parse("2017-02-18", 
LocalDate::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("1982-10-13 - 2017-02-18")
+                .isTrue();
+        left = DateTimeFormatter.ISO_DATE.parse("2017-02-18", LocalDate::from);
+        right = DateTimeFormatter.ISO_DATE.parse("2017-02-18", 
LocalDate::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2017-02-18 - 2017-02-18")
+                .isTrue();
+        left = DateTimeFormatter.ISO_TIME.parse("10:30:10", LocalTime::from);
+        right = DateTimeFormatter.ISO_TIME.parse("10:30:59", LocalTime::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("10:30:10 - 10:30:59")
+                .isTrue();
+        left = DateTimeFormatter.ISO_TIME.parse("10:30:10", LocalTime::from);
+        right = DateTimeFormatter.ISO_TIME.parse("10:30:10", LocalTime::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("10:30:10 - 10:30:10")
+                .isTrue();
+        left = LocalDateTime.of(2017, 2, 18, 10, 30, 4, 0);
+        right = LocalDateTime.of(2017, 2, 18, 10, 30, 59, 0);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2017-02-18T10:30:04 - 2017-02-18T10:30:59")
+                .isTrue();
+        left = Duration.parse("P2DT20H14M");
+        right = Duration.parse("P2DT20H15M");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("P2DT20H14M - P2DT20H15M")
+                .isTrue();
+        left  = null;
+        right = null;
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("null - null")
+                .isTrue();
+        left = ComparablePeriod.parse("P10M");
+        right = ComparablePeriod.parse("P1Y");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("P10M - P1Y")
+                .isTrue();
+        left = ComparablePeriod.parse("P1Y");
+        right = ComparablePeriod.parse("P1Y");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("P1Y - P1Y")
+                .isTrue();
+    }
+
+    @Test
+    void nodesEndpointsAscendant_False() {
+        Object left = "y";
+        Object right = "a";
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("y - a")
+                .isFalse();
+        left = 2;
+        right = 1;
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2 - 1")
+                .isFalse();
+        left = new BigDecimal("2");
+        right = new BigDecimal("1");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2- 1 (BigDecimal)")
+                .isFalse();
+        left = DateTimeFormatter.ISO_DATE.parse("2017-02-18", LocalDate::from);
+        right = DateTimeFormatter.ISO_DATE.parse("1982-10-13", 
LocalDate::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2017-02-18 - 1982-10-13")
+                .isFalse();
+        left = DateTimeFormatter.ISO_TIME.parse("10:30:59", LocalTime::from);
+        right = DateTimeFormatter.ISO_TIME.parse("10:30:10", LocalTime::from);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("10:30:59 - 10:30:10")
+                .isFalse();
+        left = LocalDateTime.of(2017, 2, 18, 10, 30, 59, 0);
+        right = LocalDateTime.of(2017, 2, 18, 10, 30, 4, 0);
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("2017-02-18T10:30:59 - 2017-02-18T10:30:04")
+                .isFalse();
+        left = Duration.parse("P2DT20H15M");
+        right = Duration.parse("P2DT20H14M");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("P2DT20H15M - P2DT20H14M")
+                .isFalse();
+        left = ComparablePeriod.parse("P1Y");
+        right = ComparablePeriod.parse("P10M");
+        assertThat(rangeFunction.nodesValuesRangeAreAscending(left, right))
+                .withFailMessage("P1Y - P10M")
+                .isFalse();
+    }
+
     @Test
     void evaluateWithValidFunctionInvocationNode() {
         Object[][] data = validFunctionInvocationNodeData();


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

Reply via email to