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 2c8ec647f4 [incubator-kie-issues#1911] DMN 1.6: Add a type conversion
from decimal to integer with Test cases (#6299)
2c8ec647f4 is described below
commit 2c8ec647f49dbbe36d7cd899413d43b76e19bffd
Author: ChinchuAjith <[email protected]>
AuthorDate: Wed Apr 30 16:01:40 2025 +0530
[incubator-kie-issues#1911] DMN 1.6: Add a type conversion from decimal to
integer with Test cases (#6299)
---
.../feel/runtime/functions/CeilingFunction.java | 25 +++---
.../runtime/functions/DateAndTimeFunction.java | 98 ++++++++++------------
.../dmn/feel/runtime/functions/DateFunction.java | 45 +++++-----
.../feel/runtime/functions/DecimalFunction.java | 28 ++++---
.../dmn/feel/runtime/functions/FloorFunction.java | 27 +++---
.../runtime/functions/InsertBeforeFunction.java | 44 +++++-----
.../runtime/functions/ListReplaceFunction.java | 34 ++++----
.../dmn/feel/runtime/functions/RemoveFunction.java | 44 +++++-----
.../feel/runtime/functions/RoundDownFunction.java | 26 +++---
.../runtime/functions/RoundHalfDownFunction.java | 26 +++---
.../runtime/functions/RoundHalfUpFunction.java | 26 +++---
.../feel/runtime/functions/RoundUpFunction.java | 26 +++---
.../feel/runtime/functions/SublistFunction.java | 57 +++++++------
.../dmn/feel/runtime/functions/TimeFunction.java | 23 +++--
.../org/kie/dmn/feel/util/NumberEvalHelper.java | 25 +++++-
.../kie/dmn/feel/util/NumberEvalHelperTest.java | 63 ++++++++++++++
16 files changed, 369 insertions(+), 248 deletions(-)
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/CeilingFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/CeilingFunction.java
index ad2e9c193a..d96297c9a3 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/CeilingFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/CeilingFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class CeilingFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -39,17 +42,17 @@ public class CeilingFunction
}
public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.CEILING ) );
+ }catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
- }
-
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.CEILING ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateAndTimeFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateAndTimeFunction.java
index c7ffcb0398..a18d6aa8a6 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateAndTimeFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateAndTimeFunction.java
@@ -30,12 +30,16 @@ import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
+import java.util.NoSuchElementException;
+import java.util.Optional;
import java.util.TimeZone;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELDateTimeFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class DateAndTimeFunction
extends BaseFEELFunction implements FEELDateTimeFunction {
@@ -119,71 +123,57 @@ public class DateAndTimeFunction
return invoke( year, month, day, hour, minute, second, (Number) null );
}
- public FEELFnResult<TemporalAccessor> invoke(@ParameterName( "year" )
Number year, @ParameterName( "month" ) Number month, @ParameterName( "day" )
Number day,
- @ParameterName( "hour" )
Number hour, @ParameterName( "minute" ) Number minute, @ParameterName( "second"
) Number second,
- @ParameterName( "hour offset"
) Number hourOffset ) {
- if ( year == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "year", "cannot be null"));
- }
- if ( month == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "month", "cannot be null"));
- }
- if ( day == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "day", "cannot be null"));
- }
- if ( hour == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "hour", "cannot be null"));
- }
- if ( minute == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "minute", "cannot be null"));
- }
- if ( second == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "second", "cannot be null"));
- }
-
+ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("year") Number
year, @ParameterName("month") Number month, @ParameterName("day") Number day,
+ @ParameterName("hour") Number
hour, @ParameterName("minute") Number minute, @ParameterName("second") Number
second,
+ @ParameterName("hour offset")
Number hourOffset) {
try {
- if( hourOffset != null ) {
- return FEELFnResult.ofResult( OffsetDateTime.of(
year.intValue(), month.intValue(), day.intValue(),
-
hour.intValue(), minute.intValue(), second.intValue(),
- 0, ZoneOffset.ofHours(
hourOffset.intValue() ) ) );
+ int coercedYear = coerceIntegerNumber(year).orElseThrow(() -> new
NoSuchElementException("year"));
+ int coercedMonth = coerceIntegerNumber(month).orElseThrow(() ->
new NoSuchElementException("month"));
+ int coercedDay = coerceIntegerNumber(day).orElseThrow(() -> new
NoSuchElementException("day"));
+ int coercedHour = coerceIntegerNumber(hour).orElseThrow(() -> new
NoSuchElementException("hour"));
+ int coercedMinute = coerceIntegerNumber(minute).orElseThrow(() ->
new NoSuchElementException("minute"));
+ int coercedSecond = coerceIntegerNumber(second).orElseThrow(() ->
new NoSuchElementException("second"));
+
+ if (hourOffset != null) {
+ Optional<Integer> coercedHourOffset =
coerceIntegerNumber(hourOffset);
+ return
coercedHourOffset.<FEELFnResult<TemporalAccessor>>map(integer ->
FEELFnResult.ofResult(
+ OffsetDateTime.of(
+ coercedYear, coercedMonth, coercedDay,
+ coercedHour, coercedMinute, coercedSecond,
+ 0, ZoneOffset.ofHours(integer)))).orElseGet(()
-> FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "hour
offset", "could not be coerced to Integer")));
+
} else {
- return FEELFnResult.ofResult( LocalDateTime.of(
year.intValue(), month.intValue(), day.intValue(),
-
hour.intValue(), minute.intValue(), second.intValue() ) );
+ return FEELFnResult.ofResult(
+ LocalDateTime.of(
+ coercedYear, coercedMonth, coercedDay,
+ coercedHour, coercedMinute, coercedSecond
+ )
+ );
}
+ } catch (NoSuchElementException e) { // thrown by
Optional.orElseThrow()
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
} catch (DateTimeException e) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "input parameters date-parsing
exception", e));
}
}
- public FEELFnResult<TemporalAccessor> invoke(@ParameterName( "year" )
Number year, @ParameterName( "month" ) Number month, @ParameterName( "day" )
Number day,
- @ParameterName( "hour" )
Number hour, @ParameterName( "minute" ) Number minute, @ParameterName( "second"
) Number second,
- @ParameterName( "timezone" )
String timezone ) {
- if (year == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "year", "cannot be null"));
- }
- if (month == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "month", "cannot be null"));
- }
- if (day == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "day", "cannot be null"));
- }
- if (hour == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "hour", "cannot be null"));
- }
- if (minute == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "minute", "cannot be null"));
- }
- if (second == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "second", "cannot be null"));
- }
-
+ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("year") Number
year, @ParameterName("month") Number month, @ParameterName("day") Number day,
+ @ParameterName("hour") Number
hour, @ParameterName("minute") Number minute, @ParameterName("second") Number
second,
+ @ParameterName("timezone")
String timezone) {
try {
- return FEELFnResult.ofResult(ZonedDateTime.of(year.intValue(),
month.intValue(), day.intValue(),
- hour.intValue(), minute.intValue(), second.intValue(), 0,
TimeZone.getTimeZone(timezone).toZoneId()));
+ int coercedYear = coerceIntegerNumber(year).orElseThrow(() -> new
NoSuchElementException("year"));
+ int coercedMonth = coerceIntegerNumber(month).orElseThrow(() ->
new NoSuchElementException("month"));
+ int coercedDay = coerceIntegerNumber(day).orElseThrow(() -> new
NoSuchElementException("day"));
+ int coercedHour = coerceIntegerNumber(hour).orElseThrow(() -> new
NoSuchElementException("hour"));
+ int coercedMinute = coerceIntegerNumber(minute).orElseThrow(() ->
new NoSuchElementException("minute"));
+ int coercedSecond = coerceIntegerNumber(second).orElseThrow(() ->
new NoSuchElementException("second"));
+ return FEELFnResult.ofResult(ZonedDateTime.of(coercedYear,
coercedMonth, coercedDay,
+ coercedHour, coercedMinute, coercedSecond, 0,
TimeZone.getTimeZone(timezone).toZoneId()));
+ } catch (NoSuchElementException e) { // thrown by
Optional.orElseThrow()
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
} catch (DateTimeException e) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "input parameters date-parsing
exception", e));
}
- }
-
+ }
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateFunction.java
index a9245f2e54..be690dd2e6 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DateFunction.java
@@ -25,6 +25,7 @@ import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;
import java.time.temporal.TemporalAccessor;
+import java.util.NoSuchElementException;
import java.util.regex.Pattern;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
@@ -34,6 +35,7 @@ import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
public class DateFunction
extends BaseFEELFunction implements FEELDateFunction {
@@ -42,22 +44,23 @@ public class DateFunction
public static final Pattern BEGIN_YEAR =
Pattern.compile("^-?(([1-9]\\d\\d\\d+)|(0\\d\\d\\d))-"); // FEEL spec,
"specified by XML Schema Part 2 Datatypes", hence: yearFrag ::= '-'? (([1-9]
digit digit digit+)) | ('0' digit digit digit))
public static final DateTimeFormatter FEEL_DATE;
+
static {
FEEL_DATE = new DateTimeFormatterBuilder().appendValue(YEAR, 4, 9,
SignStyle.NORMAL)
- .appendLiteral('-')
- .appendValue(MONTH_OF_YEAR,
2)
- .appendLiteral('-')
- .appendValue(DAY_OF_MONTH, 2)
- .toFormatter()
-
.withResolverStyle(ResolverStyle.STRICT);
+ .appendLiteral('-')
+ .appendValue(MONTH_OF_YEAR, 2)
+ .appendLiteral('-')
+ .appendValue(DAY_OF_MONTH, 2)
+ .toFormatter()
+ .withResolverStyle(ResolverStyle.STRICT);
}
protected DateFunction() {
super(FEELConversionFunctionNames.DATE);
}
- public FEELFnResult<TemporalAccessor> invoke(@ParameterName( "from" )
String val) {
- if ( val == null ) {
+ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("from") String
val) {
+ if (val == null) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "from", "cannot be null"));
}
if (!BEGIN_YEAR.matcher(val).find()) { // please notice the regex
strictly requires the beginning, so we can use find.
@@ -71,31 +74,26 @@ public class DateFunction
}
}
- public FEELFnResult<TemporalAccessor> invoke(@ParameterName( "year" )
Number year, @ParameterName( "month" ) Number month, @ParameterName( "day" )
Number day) {
- if ( year == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "year", "cannot be null"));
- }
- if ( month == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "month", "cannot be null"));
- }
- if ( day == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "day", "cannot be null"));
- }
-
+ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("year") Number
year, @ParameterName("month") Number month, @ParameterName("day") Number day) {
try {
- return FEELFnResult.ofResult( LocalDate.of( year.intValue(),
month.intValue(), day.intValue() ) );
+ int coercedYear = coerceIntegerNumber(year).orElseThrow(() -> new
NoSuchElementException("year"));
+ int coercedMonth = coerceIntegerNumber(month).orElseThrow(() ->
new NoSuchElementException("month"));
+ int coercedDay = coerceIntegerNumber(day).orElseThrow(() -> new
NoSuchElementException("day"));
+ return FEELFnResult.ofResult(LocalDate.of(coercedYear,
coercedMonth, coercedDay));
+ } catch (NoSuchElementException e) { // thrown by
Optional.orElseThrow()
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
} catch (DateTimeException e) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "input parameters date-parsing
exception", e));
}
}
- public FEELFnResult<TemporalAccessor> invoke(@ParameterName( "from" )
TemporalAccessor date) {
- if ( date == null ) {
+ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("from")
TemporalAccessor date) {
+ if (date == null) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "from", "cannot be null"));
}
try {
- return FEELFnResult.ofResult( LocalDate.from( date ) );
+ return FEELFnResult.ofResult(LocalDate.from(date));
} catch (DateTimeException e) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "from", "date-parsing exception", e));
}
@@ -104,4 +102,5 @@ public class DateFunction
protected FEELFnResult<TemporalAccessor>
manageDateTimeException(DateTimeException e, String val) {
return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR,
"date", e));
}
+
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DecimalFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DecimalFunction.java
index 270271962f..15606af1b9 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DecimalFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/DecimalFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class DecimalFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -34,18 +37,19 @@ public class DecimalFunction
super( "decimal" );
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.HALF_EVEN ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
- }
-
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.HALF_EVEN ) );
+
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/FloorFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/FloorFunction.java
index b012ad7f3a..3d297b4488 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/FloorFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/FloorFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class FloorFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -38,18 +41,18 @@ public class FloorFunction
return invoke(n, BigDecimal.ZERO);
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.FLOOR ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
- }
-
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.FLOOR ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/InsertBeforeFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/InsertBeforeFunction.java
index 0c89422b9e..3640b739cb 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/InsertBeforeFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/InsertBeforeFunction.java
@@ -21,11 +21,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELCollectionFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class InsertBeforeFunction
extends BaseFEELFunction implements FEELCollectionFunction {
@@ -36,26 +39,29 @@ public class InsertBeforeFunction
}
public FEELFnResult<List> invoke(@ParameterName( "list" ) List list,
@ParameterName( "position" ) BigDecimal position, @ParameterName( "newItem" )
Object newItem) {
- if ( list == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
- }
- if ( position == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be null"));
- }
- if ( position.intValue() == 0 ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be zero (parameter
'position' is 1-based)"));
- }
- if ( position.abs().intValue() > list.size() ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "inconsistent with 'list'
size"));
- }
+ try {
+ if ( list == null ) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
+ }
+ int coercedPosition = coerceIntegerNumber(position).orElseThrow(()
-> new NoSuchElementException("position"));
- // spec requires us to return a new list
- final List<Object> result = new ArrayList<>( list );
- if( position.intValue() > 0 ) {
- result.add( position.intValue() - 1, newItem );
- } else {
- result.add( list.size() + position.intValue(), newItem );
+ if ( coercedPosition == 0 ) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be zero (parameter
'position' is 1-based)"));
+ }
+ if ( Math.abs(coercedPosition) > list.size() ) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "inconsistent with 'list'
size"));
+ }
+ // spec requires us to return a new list
+ final List<Object> result = new ArrayList<>( list );
+ if( coercedPosition > 0 ) {
+ result.add( coercedPosition - 1, newItem );
+ } else {
+ result.add( list.size() + coercedPosition, newItem );
+ }
+ return FEELFnResult.ofResult( result );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "cannot be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( result );
+
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunction.java
index 12f0c827d3..bd67869115 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunction.java
@@ -21,12 +21,15 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELCollectionFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
import org.kie.dmn.feel.util.NumberEvalHelper;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class ListReplaceFunction
extends BaseFEELFunction implements FEELCollectionFunction {
@@ -40,22 +43,23 @@ public class ListReplaceFunction
public FEELFnResult<List> invoke(@ParameterName("list") List list,
@ParameterName("position") BigDecimal position,
@ParameterName("newItem") Object newItem)
{
- if (list == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", CANNOT_BE_NULL));
- }
- if (position == null) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", CANNOT_BE_NULL));
- }
- int intPosition = position.intValue();
- if (intPosition == 0 || Math.abs(intPosition) > list.size()) {
- String paramProblem = String.format("%s outside valid boundaries
(1-%s)", intPosition, list.size());
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", paramProblem));
+ try {
+ if (list == null) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", CANNOT_BE_NULL));
+ }
+ int coercedPosition = coerceIntegerNumber(position).orElseThrow(()
-> new NoSuchElementException("position"));
+ if (coercedPosition == 0 || Math.abs(coercedPosition) >
list.size()) {
+ String paramProblem = String.format("%s outside valid
boundaries (1-%s)", coercedPosition, list.size());
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", paramProblem));
+ }
+ Object e = NumberEvalHelper.coerceNumber(newItem);
+ List toReturn = new ArrayList(list);
+ int replacementPosition = coercedPosition > 0 ? coercedPosition -
1 : list.size() - Math.abs(coercedPosition);
+ toReturn.set(replacementPosition, e);
+ return FEELFnResult.ofResult(toReturn);
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- Object e = NumberEvalHelper.coerceNumber(newItem);
- List toReturn = new ArrayList(list);
- int replacementPosition = intPosition > 0 ? intPosition -1 :
list.size() - Math.abs(intPosition);
- toReturn.set(replacementPosition, e);
- return FEELFnResult.ofResult(toReturn);
}
public FEELFnResult<List> invoke(@ParameterName("list") List list,
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RemoveFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RemoveFunction.java
index 85561f5fc6..f732c7c84c 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RemoveFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RemoveFunction.java
@@ -21,11 +21,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELCollectionFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class RemoveFunction
extends BaseFEELFunction implements FEELCollectionFunction {
@@ -36,25 +39,28 @@ public class RemoveFunction
}
public FEELFnResult<List<Object>> invoke(@ParameterName( "list" ) List
list, @ParameterName( "position" ) BigDecimal position) {
- if ( list == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
- }
- if ( position == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be null"));
- }
- if ( position.intValue() == 0 ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be zero (parameter
'position' is 1-based)"));
- }
- if ( position.abs().intValue() > list.size() ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "inconsistent with 'list'
size"));
- }
- // spec requires us to return a new list
- List<Object> result = new ArrayList<>( list );
- if( position.intValue() > 0 ) {
- result.remove( position.intValue()-1 );
- } else {
- result.remove( list.size()+position.intValue() );
+ try {
+ if (list == null) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
+ }
+ int coercedPosition = coerceIntegerNumber(position).orElseThrow(()
-> new NoSuchElementException("position"));
+ if (coercedPosition == 0) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "cannot be zero (parameter
'position' is 1-based)"));
+ }
+ if (Math.abs(coercedPosition) > list.size()) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "position", "inconsistent with 'list'
size"));
+ }
+
+ // spec requires us to return a new list
+ List<Object> result = new ArrayList<>(list);
+ if (coercedPosition > 0) {
+ result.remove(coercedPosition - 1);
+ } else {
+ result.remove(list.size() + coercedPosition);
+ }
+ return FEELFnResult.ofResult(result);
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( result );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundDownFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundDownFunction.java
index ca37b4ef1c..35d5642938 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundDownFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundDownFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class RoundDownFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -38,17 +41,18 @@ public class RoundDownFunction
return invoke(n, BigDecimal.ZERO);
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
- }
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.DOWN ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.DOWN ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfDownFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfDownFunction.java
index 25def1a706..df0ac33a94 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfDownFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfDownFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class RoundHalfDownFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -38,17 +41,18 @@ public class RoundHalfDownFunction
return invoke(n, BigDecimal.ZERO);
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
- }
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.HALF_DOWN ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.HALF_DOWN ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfUpFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfUpFunction.java
index 5ce58bf8bf..4d1907c203 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfUpFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundHalfUpFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class RoundHalfUpFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -38,17 +41,18 @@ public class RoundHalfUpFunction
return invoke(n, BigDecimal.ZERO);
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
- }
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.HALF_UP ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.HALF_UP ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundUpFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundUpFunction.java
index 794a76aeb6..770edef0a8 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundUpFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/RoundUpFunction.java
@@ -20,11 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELNumberFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class RoundUpFunction
extends BaseFEELFunction implements FEELNumberFunction {
@@ -38,17 +41,18 @@ public class RoundUpFunction
return invoke(n, BigDecimal.ZERO);
}
- public FEELFnResult<BigDecimal> invoke(@ParameterName( "n" ) BigDecimal n,
@ParameterName( "scale" ) BigDecimal scale) {
- if ( n == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "n", "cannot be null"));
- }
- if ( scale == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "cannot be null"));
- }
- // Based on Table 76: Semantics of numeric functions, the scale is in
range −6111 .. 6176
- if (scale.compareTo(BigDecimal.valueOf(-6111)) < 0 ||
scale.compareTo(BigDecimal.valueOf(6176)) > 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ public FEELFnResult<BigDecimal> invoke(@ParameterName("n") BigDecimal n,
@ParameterName("scale") BigDecimal scale) {
+ try {
+ if (n == null) {
+ throw new NoSuchElementException("n");
+ }
+ int coercedScale = coerceIntegerNumber(scale).orElseThrow(() ->
new NoSuchElementException("scale"));
+ if (coercedScale < -6111 || coercedScale > 6176) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "scale", "must be in range between -6111
to 6176."));
+ }
+ return FEELFnResult.ofResult( n.setScale( coercedScale,
RoundingMode.UP ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
- return FEELFnResult.ofResult( n.setScale( scale.intValue(),
RoundingMode.UP ) );
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/SublistFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/SublistFunction.java
index 263c930008..c36229eb52 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/SublistFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/SublistFunction.java
@@ -20,10 +20,14 @@ package org.kie.dmn.feel.runtime.functions;
import java.math.BigDecimal;
import java.util.List;
+import java.util.NoSuchElementException;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.runtime.FEELCollectionFunction;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.NumberEvalHelper;
+
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
public class SublistFunction
extends BaseFEELFunction implements FEELCollectionFunction {
@@ -39,34 +43,37 @@ public class SublistFunction
}
public FEELFnResult<List> invoke(@ParameterName("list") List list,
@ParameterName("start position") BigDecimal start, @ParameterName("length")
BigDecimal length) {
- if ( list == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
- }
- if ( start == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "start", "cannot be null"));
- }
- if ( start.equals( BigDecimal.ZERO ) ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "start", "cannot be zero"));
- }
- if ( start.abs().intValue() > list.size() ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "start", "is inconsistent with 'list'
size"));
- }
- if ( length != null && length.compareTo(BigDecimal.ZERO) <= 0) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "length", "must be a positive number
when specified"));
- }
+ try {
+ if (list == null) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
+ }
+ int coercedStart = coerceIntegerNumber(start).orElseThrow(() ->
new NoSuchElementException("start"));
+ if (coercedStart == 0) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "start", "cannot be zero"));
+ }
+ if (Math.abs(coercedStart) > list.size()) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "start", "is inconsistent with 'list'
size"));
+ }
- if ( start.intValue() > 0 ) {
- int end = length != null ? start.intValue() - 1 +
length.intValue() : list.size();
- if ( end > list.size() ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "attempting to create a sublist bigger
than the original list"));
+ if (length != null && length.compareTo(BigDecimal.ZERO) <= 0) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "length", "must be a positive number
when specified"));
}
- return FEELFnResult.ofResult( list.subList( start.intValue() - 1,
end ) );
- } else {
- int end = length != null ? list.size() + start.intValue() +
length.intValue() : list.size();
- if ( end > list.size() ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "attempting to create a sublist bigger
than the original list"));
+ int coercedLength =
NumberEvalHelper.coerceIntegerNumber(length).orElse(0);
+ if (coercedStart > 0) {
+ int end = length != null ? coercedStart - 1 + coercedLength :
list.size();
+ if (end > list.size()) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "attempting to create a sublist bigger
than the original list"));
+ }
+ return FEELFnResult.ofResult(list.subList(coercedStart - 1,
end));
+ } else {
+ int end = length != null ? list.size() + coercedStart +
coercedLength : list.size();
+ if (end > list.size()) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "attempting to create a sublist bigger
than the original list"));
+ }
+ return FEELFnResult.ofResult(list.subList(list.size() +
coercedStart, end));
}
- return FEELFnResult.ofResult( list.subList( list.size() +
start.intValue(), end ) );
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "could not be coerced to
Integer: either null or not a valid Number."));
}
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/TimeFunction.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/TimeFunction.java
index b5c6c39e20..dc1e6813be 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/TimeFunction.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/TimeFunction.java
@@ -32,6 +32,7 @@ import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
+import java.util.NoSuchElementException;
import java.util.regex.Pattern;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
@@ -40,6 +41,8 @@ import org.kie.dmn.feel.runtime.FEELTimeFunction;
import org.kie.dmn.feel.runtime.custom.ZoneTime;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import static org.kie.dmn.feel.util.NumberEvalHelper.coerceIntegerNumber;
+
public class TimeFunction
extends BaseFEELFunction implements FEELTimeFunction {
@@ -118,17 +121,10 @@ public class TimeFunction
public FEELFnResult<TemporalAccessor> invoke(
@ParameterName("hour") Number hour, @ParameterName("minute")
Number minute,
@ParameterName("second") Number seconds, @ParameterName("offset")
Duration offset) {
- if ( hour == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "hour", "cannot be null"));
- }
- if ( minute == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "minute", "cannot be null"));
- }
- if ( seconds == null ) {
- return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "seconds", "cannot be null"));
- }
-
try {
+ int coercedHour = coerceIntegerNumber(hour).orElseThrow(() -> new
NoSuchElementException("hour"));
+ int coercedMinute = coerceIntegerNumber(minute).orElseThrow(() ->
new NoSuchElementException("minute"));
+ int coercedSecond = coerceIntegerNumber(seconds).orElseThrow(() ->
new NoSuchElementException("seconds"));
int nanosecs = 0;
if( seconds instanceof BigDecimal ) {
BigDecimal secs = (BigDecimal) seconds;
@@ -136,13 +132,15 @@ public class TimeFunction
}
if ( offset == null ) {
- return FEELFnResult.ofResult( LocalTime.of( hour.intValue(),
minute.intValue(), seconds.intValue(),
+ return FEELFnResult.ofResult( LocalTime.of( coercedHour,
coercedMinute, coercedSecond,
nanosecs ) );
} else {
- return FEELFnResult.ofResult( OffsetTime.of( hour.intValue(),
minute.intValue(), seconds.intValue(),
+ return FEELFnResult.ofResult( OffsetTime.of( coercedHour,
coercedMinute, coercedSecond,
nanosecs,
ZoneOffset.ofTotalSeconds( (int)
offset.getSeconds() ) ) );
}
+ } catch (NoSuchElementException e) {
+ return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, e.getMessage(), "One or more input
values could not be coerced to Integer: either null or not a valid Number."));
} catch (DateTimeException e) {
return FEELFnResult.ofError(new
InvalidParametersEvent(Severity.ERROR, "time-parsing exception", e));
}
@@ -180,5 +178,4 @@ public class TimeFunction
protected FEELFnResult<TemporalAccessor>
manageDateTimeException(DateTimeException e, String val) {
return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR,
"from", e));
}
-
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/NumberEvalHelper.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/NumberEvalHelper.java
index f5920416f4..229a456a02 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/NumberEvalHelper.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/NumberEvalHelper.java
@@ -21,6 +21,7 @@ package org.kie.dmn.feel.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
+import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -69,9 +70,31 @@ public class NumberEvalHelper {
public static Object coerceNumber(Object value) {
if ( value instanceof Number && !(value instanceof BigDecimal) ) {
return getBigDecimalOrNull( value );
- } else {
+ } else {
return value;
}
}
+ /**
+ * This method checks if the input is an instance of BigDecimal, BigInteger
+ * or any other subclass Number. If so, it returns an Optional containing
+ * the result of calling intValue() on the number. If the input is not a
recognized number type,
+ * it returns Optional#empty()
+ * @param value : The object to coerce into an Integer
+ * @return : An Optional<Integer> containing the coerced integer value,
+ * or Optional.empty() if the input is not a supported number
type
+ */
+ public static Optional<Integer> coerceIntegerNumber(Object value) {
+ if ( value instanceof BigDecimal ) {
+ return Optional.of(((BigDecimal) value).intValue());
+ }
+ if ( value instanceof BigInteger ) {
+ return Optional.of(((BigInteger) value).intValue());
+ }
+ if ( value instanceof Number ) {
+ return Optional.of(((Number) value).intValue());
+ }
+ return Optional.empty();
+ }
+
}
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/NumberEvalHelperTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/NumberEvalHelperTest.java
index e619069768..31249ce7cf 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/NumberEvalHelperTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/NumberEvalHelperTest.java
@@ -19,6 +19,8 @@
package org.kie.dmn.feel.util;
import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Optional;
import org.junit.jupiter.api.Test;
@@ -34,4 +36,65 @@ class NumberEvalHelperTest {
assertThat(NumberEvalHelper.getBigDecimalOrNull(10000000000.5D)).isEqualTo(new
BigDecimal("10000000000.5"));
}
+ @Test
+ void coerceIntegerNumber_withBigDecimal() {
+ //Verifies that BigDecimal values are truncated (not rounded) when
coerced to integers.
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(new
BigDecimal("99.99"));
+ assertThat(result).isPresent();
+ assertThat(result.get()).isEqualTo(99);
+
+ Optional<Integer> result1 = NumberEvalHelper.coerceIntegerNumber(new
BigDecimal("99.00001"));
+ assertThat(result1).isPresent();
+ assertThat(result1.get()).isEqualTo(99);
+ }
+
+ @Test
+ void coerceIntegerNumber_withBigInteger() {
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(new
BigInteger("1000"));
+ assertThat(result).isPresent();
+ assertThat(result.get()).isEqualTo(1000);
+ }
+
+ @Test
+ void coerceIntegerNumber_withDouble() {
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(42.50);
+ assertThat(result).isPresent();
+ assertThat(result.get()).isEqualTo(42);
+
+ Optional<Integer> result1 =
NumberEvalHelper.coerceIntegerNumber(42.009 );
+ assertThat(result1).isPresent();
+ assertThat(result1.get()).isEqualTo(42);
+
+ Optional<Integer> result2 =
NumberEvalHelper.coerceIntegerNumber(42.99999 );
+ assertThat(result2).isPresent();
+ assertThat(result2.get()).isEqualTo(42);
+ }
+
+ @Test
+ void coerceIntegerNumber_withString() {
+ // Verifies that a non-numeric input such as a String returns
Optional.empty()
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber("123");
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void coerceIntegerNumber_withInteger() {
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(42);
+ assertThat(result).isPresent();
+ assertThat(result.get()).isEqualTo(42);
+ }
+
+ @Test
+ void coerceIntegerNumber_withLong() {
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(423L);
+ assertThat(result).isPresent();
+ assertThat(result.get()).isEqualTo(423);
+ }
+
+ @Test
+ void coerceIntegerNumber_withNull() {
+ Optional<Integer> result = NumberEvalHelper.coerceIntegerNumber(null);
+ assertThat(result).isEmpty();
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]