From 925403bb215494ccbc9337be3bc88f60f4ba9483 Mon Sep 17 00:00:00 2001 From: Octavian Patrascoiu Date: Mon, 28 Oct 2024 12:40:37 +0000 Subject: [PATCH] [#655] DMN 1.5: Clarify edge cases for unary tests with ranges (DMN15-78). Move mapping for Operator Ranges in constructor of Range --- .../AbstractFEELInterpreterVisitor.java | 26 ++------- .../synthesis/AbstractFEELToJavaVisitor.java | 16 +++++- .../synthesis/FEELToTripleNativeVisitor.java | 29 ++-------- .../dmn/feel/AbstractFEELProcessorTest.java | 42 +++++++------- .../AbstractStandardFEELProcessorTest.java | 18 +++--- .../main/java/com/gs/dmn/runtime/Range.java | 57 ++++++++++++++++--- .../range/AbstractDefaultRangeLibTest.java | 18 +++--- 7 files changed, 112 insertions(+), 94 deletions(-) diff --git a/dmn-core/src/main/java/com/gs/dmn/feel/interpreter/AbstractFEELInterpreterVisitor.java b/dmn-core/src/main/java/com/gs/dmn/feel/interpreter/AbstractFEELInterpreterVisitor.java index 9fb58a469..8316ebb11 100644 --- a/dmn-core/src/main/java/com/gs/dmn/feel/interpreter/AbstractFEELInterpreterVisitor.java +++ b/dmn-core/src/main/java/com/gs/dmn/feel/interpreter/AbstractFEELInterpreterVisitor.java @@ -138,7 +138,7 @@ public Object visit(ExpressionTest element, DMNContext context) { public Object visit(OperatorRange element, DMNContext context) { LOGGER.debug("Visiting element '{}'", element); - String operator = element.getOperator(); + String operator = normalizeOperator(element.getOperator()); Type inputExpressionType = context.getInputExpressionType(); Expression endpoint = element.getEndpoint(); Type endpointType = endpoint.getType(); @@ -152,20 +152,14 @@ public Object visit(OperatorRange element, DMNContext context) { Object self = context.lookupBinding(INPUT_ENTRY_PLACE_HOLDER); if (Type.sameSemanticDomain(endpointType, inputExpressionType)) { // input and endpoint are comparable - Object condition; - if (operator == null) { - condition = evaluateOperatorRange(element, "=", self, endpoint, context); - } else { - condition = evaluateOperatorRange(element, operator, self, endpoint, context); - } - return condition; + return evaluateOperatorRange(element, operator, self, endpoint, context); } else if (endpointType instanceof ListType) { Type endpointElementType = ((ListType) endpointType).getElementType(); if (Type.sameSemanticDomain(endpointElementType, inputExpressionType)) { // input and list elements are comparable List endpointValueList = (List) endpoint.accept(this, context); List results = new ArrayList(); - for(Object endpointValue: endpointValueList) { + for (Object endpointValue: endpointValueList) { results.add(evaluateOperatorRange(element, "=", self, inputExpressionType, ((ListType) endpointType).getElementType(), endpointValue)); } return this.lib.or(results); @@ -185,18 +179,8 @@ public Object visit(OperatorRange element, DMNContext context) { private Object evaluateOperatorRange(Expression element, String operator, Object self, Expression endpointExpression, DMNContext context) throws Exception { Object endpointValue = endpointExpression.accept(this, context); if (context.isExpressionContext()) { - if (operator == null || "=".equals(operator)) { - return new Range(true, endpointValue, true, endpointValue, "="); - } else if ("!=".equals(operator)) { - return new Range(false, endpointValue, false, endpointValue, operator); - } else if ("<".equals(operator)) { - return new Range(false, null, false, endpointValue, operator); - } else if ("<=".equals(operator)) { - return new Range(false, null, true, endpointValue, operator); - } else if (">".equals(operator)) { - return new Range(false, endpointValue, false, null, operator); - } else if (">=".equals(operator)) { - return new Range(true, endpointValue, false, null, operator); + if (isValidRangeOperator(operator)) { + return new Range(operator, endpointValue); } else { throw new DMNRuntimeException(String.format("Unknown operator '%s'", operator)); } diff --git a/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/AbstractFEELToJavaVisitor.java b/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/AbstractFEELToJavaVisitor.java index 705e22a79..c1255c6dd 100644 --- a/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/AbstractFEELToJavaVisitor.java +++ b/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/AbstractFEELToJavaVisitor.java @@ -24,9 +24,7 @@ import com.gs.dmn.transformation.basic.BasicDMNToNativeTransformer; import org.apache.commons.lang3.StringUtils; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public abstract class AbstractFEELToJavaVisitor extends AbstractAnalysisVisitor { private static final Map FEEL_2_JAVA_FUNCTION = new LinkedHashMap<>(); @@ -77,6 +75,10 @@ public abstract class AbstractFEELToJavaVisitor extends AbstractAnalysisVisit FEEL_2_JAVA_FUNCTION.put("week of year", "weekOfYear"); } + private static final Set RANGE_OPERATORS = new LinkedHashSet<>( + Arrays.asList("=", "!=", "<", "<=", ">", ">=") + ); + public AbstractFEELToJavaVisitor(BasicDMNToNativeTransformer dmnTransformer) { super(dmnTransformer, new LogAndThrowErrorHandler(LOGGER)); } @@ -116,4 +118,12 @@ protected String functionName(Object function) { return null; } } + + protected static String normalizeOperator(String operator) { + return StringUtils.isBlank(operator) ? "=" : operator; + } + + protected static boolean isValidRangeOperator(String operator) { + return RANGE_OPERATORS.contains(operator); + } } diff --git a/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/FEELToTripleNativeVisitor.java b/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/FEELToTripleNativeVisitor.java index 984d970a7..52e48106b 100644 --- a/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/FEELToTripleNativeVisitor.java +++ b/dmn-core/src/main/java/com/gs/dmn/feel/synthesis/FEELToTripleNativeVisitor.java @@ -112,28 +112,15 @@ public Triple visit(ExpressionTest element, DMNContext context) { @Override public Triple visit(OperatorRange element, DMNContext context) { - String operator = element.getOperator(); + String operator = normalizeOperator(element.getOperator()); Expression endpoint = element.getEndpoint(); if (context.isExpressionContext()) { // Evaluate as range Triple endpointValue = (Triple) endpoint.accept(this, context); - Triple trueValue = this.triples.booleanValueConstant("true"); - Triple falseValue = this.triples.booleanValueConstant("false"); - Triple nullValue = this.triples.nullLiteral(); - Triple operatorValue = this.triples.text(operator == null ? "=" : operator); + Triple operatorValue = this.triples.text(operator); List arguments; - if (operator == null || "=".equals(operator)) { - arguments = Arrays.asList(trueValue, endpointValue, trueValue, endpointValue, operatorValue); - } else if ("!=".equals(operator)) { - arguments = Arrays.asList(falseValue, endpointValue, falseValue, endpointValue, operatorValue); - } else if ("<".equals(operator)) { - arguments = Arrays.asList(falseValue, nullValue, falseValue, endpointValue, operatorValue); - } else if ("<=".equals(operator)) { - arguments = Arrays.asList(falseValue, nullValue, trueValue, endpointValue, operatorValue); - } else if (">".equals(operator)) { - arguments = Arrays.asList(falseValue, endpointValue, falseValue, nullValue, operatorValue); - } else if (">=".equals(operator)) { - arguments = Arrays.asList(trueValue, endpointValue, falseValue, nullValue, operatorValue); + if (isValidRangeOperator(operator)) { + arguments = Arrays.asList(operatorValue, endpointValue); } else { throw new DMNRuntimeException(String.format("Unknown operator '%s'", operator)); } @@ -145,13 +132,7 @@ public Triple visit(OperatorRange element, DMNContext context) { Type endpointType = endpoint.getType(); if (Type.sameSemanticDomain(endpointType, inputExpressionType)) { // input and endpoint are comparable - Triple condition; - if (operator == null) { - condition = makeRangeCondition("=", (Expression) context.getInputExpression(), endpoint, context); - } else { - condition = makeRangeCondition(operator, (Expression) context.getInputExpression(), endpoint, context); - } - return condition; + return makeRangeCondition(operator, (Expression) context.getInputExpression(), endpoint, context); } else if (endpointType instanceof ListType) { Type endpointElementType = ((ListType) endpointType).getElementType(); if (Type.sameSemanticDomain(endpointElementType, inputExpressionType)) { diff --git a/dmn-core/src/test/java/com/gs/dmn/feel/AbstractFEELProcessorTest.java b/dmn-core/src/test/java/com/gs/dmn/feel/AbstractFEELProcessorTest.java index 0cf3ae5eb..a7a4d3b2f 100644 --- a/dmn-core/src/test/java/com/gs/dmn/feel/AbstractFEELProcessorTest.java +++ b/dmn-core/src/test/java/com/gs/dmn/feel/AbstractFEELProcessorTest.java @@ -1148,38 +1148,38 @@ public void testRelationalExpression() { doExpressionTest(entries, "", "(< 10) = (null..10)", "Relational(=,OperatorRange(<,NumericLiteral(10)),EndpointsRange(true,NullLiteral(),true,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, number(\"10\"), \"<\"), new com.gs.dmn.runtime.Range(false, null, false, number(\"10\")))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"), "<"), new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"))), + "rangeEqual(new com.gs.dmn.runtime.Range(\"<\", number(\"10\")), new com.gs.dmn.runtime.Range(false, null, false, number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("<", this.lib.number("10")), new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"))), false); doExpressionTest(entries, "", "(<= 10) = (null..10]", "Relational(=,OperatorRange(<=,NumericLiteral(10)),EndpointsRange(true,NullLiteral(),false,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, null, true, number(\"10\"), \"<=\"), new com.gs.dmn.runtime.Range(false, null, true, number(\"10\")))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, null, true, this.lib.number("10"), "<="), new com.gs.dmn.runtime.Range(false, null, true, this.lib.number("10"))), + "rangeEqual(new com.gs.dmn.runtime.Range(\"<=\", number(\"10\")), new com.gs.dmn.runtime.Range(false, null, true, number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("<=", this.lib.number("10")), new com.gs.dmn.runtime.Range(false, null, true, this.lib.number("10"))), false); doExpressionTest(entries, "", "(> 10) = (10..null)", "Relational(=,OperatorRange(>,NumericLiteral(10)),EndpointsRange(true,NumericLiteral(10),true,NullLiteral()))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, number(\"10\"), false, null, \">\"), new com.gs.dmn.runtime.Range(false, number(\"10\"), false, null))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, null, ">"), new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, null)), + "rangeEqual(new com.gs.dmn.runtime.Range(\">\", number(\"10\")), new com.gs.dmn.runtime.Range(false, number(\"10\"), false, null))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range(">", this.lib.number("10")), new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, null)), false); doExpressionTest(entries, "", "(>= 10) = [10..null)", "Relational(=,OperatorRange(>=,NumericLiteral(10)),EndpointsRange(false,NumericLiteral(10),true,NullLiteral()))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null, \">=\"), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null, ">="), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null)), + "rangeEqual(new com.gs.dmn.runtime.Range(\">=\", number(\"10\")), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range(">=", this.lib.number("10")), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null)), false); doExpressionTest(entries, "", "(=10) = [10..10]", "Relational(=,OperatorRange(=,NumericLiteral(10)),EndpointsRange(false,NumericLiteral(10),false,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(true, number(\"10\"), true, number(\"10\"), \"=\"), new com.gs.dmn.runtime.Range(true, number(\"10\"), true, number(\"10\")))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(true, this.lib.number("10"), true, this.lib.number("10"), "="), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), true, this.lib.number("10"))), + "rangeEqual(new com.gs.dmn.runtime.Range(\"=\", number(\"10\")), new com.gs.dmn.runtime.Range(true, number(\"10\"), true, number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("=", this.lib.number("10")), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), true, this.lib.number("10"))), false); doExpressionTest(entries, "", "(!=10) = (!=10)", "Relational(=,OperatorRange(!=,NumericLiteral(10)),OperatorRange(!=,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, number(\"10\"), false, number(\"10\"), \"!=\"), new com.gs.dmn.runtime.Range(false, number(\"10\"), false, number(\"10\"), \"!=\"))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, this.lib.number("10"), "!="), new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, this.lib.number("10"), "!=")), + "rangeEqual(new com.gs.dmn.runtime.Range(\"!=\", number(\"10\")), new com.gs.dmn.runtime.Range(\"!=\", number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("!=", this.lib.number("10")), new com.gs.dmn.runtime.Range("!=", this.lib.number("10"))), true); } @@ -2640,7 +2640,7 @@ public void testList() { doExpressionTest(expressionPairs, "", "[1, <2, [3..4]]", "ListLiteral(NumericLiteral(1),OperatorRange(<,NumericLiteral(2)),EndpointsRange(false,NumericLiteral(3),false,NumericLiteral(4)))", "ListType(Any)", - "asList(number(\"1\"), new com.gs.dmn.runtime.Range(false, null, false, number(\"2\"), \"<\"), new com.gs.dmn.runtime.Range(true, number(\"3\"), true, number(\"4\")))", + "asList(number(\"1\"), new com.gs.dmn.runtime.Range(\"<\", number(\"2\")), new com.gs.dmn.runtime.Range(true, number(\"3\"), true, number(\"4\")))", null, null); @@ -2853,14 +2853,14 @@ public void testTypeIsMissing() { doExpressionTest(entries, "", "(< 10) = (null_input..10)", "Relational(=,OperatorRange(<,NumericLiteral(10)),EndpointsRange(true,Name(null_input),true,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, number(\"10\"), \"<\"), new com.gs.dmn.runtime.Range(false, null_input, false, number(\"10\")))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"), "<"), new com.gs.dmn.runtime.Range(false, null_input, false, this.lib.number("10"))), + "rangeEqual(new com.gs.dmn.runtime.Range(\"<\", number(\"10\")), new com.gs.dmn.runtime.Range(false, null_input, false, number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("<", this.lib.number("10")), new com.gs.dmn.runtime.Range(false, null_input, false, this.lib.number("10"))), false); doExpressionTest(entries, "", "(>=; 10) = [10..null_input)", "Relational(=,OperatorRange(>=,NumericLiteral(10)),EndpointsRange(false,NumericLiteral(10),true,Name(null_input)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null, \">=\"), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null_input))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null, ">="), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null_input)), + "rangeEqual(new com.gs.dmn.runtime.Range(\">=\", number(\"10\")), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null_input))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range(">=", this.lib.number("10")), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null_input)), false); } @@ -2883,14 +2883,14 @@ public void testTypeIsAny() { doExpressionTest(entries, "", "(< 10) = (null_input..10)", "Relational(=,OperatorRange(<,NumericLiteral(10)),EndpointsRange(true,Name(null_input),true,NumericLiteral(10)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, number(\"10\"), \"<\"), new com.gs.dmn.runtime.Range(false, null_input, false, number(\"10\")))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"), "<"), new com.gs.dmn.runtime.Range(false, null_input, false, this.lib.number("10"))), + "rangeEqual(new com.gs.dmn.runtime.Range(\"<\", number(\"10\")), new com.gs.dmn.runtime.Range(false, null_input, false, number(\"10\")))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range("<", this.lib.number("10")), new com.gs.dmn.runtime.Range(false, null_input, false, this.lib.number("10"))), false); doExpressionTest(entries, "", "(>=; 10) = [10..null_input)", "Relational(=,OperatorRange(>=,NumericLiteral(10)),EndpointsRange(false,NumericLiteral(10),true,Name(null_input)))", "boolean", - "rangeEqual(new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null, \">=\"), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null_input))", - this.lib.rangeEqual(new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null, ">="), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null_input)), + "rangeEqual(new com.gs.dmn.runtime.Range(\">=\", number(\"10\")), new com.gs.dmn.runtime.Range(true, number(\"10\"), false, null_input))", + this.lib.rangeEqual(new com.gs.dmn.runtime.Range(">=", this.lib.number("10")), new com.gs.dmn.runtime.Range(true, this.lib.number("10"), false, null_input)), false); } diff --git a/dmn-core/src/test/java/com/gs/dmn/feel/AbstractStandardFEELProcessorTest.java b/dmn-core/src/test/java/com/gs/dmn/feel/AbstractStandardFEELProcessorTest.java index 7ba2a9ae6..7b95e05e8 100644 --- a/dmn-core/src/test/java/com/gs/dmn/feel/AbstractStandardFEELProcessorTest.java +++ b/dmn-core/src/test/java/com/gs/dmn/feel/AbstractStandardFEELProcessorTest.java @@ -46,7 +46,7 @@ public void testOperatorRange() { NUMBER number = this.lib.number("15"); DATE date = this.lib.date("2015-01-01"); - Range range = new Range(false, null, true, this.lib.number("10"), ">="); + Range range = new Range(">=", this.lib.number("10")); List entries = Arrays.asList( new EnvironmentEntry("number", NUMBER, number), new EnvironmentEntry("date", DateType.DATE, date), @@ -1726,29 +1726,29 @@ public void testRangeProperties() { doExpressionTest(entries, "", "(< 10).start", "PathExpression(OperatorRange(<,NumericLiteral(10)), start)", "number", - "new com.gs.dmn.runtime.Range(false, null, false, number(\"10\"), \"<\").getStart()", - new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"), "<").getStart(), + "new com.gs.dmn.runtime.Range(\"<\", number(\"10\")).getStart()", + new com.gs.dmn.runtime.Range("<", this.lib.number("10")).getStart(), null); doExpressionTest(entries, "", "(<= 10).end", "PathExpression(OperatorRange(<=,NumericLiteral(10)), end)", "number", - "new com.gs.dmn.runtime.Range(false, null, true, number(\"10\"), \"<=\").getEnd()", - new com.gs.dmn.runtime.Range(false, null, true, this.lib.number("10"), "<=").getEnd(), + "new com.gs.dmn.runtime.Range(\"<=\", number(\"10\")).getEnd()", + new com.gs.dmn.runtime.Range("<=", this.lib.number("10")).getEnd(), this.lib.number("10")); doExpressionTest(entries, "", "(< 10).start included", "PathExpression(OperatorRange(<,NumericLiteral(10)), start included)", "boolean", - "new com.gs.dmn.runtime.Range(false, null, false, number(\"10\"), \"<\").isStartIncluded()", - new com.gs.dmn.runtime.Range(false, null, false, this.lib.number("10"), "<").isStartIncluded(), + "new com.gs.dmn.runtime.Range(\"<\", number(\"10\")).isStartIncluded()", + new com.gs.dmn.runtime.Range("<", this.lib.number("10")).isStartIncluded(), false); doExpressionTest(entries, "", "(> 10).end included", "PathExpression(OperatorRange(>,NumericLiteral(10)), end included)", "boolean", - "new com.gs.dmn.runtime.Range(false, number(\"10\"), false, null, \">\").isEndIncluded()", - new com.gs.dmn.runtime.Range(false, this.lib.number("10"), false, null, ">").isEndIncluded(), + "new com.gs.dmn.runtime.Range(\">\", number(\"10\")).isEndIncluded()", + new com.gs.dmn.runtime.Range(">", this.lib.number("10")).isEndIncluded(), false); } diff --git a/dmn-runtime/src/main/java/com/gs/dmn/runtime/Range.java b/dmn-runtime/src/main/java/com/gs/dmn/runtime/Range.java index d1c5dc247..6b7dd6a23 100644 --- a/dmn-runtime/src/main/java/com/gs/dmn/runtime/Range.java +++ b/dmn-runtime/src/main/java/com/gs/dmn/runtime/Range.java @@ -12,6 +12,8 @@ */ package com.gs.dmn.runtime; +import org.apache.commons.lang3.StringUtils; + import java.util.Objects; public class Range { @@ -22,7 +24,11 @@ public class Range { private final String operator; public Range() { - this(false, null, false, null, null); + this.startIncluded = false; + this.start = null; + this.endIncluded = false; + this.end = null; + this.operator = null; } public Range(boolean startIncluded, Object start, boolean endIncluded, Object end) { @@ -33,12 +39,49 @@ public Range(boolean startIncluded, Object start, boolean endIncluded, Object en this.operator = null; } - public Range(boolean startIncluded, Object start, boolean endIncluded, Object end, String operator) { - this.startIncluded = startIncluded; - this.start = start; - this.endIncluded = endIncluded; - this.end = end; - this.operator = operator; + public Range(String operator, Object endpoint) { + this.operator = StringUtils.isBlank(operator) ? "=" : operator; + // 10.3.2.7 Ranges + switch (this.operator) { + case "=": + startIncluded = true; + start = endpoint; + end = endpoint; + endIncluded = true; + break; + case "!=": + startIncluded = false; + start = null; + end = null; + endIncluded = false; + break; + case "<": + startIncluded = false; + start = null; + end = endpoint; + endIncluded = false; + break; + case "<=": + startIncluded = false; + start = null; + end = endpoint; + endIncluded = true; + break; + case ">": + startIncluded = false; + start = endpoint; + end = null; + endIncluded = false; + break; + case ">=": + startIncluded = true; + start = endpoint; + end = null; + endIncluded = false; + break; + default: + throw new DMNRuntimeException(String.format("Illegal operator '%s'", this.operator)); + } } public boolean isStartIncluded() { diff --git a/dmn-runtime/src/test/java/com/gs/dmn/feel/lib/type/range/AbstractDefaultRangeLibTest.java b/dmn-runtime/src/test/java/com/gs/dmn/feel/lib/type/range/AbstractDefaultRangeLibTest.java index 1ef0372e2..a35037ded 100644 --- a/dmn-runtime/src/test/java/com/gs/dmn/feel/lib/type/range/AbstractDefaultRangeLibTest.java +++ b/dmn-runtime/src/test/java/com/gs/dmn/feel/lib/type/range/AbstractDefaultRangeLibTest.java @@ -253,23 +253,23 @@ public void testCoincides() { @Test public void testOperatorRanges() { // 5 before <= 10 - assertNull(getLib().before(makePoint(5), new Range(false, null, true, makePoint(10), "<=") )); + assertNull(getLib().before(makePoint(5), new Range("<=", makePoint(10)) )); // 5 after <= 10 - assertFalse(getLib().after(makePoint(5), new Range(false, null, true, makePoint(10), "<=") )); + assertFalse(getLib().after(makePoint(5), new Range("<=", makePoint(10)) )); // 5 finishes <= 5 - assertTrue(getLib().finishes(makePoint(5), new Range(false, null, true, makePoint(5), "<=") )); + assertTrue(getLib().finishes(makePoint(5), new Range("<=", makePoint(5)) )); // <= 5 finished by 5 - assertNull(getLib().finishedBy(new Range(false, null, true, makePoint(5), "<="), makePoint(5) )); + assertNull(getLib().finishedBy(new Range("<=", makePoint(5)), makePoint(5) )); // <= 10 includes 5 - assertNull(getLib().includes(new Range(false, null, true, makePoint(10), "<="), makePoint(5) )); + assertNull(getLib().includes(new Range("<=", makePoint(10)), makePoint(5) )); // 5 during <= 10 - assertNull(getLib().during(makePoint(5), new Range(false, null, true, makePoint(10), "<=") )); + assertNull(getLib().during(makePoint(5), new Range("<=", makePoint(10)) )); // 5 starts <= 5 - assertFalse(getLib().starts(makePoint(5), new Range(false, null, true, makePoint(5), "<=") )); + assertFalse(getLib().starts(makePoint(5), new Range("<=", makePoint(5)) )); // <= 5 started by 5 - assertFalse(getLib().startedBy(new Range(false, null, true, makePoint(5), "<="), makePoint(5) )); + assertFalse(getLib().startedBy(new Range("<=", makePoint(5)), makePoint(5) )); // <= 5 coincides <= 5 - assertNull(getLib().coincides(new Range(false, null, true, makePoint(5), "<="), new Range(false, null, true, makePoint(5), "<=") )); + assertNull(getLib().coincides(new Range("<=", makePoint(5)), new Range("<=", makePoint(5)) )); } private Range makeRange(String startIncluded, int start, int end, String endIncluded) {