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 16897949cb [incubator-kie-issues#1546] Fix DMN TCK range equality test
failures for unary test ranges (#6134)
16897949cb is described below
commit 16897949cb6b691ec6b919cd4593288ebbd00cee
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Wed Oct 23 10:42:21 2024 +0200
[incubator-kie-issues#1546] Fix DMN TCK range equality test failures for
unary test ranges (#6134)
* Introduce undefined boundaries for range instances.
Signed-off-by: Tibor Zimányi <[email protected]>
* Update inclusion and equality methods for FEEL range.
Signed-off-by: Tibor Zimányi <[email protected]>
* Fix compiled FEEL scenarios with ranges.
* Restore FEELRangesTest.
* Add RangeImpl unit tests.
* [range-problems-gc] WIP
* [range-problems-gc] WIP
* [incubator-kie-issues#1546] Add UndefinedValueComparable
UndefinedValueNode
* [incubator-kie-issues#1546] Fixing tests - WIP
* [incubator-kie-issues#1546] Fixing tests - WIP
* [incubator-kie-issues#1546] Fixing tests
* [incubator-kie-issues#1546] Fixing tests
---------
Signed-off-by: Tibor Zimányi <[email protected]>
Co-authored-by: Tibor Zimányi <[email protected]>
Co-authored-by: Gabriele-Cardosi <[email protected]>
---
.../org/kie/dmn/feel/parser/feel11/FEEL_1_1.g4 | 9 +++-
.../dmn/feel/codegen/feel11/ASTCompilerHelper.java | 6 +++
.../feel/codegen/feel11/ASTCompilerVisitor.java | 7 +++
.../feel/codegen/feel11/ASTUnaryTestTransform.java | 6 +++
.../feel/codegen/feel11/DMNCodegenConstants.java | 2 +
.../kie/dmn/feel/lang/ast/ASTBuilderFactory.java | 4 ++
.../java/org/kie/dmn/feel/lang/ast/RangeNode.java | 11 ++--
.../ast/UndefinedValueNode.java} | 26 +++++-----
.../java/org/kie/dmn/feel/lang/ast/Visitor.java | 1 +
.../ast/visitor/ASTHeuristicCheckerVisitor.java | 7 ++-
.../feel/lang/ast/visitor/DefaultedVisitor.java | 6 +++
.../dmn/feel/parser/feel11/ASTBuilderVisitor.java | 13 +++--
.../main/java/org/kie/dmn/feel/runtime/Range.java | 2 +
.../dmn/feel/runtime/functions/RangeFunction.java | 1 +
.../org/kie/dmn/feel/runtime/impl/RangeImpl.java | 60 ++++++++++++++++++----
.../UndefinedValueComparable.java} | 34 +++++++-----
.../java/org/kie/dmn/feel/util/EvalHelper.java | 4 ++
.../main/java/org/kie/dmn/feel/util/TypeUtil.java | 47 ++++++++++++++---
.../feel/marshaller/FEELCodeMarshallerTest.java | 12 +++--
.../FEELCodeMarshallerUnmarshallTest.java | 14 +++--
.../feel/parser/feel11/FEELParserSeverityTest.java | 2 +-
.../org/kie/dmn/feel/runtime/FEELRangesTest.java | 12 ++++-
.../kie/dmn/feel/runtime/impl/RangeImplTest.java | 38 ++++++++++++++
.../dmn/validation/dtanalysis/DMNDTAnalyser.java | 10 ++--
.../dmn/validation/dtanalysis/model/Interval.java | 3 +-
25 files changed, 269 insertions(+), 68 deletions(-)
diff --git
a/kie-dmn/kie-dmn-feel/src/main/antlr4/org/kie/dmn/feel/parser/feel11/FEEL_1_1.g4
b/kie-dmn/kie-dmn-feel/src/main/antlr4/org/kie/dmn/feel/parser/feel11/FEEL_1_1.g4
index 9f04edc453..09eb8cb081 100644
---
a/kie-dmn/kie-dmn-feel/src/main/antlr4/org/kie/dmn/feel/parser/feel11/FEEL_1_1.g4
+++
b/kie-dmn/kie-dmn-feel/src/main/antlr4/org/kie/dmn/feel/parser/feel11/FEEL_1_1.g4
@@ -324,7 +324,8 @@ literal
| BooleanLiteral #boolLiteral
| atLiteral #atLiteralLabel
| StringLiteral #stringLiteral
- | NULL #nullLiteral
+ | NULL #nullLiteral
+ | UNDEFINEDVALUE #undefined
;
atLiteral
@@ -340,6 +341,7 @@ BooleanLiteral
| FALSE
;
+
/**************************
* OTHER CONSTRUCTS
**************************/
@@ -463,6 +465,7 @@ reusableKeywords
| BETWEEN
| NOT
| NULL
+ | UNDEFINEDVALUE
| TRUE
| FALSE
;
@@ -536,6 +539,10 @@ NULL
: 'null'
;
+UNDEFINEDVALUE
+ : 'undefined'
+ ;
+
TRUE
: 'true'
;
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerHelper.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerHelper.java
index dc87cd9e5d..b2b5f1bf59 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerHelper.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerHelper.java
@@ -79,6 +79,7 @@ import org.kie.dmn.feel.lang.ast.TemporalConstantNode;
import org.kie.dmn.feel.lang.ast.TypeNode;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.impl.JavaBackedType;
import org.kie.dmn.feel.lang.impl.MapBackedType;
import org.kie.dmn.feel.lang.types.AliasFEELType;
@@ -144,6 +145,7 @@ import static
org.kie.dmn.feel.codegen.feel11.DMNCodegenConstants.TEMPORALCONSTA
import static org.kie.dmn.feel.codegen.feel11.DMNCodegenConstants.TYPE_CT;
import static
org.kie.dmn.feel.codegen.feel11.DMNCodegenConstants.UNARYTESTLISTNODE_CT;
import static
org.kie.dmn.feel.codegen.feel11.DMNCodegenConstants.UNARYTESTNODE_CT;
+import static
org.kie.dmn.feel.codegen.feel11.DMNCodegenConstants.UNDEFINEDVALUENODE_CT;
import static org.kie.dmn.feel.util.CodegenUtils.getEnumExpression;
import static org.kie.dmn.feel.util.CodegenUtils.getListExpression;
import static org.kie.dmn.feel.util.CodegenUtils.getStringLiteralExpr;
@@ -488,6 +490,10 @@ public class ASTCompilerHelper {
n.getText());
}
+ public BlockStmt add(UndefinedValueNode n) {
+ return addVariableDeclaratorWithObjectCreation(UNDEFINEDVALUENODE_CT,
NodeList.nodeList());
+ }
+
public String getLastVariableName() {
return lastVariableName.get();
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerVisitor.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerVisitor.java
index a4bef5554d..ffa86fc061 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerVisitor.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTCompilerVisitor.java
@@ -56,6 +56,7 @@ import org.kie.dmn.feel.lang.ast.StringNode;
import org.kie.dmn.feel.lang.ast.TemporalConstantNode;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.ast.Visitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -290,6 +291,12 @@ public class ASTCompilerVisitor implements
Visitor<BlockStmt> {
return compilerHelper.add(n);
}
+ @Override
+ public BlockStmt visit(UndefinedValueNode n) {
+ LOGGER.trace("visit {}", n);
+ return compilerHelper.add(n);
+ }
+
public String getLastVariableName() {
LOGGER.trace("getLastVariableName");
return compilerHelper.getLastVariableName();
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTUnaryTestTransform.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTUnaryTestTransform.java
index 133531034e..3f2ea6e907 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTUnaryTestTransform.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/ASTUnaryTestTransform.java
@@ -37,6 +37,7 @@ import org.kie.dmn.feel.lang.ast.RangeNode;
import org.kie.dmn.feel.lang.ast.StringNode;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.ast.visitor.DefaultedVisitor;
public class ASTUnaryTestTransform extends
DefaultedVisitor<ASTUnaryTestTransform.UnaryTestSubexpr> {
@@ -136,6 +137,11 @@ public class ASTUnaryTestTransform extends
DefaultedVisitor<ASTUnaryTestTransfor
}
}
+ @Override
+ public UnaryTestSubexpr visit(UndefinedValueNode n) {
+ return new SimpleUnaryExpression(n);
+ }
+
private UnaryTestSubexpr propagateWildcard(ASTNode n) {
return Arrays.stream(n.getChildrenNode()).map(e ->
e.accept(this)).anyMatch(UnaryTestSubexpr::isWildcard) ?
new WildCardUnaryExpression((BaseNode) n) : new
SimpleUnaryExpression((BaseNode) n);
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/DMNCodegenConstants.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/DMNCodegenConstants.java
index f5db4e4150..4b214951b0 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/DMNCodegenConstants.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/DMNCodegenConstants.java
@@ -57,6 +57,7 @@ import org.kie.dmn.feel.lang.ast.StringNode;
import org.kie.dmn.feel.lang.ast.TemporalConstantNode;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.impl.JavaBackedType;
import org.kie.dmn.feel.lang.impl.MapBackedType;
import org.kie.dmn.feel.lang.types.AliasFEELType;
@@ -172,6 +173,7 @@ public class DMNCodegenConstants {
parseClassOrInterfaceType(UnaryTestListNode.class.getCanonicalName());
public static final ClassOrInterfaceType UNARYTESTNODE_CT =
parseClassOrInterfaceType(UnaryTestNode.class.getCanonicalName());
+ public static final ClassOrInterfaceType UNDEFINEDVALUENODE_CT =
parseClassOrInterfaceType(UndefinedValueNode.class.getCanonicalName());
private DMNCodegenConstants() {
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ASTBuilderFactory.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ASTBuilderFactory.java
index 95a1f5c54a..8908a3a9dd 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ASTBuilderFactory.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ASTBuilderFactory.java
@@ -43,6 +43,10 @@ public class ASTBuilderFactory {
return new NullNode( ctx );
}
+ public static UndefinedValueNode newUndefinedValueNode() {
+ return new UndefinedValueNode();
+ }
+
public static StringNode newStringNode(ParserRuleContext ctx) {
return new StringNode( ctx );
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/RangeNode.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/RangeNode.java
index c64317ad43..0d44d025d7 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/RangeNode.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/RangeNode.java
@@ -28,6 +28,7 @@ import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
import org.kie.dmn.feel.util.Msg;
public class RangeNode
@@ -113,13 +114,17 @@ public class RangeNode
Type sType = BuiltInType.determineTypeFromInstance(s);
Type eType = BuiltInType.determineTypeFromInstance(e);
- if (s != null && e != null && sType != eType &&
!s.getClass().isAssignableFrom(e.getClass())) {
+ boolean withUndefined = s instanceof UndefinedValueComparable || e
instanceof UndefinedValueComparable;
+ if (s != null && e != null &&
+ !withUndefined &&
+ sType != eType &&
+ !s.getClass().isAssignableFrom(e.getClass())) {
ctx.notifyEvt( astEvent(Severity.ERROR,
Msg.createMessage(Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, "Start", "End")));
return null;
}
- Comparable start = convertToComparable( ctx, s );
- Comparable end = convertToComparable( ctx, e );
+ Comparable start = s instanceof UndefinedValueComparable ?
(Comparable) s : convertToComparable(ctx, s );
+ Comparable end = e instanceof UndefinedValueComparable ? (Comparable)
e : convertToComparable( ctx, e );
return new RangeImpl( lowerBound==IntervalBoundary.OPEN ?
Range.RangeBoundary.OPEN : Range.RangeBoundary.CLOSED,
start,
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/UndefinedValueNode.java
similarity index 64%
copy from kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
copy to
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/UndefinedValueNode.java
index 39666b6c85..dd423acdb5 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/UndefinedValueNode.java
@@ -16,22 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.kie.dmn.feel.runtime;
+package org.kie.dmn.feel.lang.ast;
-public interface Range {
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
- enum RangeBoundary {
- OPEN, CLOSED;
- }
-
- RangeBoundary getLowBoundary();
-
- Comparable getLowEndPoint();
+public class UndefinedValueNode
+ extends BaseNode {
- Comparable getHighEndPoint();
+ public UndefinedValueNode() { }
- RangeBoundary getHighBoundary();
+ @Override
+ public Object evaluate(EvaluationContext ctx) {
+ return new UndefinedValueComparable();
+ }
- Boolean includes(Object param);
+ @Override
+ public <T> T accept(Visitor<T> v) {
+ return v.visit(this);
+ }
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/Visitor.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/Visitor.java
index 8277535645..1158d134b0 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/Visitor.java
+++ b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/Visitor.java
@@ -60,4 +60,5 @@ public interface Visitor<T> {
T visit(UnaryTestListNode n);
T visit(UnaryTestNode n);
+ T visit(UndefinedValueNode n);
}
\ No newline at end of file
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/ASTHeuristicCheckerVisitor.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/ASTHeuristicCheckerVisitor.java
index 2d39b7d19d..5927d3e0c0 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/ASTHeuristicCheckerVisitor.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/ASTHeuristicCheckerVisitor.java
@@ -19,16 +19,15 @@
package org.kie.dmn.feel.lang.ast.visitor;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.ast.ASTNode;
import org.kie.dmn.feel.lang.ast.InfixOpNode;
-import org.kie.dmn.feel.lang.ast.NullNode;
import org.kie.dmn.feel.lang.ast.RangeNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.runtime.events.ASTHeuristicCheckEvent;
import org.kie.dmn.feel.util.Msg;
@@ -63,8 +62,8 @@ public class ASTHeuristicCheckerVisitor extends
DefaultedVisitor<List<FEELEvent>
@Override
public List<FEELEvent> visit(RangeNode n) {
- if ((n.getStart() instanceof NullNode && n.getEnd() instanceof
RangeNode)
- || (n.getStart() instanceof RangeNode && n.getEnd() instanceof
NullNode)) {
+ if ((n.getStart() instanceof UndefinedValueNode && n.getEnd()
instanceof RangeNode)
+ || (n.getStart() instanceof RangeNode && n.getEnd() instanceof
UndefinedValueNode)) {
return List.of(new ASTHeuristicCheckEvent(Severity.WARN,
Msg.createMessage(Msg.UT_OF_UT, n.getText()), n));
}
return defaultVisit(n);
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/DefaultedVisitor.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/DefaultedVisitor.java
index 6eb2d6b79d..1b55497e2f 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/DefaultedVisitor.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/visitor/DefaultedVisitor.java
@@ -54,6 +54,7 @@ import org.kie.dmn.feel.lang.ast.SignedUnaryNode;
import org.kie.dmn.feel.lang.ast.StringNode;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.ast.Visitor;
public abstract class DefaultedVisitor<T> implements Visitor<T> {
@@ -240,4 +241,9 @@ public abstract class DefaultedVisitor<T> implements
Visitor<T> {
return defaultVisit(n);
}
+ @Override
+ public T visit(UndefinedValueNode n) {
+ return defaultVisit(n);
+ }
+
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/parser/feel11/ASTBuilderVisitor.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/parser/feel11/ASTBuilderVisitor.java
index 295b9fe539..64465e00d0 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/parser/feel11/ASTBuilderVisitor.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/parser/feel11/ASTBuilderVisitor.java
@@ -113,6 +113,11 @@ public class ASTBuilderVisitor
return ASTBuilderFactory.newNullNode( ctx );
}
+ @Override
+ public BaseNode visitUndefined(FEEL_1_1Parser.UndefinedContext ctx) {
+ return ASTBuilderFactory.newUndefinedValueNode();
+ }
+
@Override
public BaseNode visitStringLiteral(FEEL_1_1Parser.StringLiteralContext
ctx) {
return ASTBuilderFactory.newStringNode( ctx );
@@ -188,13 +193,13 @@ public class ASTBuilderVisitor
String op = ctx.op.getText();
switch (UnaryOperator.determineOperator(op)) {
case GT:
- return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, value, ASTBuilderFactory.newNullNode(ctx),
RangeNode.IntervalBoundary.OPEN);
+ return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, value,
ASTBuilderFactory.newUndefinedValueNode(), RangeNode.IntervalBoundary.OPEN);
case GTE:
- return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.CLOSED, value, ASTBuilderFactory.newNullNode(ctx),
RangeNode.IntervalBoundary.OPEN);
+ return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.CLOSED, value,
ASTBuilderFactory.newUndefinedValueNode(), RangeNode.IntervalBoundary.OPEN);
case LT:
- return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, ASTBuilderFactory.newNullNode(ctx), value,
RangeNode.IntervalBoundary.OPEN);
+ return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, ASTBuilderFactory.newUndefinedValueNode(),
value, RangeNode.IntervalBoundary.OPEN);
case LTE:
- return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, ASTBuilderFactory.newNullNode(ctx), value,
RangeNode.IntervalBoundary.CLOSED);
+ return ASTBuilderFactory.newIntervalNode(ctx,
RangeNode.IntervalBoundary.OPEN, ASTBuilderFactory.newUndefinedValueNode(),
value, RangeNode.IntervalBoundary.CLOSED);
default:
throw new UnsupportedOperationException("by the parser rule
FEEL grammar rule 7.a for range syntax should not have determined the operator
" + op);
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
index 39666b6c85..3ca1ec857b 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
+++ b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
@@ -34,4 +34,6 @@ public interface Range {
Boolean includes(Object param);
+ boolean isWithUndefined();
+
}
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 9dab904aca..5e37b769bc 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
@@ -134,6 +134,7 @@ public class RangeFunction extends BaseFEELFunction {
return FEELFnResult.ofError(new
InvalidParametersEvent(FEELEvent.Severity.ERROR, "from", "endpoints must be of
equivalent types"));
}
+ // Boundary values need to be always defined in range string. They can
be undefined only in unary test, that represents range, e.g. (<10).
return FEELFnResult.ofResult(new RangeImpl(startBoundary, (Comparable)
left, (Comparable) right, endBoundary));
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/RangeImpl.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/RangeImpl.java
index f16ee87dd3..51893062d9 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/RangeImpl.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/RangeImpl.java
@@ -23,6 +23,11 @@ import java.util.function.BiPredicate;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.util.BooleanEvalHelper;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.GT;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.GTE;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.LT;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.LTE;
+
public class RangeImpl
implements Range {
@@ -30,7 +35,7 @@ public class RangeImpl
private RangeBoundary highBoundary;
private Comparable lowEndPoint;
private Comparable highEndPoint;
-
+ private boolean withUndefined = false;
public RangeImpl() {
}
@@ -40,6 +45,7 @@ public class RangeImpl
this.highBoundary = highBoundary;
this.lowEndPoint = lowEndPoint;
this.highEndPoint = highEndPoint;
+ withUndefined = lowEndPoint instanceof UndefinedValueComparable ||
highEndPoint instanceof UndefinedValueComparable;
}
@Override
@@ -67,21 +73,30 @@ public class RangeImpl
if (param == null) {
return null;
}
- if (lowEndPoint == null) {
- if (highEndPoint == null) {
+ if (lowEndPoint == null || lowEndPoint instanceof
UndefinedValueComparable) {
+ if (highEndPoint == null || highEndPoint instanceof
UndefinedValueComparable) {
return null;
- } else {
+ } else if (lowEndPoint != null) { // it means it is
UndefinedValueComparable
return negInfRangeIncludes(param);
+ } else {
+ return false;
}
} else {
- if (highEndPoint == null) {
+ if (highEndPoint instanceof UndefinedValueComparable) {
return posInfRangeIncludes(param);
- } else {
+ } else if (highEndPoint != null) {
return finiteRangeIncludes(param);
+ } else {
+ return false;
}
}
}
+ @Override
+ public boolean isWithUndefined() {
+ return withUndefined;
+ }
+
private Boolean finiteRangeIncludes(Object param) {
if (lowBoundary == RangeBoundary.OPEN && highBoundary ==
RangeBoundary.OPEN) {
return bothOrThrow(compare(lowEndPoint, param, (l, r) ->
l.compareTo(r) < 0) , compare(highEndPoint, param, (l, r) -> l.compareTo(r) >
0), param);
@@ -154,9 +169,36 @@ public class RangeImpl
@Override
public String toString() {
+ return withUndefined ? withUndefinedtoString() :
withoutUndefinedtoString();
+ }
+
+ private String withoutUndefinedtoString() {
return (lowBoundary == RangeBoundary.OPEN ? "(" : "[") +
- " " + lowEndPoint +
- " .. " + highEndPoint +
- " " + ( highBoundary == RangeBoundary.OPEN ? ")" : "]" );
+ " " + lowEndPoint +
+ " .. " + highEndPoint +
+ " " + ( highBoundary == RangeBoundary.OPEN ? ")" : "]" );
+ }
+
+ private String withUndefinedtoString() {
+ StringBuilder sb = new StringBuilder("( ");
+ if (lowEndPoint instanceof UndefinedValueComparable) {
+ if (highBoundary == RangeBoundary.OPEN) {
+ sb.append(LT.symbol);
+ } else {
+ sb.append(LTE.symbol);
+ }
+ sb.append(" ");
+ sb.append(highEndPoint);
+ } else if (highEndPoint instanceof UndefinedValueComparable) {
+ if (lowBoundary == RangeBoundary.OPEN) {
+ sb.append(GT.symbol);
+ } else {
+ sb.append(GTE.symbol);
+ }
+ sb.append(" ");
+ sb.append(lowEndPoint);
+ }
+ sb.append(" )");
+ return sb.toString();
}
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/UndefinedValueComparable.java
similarity index 63%
copy from kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
copy to
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/UndefinedValueComparable.java
index 39666b6c85..240f7c98da 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/Range.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/impl/UndefinedValueComparable.java
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -16,22 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.kie.dmn.feel.runtime;
+package org.kie.dmn.feel.runtime.impl;
-public interface Range {
+public class UndefinedValueComparable implements
Comparable<UndefinedValueComparable> {
- enum RangeBoundary {
- OPEN, CLOSED;
- }
-
- RangeBoundary getLowBoundary();
- Comparable getLowEndPoint();
-
- Comparable getHighEndPoint();
+ @Override
+ public int compareTo(UndefinedValueComparable o) {
+ return 0;
+ }
- RangeBoundary getHighBoundary();
+ @Override
+ public String toString() {
+ return "undefined";
+ }
- Boolean includes(Object param);
+ @Override
+ public int hashCode() {
+ return 0;
+ }
-}
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof UndefinedValueComparable;
+ }
+}
\ No newline at end of file
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 ddd788b19d..346712fe93 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
@@ -38,6 +38,7 @@ import org.kie.dmn.api.core.FEELPropertyAccessible;
import org.kie.dmn.feel.lang.FEELProperty;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.Range.RangeBoundary;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -186,6 +187,9 @@ public class EvalHelper {
default:
return PropertyValueResult.notDefined();
}
+ if (result instanceof UndefinedValueComparable) {
+ result = null;
+ }
} else {
Method getter = getGenericAccessor( current.getClass(), property );
if ( getter != null ) {
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/TypeUtil.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/TypeUtil.java
index 7af8ad5d7a..339f1dbf14 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/TypeUtil.java
+++ b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/TypeUtil.java
@@ -41,6 +41,12 @@ import org.kie.dmn.feel.runtime.custom.ZoneTime;
import org.kie.dmn.feel.runtime.functions.DateAndTimeFunction;
import org.kie.dmn.feel.runtime.functions.DateFunction;
import org.kie.dmn.feel.runtime.functions.TimeFunction;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
+
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.GT;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.GTE;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.LT;
+import static org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator.LTE;
public final class TypeUtil {
@@ -78,7 +84,8 @@ public final class TypeUtil {
} else if (val instanceof ZoneTime zoneTime) {
return formatTimeString(zoneTime.format(), wrapForCodeUsage);
} else if (val instanceof LocalDateTime || val instanceof
OffsetDateTime) {
- return
formatDateTimeString(DateAndTimeFunction.FEEL_DATE_TIME.format((TemporalAccessor)
val), wrapForCodeUsage);
+ return
formatDateTimeString(DateAndTimeFunction.FEEL_DATE_TIME.format((TemporalAccessor)
val),
+ wrapForCodeUsage);
} else if (val instanceof ZonedDateTime) {
TemporalAccessor ta = (TemporalAccessor) val;
ZoneId zone = ta.query(TemporalQueries.zone());
@@ -86,7 +93,8 @@ public final class TypeUtil {
// it is a ZoneRegion
return
formatDateTimeString(DateAndTimeFunction.REGION_DATETIME_FORMATTER.format((TemporalAccessor)
val), wrapForCodeUsage);
} else {
- return
formatDateTimeString(DateAndTimeFunction.FEEL_DATE_TIME.format((TemporalAccessor)
val), wrapForCodeUsage);
+ return
formatDateTimeString(DateAndTimeFunction.FEEL_DATE_TIME.format((TemporalAccessor)
val),
+ wrapForCodeUsage);
}
} else if (val instanceof Duration) {
return formatDuration((Duration) val, wrapForCodeUsage);
@@ -183,11 +191,33 @@ public final class TypeUtil {
public static String formatRange(final Range val, final boolean
wrapDateTimeValuesInFunctions) {
final StringBuilder sb = new StringBuilder();
- sb.append(val.getLowBoundary() == Range.RangeBoundary.OPEN ? "( " : "[
");
- sb.append(formatValue(val.getLowEndPoint(),
wrapDateTimeValuesInFunctions));
- sb.append(" .. ");
- sb.append(formatValue(val.getHighEndPoint(),
wrapDateTimeValuesInFunctions));
- sb.append(val.getHighBoundary() == Range.RangeBoundary.OPEN ? " )" : "
]");
+ if (val.isWithUndefined()) {
+ sb.append("( ");
+ if (val.getLowEndPoint() instanceof UndefinedValueComparable) {
+ if (val.getHighBoundary() == Range.RangeBoundary.OPEN) {
+ sb.append(LT.symbol);
+ } else {
+ sb.append(LTE.symbol);
+ }
+ sb.append(" ");
+ sb.append(formatValue(val.getHighEndPoint(),
wrapDateTimeValuesInFunctions));
+ } else if (val.getHighEndPoint() instanceof
UndefinedValueComparable) {
+ if (val.getLowBoundary() == Range.RangeBoundary.OPEN) {
+ sb.append(GT.symbol);
+ } else {
+ sb.append(GTE.symbol);
+ }
+ sb.append(" ");
+ sb.append(formatValue(val.getLowEndPoint(),
wrapDateTimeValuesInFunctions));
+ }
+ sb.append(" )");
+ } else {
+ sb.append(val.getLowBoundary() == Range.RangeBoundary.OPEN ? "( "
: "[ ");
+ sb.append(formatValue(val.getLowEndPoint(),
wrapDateTimeValuesInFunctions));
+ sb.append(" .. ");
+ sb.append(formatValue(val.getHighEndPoint(),
wrapDateTimeValuesInFunctions));
+ sb.append(val.getHighBoundary() == Range.RangeBoundary.OPEN ? " )"
: " ]");
+ }
return sb.toString();
}
@@ -274,7 +304,8 @@ public final class TypeUtil {
sb.append(timeSegmentChar);
}
- private static void appendSecondsToDurationString(final StringBuilder sb,
final long seconds, final long nanoseconds) {
+ private static void appendSecondsToDurationString(final StringBuilder sb,
final long seconds,
+ final long nanoseconds) {
if (seconds < 0 && nanoseconds > 0) {
if (seconds == -1) {
sb.append("0");
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerTest.java
index 8b2adc20b4..b79ad9ab47 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerTest.java
@@ -36,6 +36,7 @@ import org.junit.jupiter.params.provider.MethodSource;
import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
import static org.assertj.core.api.Assertions.assertThat;
@@ -96,13 +97,18 @@ public class FEELCodeMarshallerTest {
{ Arrays.asList( Duration.ofDays( 4 ), Duration.ofDays( 2 ),
Duration.ofHours( 25 ) ), "[ duration( \"P4D\" ), duration( \"P2D\" ),
duration( \"P1DT1H\" ) ]" },
{ Arrays.asList( Arrays.asList( 1, 2 ), Arrays.asList( 3, 4 )
), "[ [ 1, 2 ], [ 3, 4 ] ]" },
// ranges
- { new RangeImpl( Range.RangeBoundary.CLOSED, "a", "z",
Range.RangeBoundary.OPEN ), "[ \"a\" .. \"z\" )" },
- { new RangeImpl( Range.RangeBoundary.CLOSED, Duration.ofHours(
30 ), Duration.ofHours( 50 ), Range.RangeBoundary.OPEN ), "[ duration(
\"P1DT6H\" ) .. duration( \"P2DT2H\" ) )" },
+ { new RangeImpl( Range.RangeBoundary.CLOSED, "a", "z",
Range.RangeBoundary.OPEN), "[ \"a\" .. \"z\" )" },
+ { new RangeImpl( Range.RangeBoundary.CLOSED, Duration.ofHours(
30 ), Duration.ofHours( 50 ), Range.RangeBoundary.OPEN), "[ duration(
\"P1DT6H\" ) .. duration( \"P2DT2H\" ) )" },
+ { new RangeImpl(Range.RangeBoundary.OPEN, BigDecimal.ONE, new
UndefinedValueComparable(), Range.RangeBoundary.OPEN), "( > 1 )" },
+ { new RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.ONE,
new UndefinedValueComparable(), Range.RangeBoundary.OPEN), "( >= 1 )" },
+ { new RangeImpl(Range.RangeBoundary.OPEN, new
UndefinedValueComparable(), BigDecimal.ONE, Range.RangeBoundary.OPEN), "( < 1
)" },
+ { new RangeImpl(Range.RangeBoundary.OPEN, new
UndefinedValueComparable(), BigDecimal.ONE, Range.RangeBoundary.CLOSED), "( <=
1 )" },
// context
{ new LinkedHashMap() {{ put( "Full Name", "John Doe"); put(
"Age", 35 ); put( "Date of Birth", LocalDate.of( 1982, 6, 9 ) ); }},
"{ Full Name : \"John Doe\", Age : 35, Date of Birth : date(
\"1982-06-09\" ) }" },
// null
- { null, "null" }
+ { null, "null" },
+ { new UndefinedValueComparable(), "undefined"}
};
return Arrays.asList( cases );
}
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerUnmarshallTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerUnmarshallTest.java
index aa2457b836..0635ac3640 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerUnmarshallTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/marshaller/FEELCodeMarshallerUnmarshallTest.java
@@ -37,6 +37,7 @@ import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
import static org.assertj.core.api.Assertions.assertThat;
@@ -91,13 +92,20 @@ public class FEELCodeMarshallerUnmarshallTest {
{ BuiltInType.UNKNOWN, "[ duration( \"P4D\" ), duration(
\"P2D\" ), duration( \"P1DT1H\" ) ]", Arrays.asList( Duration.ofDays( 4 ),
Duration.ofDays( 2 ), Duration.ofHours( 25 ) ) },
{ BuiltInType.UNKNOWN, "[ [ 1, 2 ], [ 3, 4 ] ]",
Arrays.asList( Arrays.asList( BigDecimal.valueOf( 1 ), BigDecimal.valueOf( 2 )
), Arrays.asList( BigDecimal.valueOf( 3 ), BigDecimal.valueOf( 4 ) ) ) },
// ranges
- { BuiltInType.UNKNOWN, "[ \"a\" .. \"z\" )", new RangeImpl(
Range.RangeBoundary.CLOSED, "a", "z", Range.RangeBoundary.OPEN ) },
- { BuiltInType.UNKNOWN, "[ duration( \"P1DT6H\" ) .. duration(
\"P2DT2H\" ) )", new RangeImpl( Range.RangeBoundary.CLOSED, Duration.ofHours(
30 ), Duration.ofHours( 50 ), Range.RangeBoundary.OPEN ) },
+ { BuiltInType.UNKNOWN, "[ \"a\" .. \"z\" )", new RangeImpl(
Range.RangeBoundary.CLOSED, "a", "z", Range.RangeBoundary.OPEN) },
+ { BuiltInType.UNKNOWN, "[ duration( \"P1DT6H\" ) .. duration(
\"P2DT2H\" ) )", new RangeImpl( Range.RangeBoundary.CLOSED, Duration.ofHours(
30 ), Duration.ofHours( 50 ), Range.RangeBoundary.OPEN) },
+
+ { BuiltInType.UNKNOWN, "( > 1 )", new
RangeImpl(Range.RangeBoundary.OPEN, BigDecimal.ONE, new
UndefinedValueComparable(), Range.RangeBoundary.OPEN)},
+ { BuiltInType.UNKNOWN, "( >= 1 )", new
RangeImpl(Range.RangeBoundary.CLOSED, BigDecimal.ONE, new
UndefinedValueComparable(), Range.RangeBoundary.OPEN) },
+ { BuiltInType.UNKNOWN, "( < 1 )", new
RangeImpl(Range.RangeBoundary.OPEN, new UndefinedValueComparable(),
BigDecimal.ONE, Range.RangeBoundary.OPEN)},
+ { BuiltInType.UNKNOWN, "( <= 1 )", new
RangeImpl(Range.RangeBoundary.OPEN, new UndefinedValueComparable(),
BigDecimal.ONE, Range.RangeBoundary.CLOSED) },
+
// context
{ BuiltInType.UNKNOWN, "{ Full Name : \"John Doe\", Age : 35,
Date of Birth : date( \"1982-06-09\" ) }",
new LinkedHashMap() {{ put( "Full Name", "John Doe"); put(
"Age", BigDecimal.valueOf( 35 ) ); put( "Date of Birth", LocalDate.of( 1982, 6,
9 ) ); }} },
// null
- { BuiltInType.UNKNOWN, "null", null }
+ { BuiltInType.UNKNOWN, "null", null },
+ { BuiltInType.UNKNOWN, "undefined", new
UndefinedValueComparable() }
};
return Arrays.asList( cases );
}
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserSeverityTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserSeverityTest.java
index 6f49989897..02851b82d2 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserSeverityTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserSeverityTest.java
@@ -83,7 +83,7 @@ class FEELParserSeverityTest {
@Test
void unexistentOperatorInvokeLTLT() {
- // RHDM-1119
+ // RHDM-1119
String inputExpression = "{ m: <<18 }.m(16)";
ASTNode number = parseSeverity(inputExpression,
FEELEvent.Severity.WARN);
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELRangesTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELRangesTest.java
index 780e31e96d..b2419f5263 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELRangesTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELRangesTest.java
@@ -31,6 +31,7 @@ import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.feel.lang.FEELDialect;
import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
public class FEELRangesTest extends BaseFEELTest {
@@ -42,6 +43,13 @@ public class FEELRangesTest extends BaseFEELTest {
private static Collection<Object[]> data() {
final Object[][] cases = new Object[][]{
+ // when converting from unary tests, boundaries are dictated
by comparison
+ {"(>1)", new RangeImpl(Range.RangeBoundary.OPEN,
BigDecimal.ONE, new UndefinedValueComparable(), Range.RangeBoundary.OPEN),
null},
+ {"(>=1)", new RangeImpl(Range.RangeBoundary.CLOSED,
BigDecimal.ONE, new UndefinedValueComparable(), Range.RangeBoundary.OPEN),
null},
+ {"(<1)", new RangeImpl(Range.RangeBoundary.OPEN, new
UndefinedValueComparable(), BigDecimal.ONE, Range.RangeBoundary.OPEN), null},
+ {"(<=1)", new RangeImpl(Range.RangeBoundary.OPEN, new
UndefinedValueComparable(), BigDecimal.ONE, Range.RangeBoundary.CLOSED), null},
+ {"(null..10)", new RangeImpl(Range.RangeBoundary.OPEN, null,
BigDecimal.valueOf(10), Range.RangeBoundary.OPEN), null},
+
{"[1..2]", new RangeImpl(Range.RangeBoundary.CLOSED,
BigDecimal.ONE, BigDecimal.valueOf(2), Range.RangeBoundary.CLOSED), null},
{"[2..1]", new RangeImpl(Range.RangeBoundary.CLOSED,
BigDecimal.valueOf(2), BigDecimal.ONE, Range.RangeBoundary.CLOSED), null},
{"[1..2)", new RangeImpl(Range.RangeBoundary.CLOSED,
BigDecimal.ONE, BigDecimal.valueOf(2), Range.RangeBoundary.OPEN), null},
@@ -161,7 +169,7 @@ public class FEELRangesTest extends BaseFEELTest {
put("enddate", LocalDate.of(1978, 10, 13));
put("rangedates", new
RangeImpl(Range.RangeBoundary.CLOSED, LocalDate.of(1978, 9, 12),
LocalDate.of(1978, 10, 13), Range.RangeBoundary.CLOSED));
}}, null},
-
+
// Table 42:
{"[1..10].start included", Boolean.TRUE, null},
{"[1..10].start", new BigDecimal(1), null},
@@ -172,12 +180,14 @@ public class FEELRangesTest extends BaseFEELTest {
{"(1..10].end", new BigDecimal(10), null},
{"(1..10].end included", Boolean.TRUE, null},
{"(<=10).start included", Boolean.FALSE, null},
+ {"(<10).start", null, null},
{"(<=10).start", null, null},
{"(<=10).end", new BigDecimal(10), null},
{"(<=10).end included", Boolean.TRUE, null},
{"(>1).start included", Boolean.FALSE, null},
{"(>1).start", new BigDecimal(1), null},
{"(>1).end", null, null},
+ {"(>=1).end", null, null},
{"(>1).end included", Boolean.FALSE, null},
};
return addAdditionalParameters(cases, false);
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/impl/RangeImplTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/impl/RangeImplTest.java
index 6201fe90b1..521abb12fc 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/impl/RangeImplTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/impl/RangeImplTest.java
@@ -25,6 +25,24 @@ import static org.assertj.core.api.Assertions.assertThat;
class RangeImplTest {
+ @Test
+ void isWithUndefined() {
+ RangeImpl rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, null,
null, Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isFalse();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, 10, null,
Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isFalse();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, null, 10,
Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isFalse();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, null, new
UndefinedValueComparable(), Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isTrue();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, new
UndefinedValueComparable(), null, Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isTrue();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, 10, new
UndefinedValueComparable(), Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isTrue();
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, new
UndefinedValueComparable(), 10, Range.RangeBoundary.OPEN);
+ assertThat(rangeImpl.isWithUndefined()).isTrue();
+ }
+
@Test
void getLowBoundary() {
final Range.RangeBoundary lowBoundary = Range.RangeBoundary.CLOSED;
@@ -77,6 +95,26 @@ class RangeImplTest {
assertThat(rangeImpl.includes(10)).isTrue();
assertThat(rangeImpl.includes(12)).isTrue();
assertThat(rangeImpl.includes(15)).isTrue();
+
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, new
UndefinedValueComparable(), 15, Range.RangeBoundary.CLOSED);
+ assertThat(rangeImpl.includes(-1456)).isTrue();
+ assertThat(rangeImpl.includes(20)).isFalse();
+ assertThat(rangeImpl.includes(null)).isNull();
+
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, 15, new
UndefinedValueComparable(), Range.RangeBoundary.CLOSED);
+ assertThat(rangeImpl.includes(-1456)).isFalse();
+ assertThat(rangeImpl.includes(20)).isTrue();
+ assertThat(rangeImpl.includes(null)).isNull();
+
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, null, new
UndefinedValueComparable(), Range.RangeBoundary.CLOSED);
+ assertThat(rangeImpl.includes(-1456)).isNull();
+ assertThat(rangeImpl.includes(20)).isNull();
+ assertThat(rangeImpl.includes(null)).isNull();
+
+ rangeImpl = new RangeImpl(Range.RangeBoundary.CLOSED, new
UndefinedValueComparable(), null, Range.RangeBoundary.CLOSED);
+ assertThat(rangeImpl.includes(-1456)).isNull();
+ assertThat(rangeImpl.includes(20)).isNull();
+ assertThat(rangeImpl.includes(null)).isNull();
}
@Test
diff --git
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
index 84bdbc3683..e82e068c88 100644
---
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
+++
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
@@ -55,6 +55,7 @@ import org.kie.dmn.feel.lang.ast.RangeNode.IntervalBoundary;
import org.kie.dmn.feel.lang.ast.UnaryTestListNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode;
import org.kie.dmn.feel.lang.ast.UnaryTestNode.UnaryOperator;
+import org.kie.dmn.feel.lang.ast.UndefinedValueNode;
import org.kie.dmn.feel.lang.ast.Visitor;
import org.kie.dmn.feel.lang.impl.FEELBuilder;
import org.kie.dmn.feel.lang.impl.InterpretedExecutableExpression;
@@ -289,9 +290,9 @@ public class DMNDTAnalyser implements InternalDMNDTAnalyser
{
}
private Optional<BaseNode> checkForDiamondRange(RangeNode rangeNode) {
- if ((rangeNode.getStart() instanceof NullNode || rangeNode.getStart()
== null) && rangeNode.getUpperBound() == IntervalBoundary.OPEN &&
rangeNode.getEnd() instanceof RangeNode) {
+ if ((rangeNode.getStart() instanceof NullNode || rangeNode.getStart()
instanceof UndefinedValueNode || rangeNode.getStart() == null) &&
rangeNode.getUpperBound() == IntervalBoundary.OPEN && rangeNode.getEnd()
instanceof RangeNode) {
return Optional.ofNullable(((RangeNode)
rangeNode.getEnd()).getStart()); // <> value
- } else if ((rangeNode.getEnd() instanceof NullNode ||
rangeNode.getEnd() == null) && rangeNode.getLowerBound() ==
IntervalBoundary.OPEN && rangeNode.getStart() instanceof RangeNode) {
+ } else if ((rangeNode.getEnd() instanceof NullNode ||
rangeNode.getEnd() instanceof UndefinedValueNode || rangeNode.getEnd() ==
null) && rangeNode.getLowerBound() == IntervalBoundary.OPEN &&
rangeNode.getStart() instanceof RangeNode) {
return Optional.ofNullable(((RangeNode)
rangeNode.getStart()).getEnd()); // >< value
} else {
return Optional.empty();
@@ -751,14 +752,15 @@ public class DMNDTAnalyser implements
InternalDMNDTAnalyser {
return new Interval(RangeBoundary.CLOSED,
valueFromNode(ut.getValue()), minMax.getUpperBound().getValue(),
minMax.getUpperBound().getBoundaryType(), rule, col);
} else if (ut.getValue() instanceof RangeNode) {
RangeNode rangeNode = (RangeNode) ut.getValue();
- if (!(rangeNode.getStart() instanceof NullNode ||
rangeNode.getEnd() instanceof NullNode)) {
+ if (!(rangeNode.getStart() instanceof NullNode ||
rangeNode.getStart() instanceof UndefinedValueNode ||
+ rangeNode.getEnd() instanceof NullNode ||
rangeNode.getEnd() instanceof UndefinedValueNode)) {
return new Interval(rangeNode.getLowerBound() ==
IntervalBoundary.OPEN ? RangeBoundary.OPEN : RangeBoundary.CLOSED,
valueFromNode(rangeNode.getStart()),
valueFromNode(rangeNode.getEnd()),
rangeNode.getUpperBound() ==
IntervalBoundary.OPEN ? RangeBoundary.OPEN : RangeBoundary.CLOSED,
rule,
col);
- } else if (rangeNode.getStart() instanceof NullNode) {
+ } else if (rangeNode.getStart() instanceof NullNode ||
rangeNode.getStart() instanceof UndefinedValueNode) {
return new Interval(minMax.getLowerBound().getBoundaryType(),
minMax.getLowerBound().getValue(),
valueFromNode(rangeNode.getEnd()),
diff --git
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/model/Interval.java
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/model/Interval.java
index bb9c9ca09c..fb4ebccc8a 100644
---
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/model/Interval.java
+++
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/model/Interval.java
@@ -30,6 +30,7 @@ import java.util.stream.Stream;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.Range.RangeBoundary;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
+import org.kie.dmn.feel.runtime.impl.UndefinedValueComparable;
import org.kie.dmn.feel.util.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -99,7 +100,7 @@ public class Interval {
if (input != POS_INF && input != NEG_INF) {
return input;
} else {
- return null;
+ return new UndefinedValueComparable();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]