diff --git a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/EvalHelper.java b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/EvalHelper.java index d8bab38757e..34a85df1b4f 100644 --- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/EvalHelper.java +++ b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/EvalHelper.java @@ -533,12 +533,14 @@ public static String lcFirst(final String name) { public static Boolean compare(Object left, Object right, EvaluationContext ctx, BiPredicate op) { if ( left == null || right == null ) { return null; - } else if (left instanceof ChronoPeriod && right instanceof ChronoPeriod) { + } + if (left instanceof ChronoPeriod && right instanceof ChronoPeriod) { // periods have special compare semantics in FEEL as it ignores "days". Only months and years are compared Long l = ComparablePeriod.toTotalMonths((ChronoPeriod) left); Long r = ComparablePeriod.toTotalMonths((ChronoPeriod) right); return op.test( l, r ); - } else if (left instanceof TemporalAccessor && right instanceof TemporalAccessor) { + } + if (left instanceof TemporalAccessor && right instanceof TemporalAccessor) { // Handle specific cases when both time / datetime TemporalAccessor l = (TemporalAccessor) left; TemporalAccessor r = (TemporalAccessor) right; @@ -546,15 +548,20 @@ public static Boolean compare(Object left, Object right, EvaluationContext ctx, return op.test(valuet(l), valuet(r)); } else if (BuiltInType.determineTypeFromInstance(left) == BuiltInType.DATE_TIME && BuiltInType.determineTypeFromInstance(right) == BuiltInType.DATE_TIME) { return op.test(valuedt(l, r.query(TemporalQueries.zone())), valuedt(r, l.query(TemporalQueries.zone()))); - } // fallback; continue: + } + } + if (left instanceof Number && right instanceof Number) { + // Handle specific cases when both are Number, converting both to BigDecimal + BigDecimal l = getBigDecimalOrNull(left); + BigDecimal r = getBigDecimalOrNull(right); + return op.test(l, r); } // last fallback: if ((left instanceof String && right instanceof String) || - (left instanceof Number && right instanceof Number) || (left instanceof Boolean && right instanceof Boolean) || (left instanceof Comparable && left.getClass().isAssignableFrom(right.getClass()))) { - Comparable l = (Comparable) left; - Comparable r = (Comparable) right; + Comparable l = (Comparable) left; + Comparable r = (Comparable) right; return op.test(l, r); } return null; diff --git a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/EvalHelperTest.java b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/EvalHelperTest.java index b027cb4cace..ebaf42df3ae 100644 --- a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/EvalHelperTest.java +++ b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/EvalHelperTest.java @@ -18,6 +18,7 @@ import java.lang.reflect.Method; import java.math.BigDecimal; +import java.math.BigInteger; import org.junit.Test; import org.kie.dmn.feel.lang.FEELProperty; @@ -70,6 +71,22 @@ public void testGetGenericAccessor() throws NoSuchMethodException { assertThat(EvalHelper.getGenericAccessor(TestPojo.class, "feelPropertyIdentifier")).as("getGenericAccessor should work for methods annotated with '@FEELProperty'.").isEqualTo(expectedAccessor); } + @Test + public void testNumericValuesComparative() { + assertThat(EvalHelper.compare(BigDecimal.valueOf(1), BigDecimal.valueOf(2), null, (l, r) -> l.compareTo(r) < 0)).isTrue(); + assertThat(EvalHelper.compare(1.0, 2.0, null, (l, r) -> l.compareTo(r) < 0)).isTrue(); + assertThat(EvalHelper.compare(1, 2, null, (l, r) -> l.compareTo(r) > 0)).isFalse(); + assertThat(EvalHelper.compare(BigDecimal.valueOf(1), 2, null, (l, r) -> l.compareTo(r) > 0)).isFalse(); + assertThat(EvalHelper.compare(1, BigDecimal.valueOf(2), null, (l, r) -> l.compareTo(r) < 0)).isTrue(); + assertThat(EvalHelper.compare(BigDecimal.valueOf(1), 2.3, null, (l, r) -> l.compareTo(r) == 0)).isFalse(); + assertThat(EvalHelper.compare(1.2, BigDecimal.valueOf(1.2), null, (l, r) -> l.compareTo(r) == 0)).isTrue(); + assertThat(EvalHelper.compare(BigDecimal.valueOf(1), 0L, null, (l, r) -> l.compareTo(r) > 0)).isTrue(); + assertThat(EvalHelper.compare(10L, BigDecimal.valueOf(2), null, (l, r) -> l.compareTo(r) < 0)).isFalse(); + assertThat(EvalHelper.compare(BigInteger.valueOf(1), BigInteger.valueOf(2), null, (l, r) -> l.compareTo(r) == 0)).isFalse(); + assertThat(EvalHelper.compare(BigInteger.valueOf(1), 2, null, (l, r) -> l.compareTo(r) < 0)).isTrue(); + assertThat(EvalHelper.compare(BigInteger.valueOf(1), 2.3, null, (l, r) -> l.compareTo(r) == 0)).isFalse(); + } + private static class TestPojo { @FEELProperty("feelPropertyIdentifier") public String getAProperty() {