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]