Search in sources :

Example 1 with UnaryTestNode

use of org.kie.dmn.feel.lang.ast.UnaryTestNode in project drools by kiegroup.

the class DMNDTAnalyser method compileTableInputClauses.

private void compileTableInputClauses(DMNModel model, DecisionTable dt, DDTATable ddtaTable) {
    for (int jColIdx = 0; jColIdx < dt.getInput().size(); jColIdx++) {
        InputClause ie = dt.getInput().get(jColIdx);
        Interval infDomain = new Interval(RangeBoundary.CLOSED, Interval.NEG_INF, Interval.POS_INF, RangeBoundary.CLOSED, 0, jColIdx + 1);
        String allowedValues;
        if (ie.getInputValues() != null) {
            allowedValues = ie.getInputValues().getText();
        } else {
            QName typeRef = DMNCompilerImpl.getNamespaceAndName(dt, ((DMNModelImpl) model).getImportAliasesForNS(), ie.getInputExpression().getTypeRef(), model.getNamespace());
            allowedValues = findAllowedValues(model, typeRef);
        }
        if (allowedValues != null) {
            ProcessedUnaryTest compileUnaryTests = (ProcessedUnaryTest) FEEL.compileUnaryTests(allowedValues, FEEL.newCompilerContext());
            UnaryTestInterpretedExecutableExpression interpreted = compileUnaryTests.getInterpreted();
            UnaryTestListNode utln = (UnaryTestListNode) interpreted.getASTNode();
            if (utln.getElements().size() != 1) {
                verifyUnaryTestsAllEQ(utln, dt);
                List<Comparable<?>> discreteValues = getDiscreteValues(utln);
                Collections.sort((List) discreteValues);
                Interval discreteDomainMinMax = new Interval(RangeBoundary.CLOSED, discreteValues.get(0), discreteValues.get(discreteValues.size() - 1), RangeBoundary.CLOSED, 0, jColIdx + 1);
                DDTAInputClause ic = new DDTAInputClause(discreteDomainMinMax, discreteValues, getDiscreteValues(utln));
                ddtaTable.getInputs().add(ic);
            } else if (utln.getElements().size() == 1) {
                UnaryTestNode utn0 = (UnaryTestNode) utln.getElements().get(0);
                Interval interval = utnToInterval(utn0, infDomain, null, 0, jColIdx + 1);
                DDTAInputClause ic = new DDTAInputClause(interval);
                ddtaTable.getInputs().add(ic);
            } else {
                throw new IllegalStateException("inputValues not null but utln: " + utln);
            }
        } else {
            DDTAInputClause ic = new DDTAInputClause(infDomain);
            ddtaTable.getInputs().add(ic);
        }
    }
}
Also used : UnaryTestNode(org.kie.dmn.feel.lang.ast.UnaryTestNode) QName(javax.xml.namespace.QName) ProcessedUnaryTest(org.kie.dmn.feel.codegen.feel11.ProcessedUnaryTest) UnaryTestInterpretedExecutableExpression(org.kie.dmn.feel.lang.impl.UnaryTestInterpretedExecutableExpression) UnaryTestListNode(org.kie.dmn.feel.lang.ast.UnaryTestListNode) DDTAInputClause(org.kie.dmn.validation.dtanalysis.model.DDTAInputClause) DDTAInputClause(org.kie.dmn.validation.dtanalysis.model.DDTAInputClause) InputClause(org.kie.dmn.model.api.InputClause) Interval(org.kie.dmn.validation.dtanalysis.model.Interval)

Example 2 with UnaryTestNode

use of org.kie.dmn.feel.lang.ast.UnaryTestNode in project drools by kiegroup.

the class DMNDTAnalyser method compileTableOutputClauses.

private void compileTableOutputClauses(DMNModel model, DecisionTable dt, DDTATable ddtaTable) {
    for (int jColIdx = 0; jColIdx < dt.getOutput().size(); jColIdx++) {
        OutputClause oe = dt.getOutput().get(jColIdx);
        Interval infDomain = new Interval(RangeBoundary.CLOSED, Interval.NEG_INF, Interval.POS_INF, RangeBoundary.CLOSED, 0, jColIdx + 1);
        String allowedValues = null;
        if (oe.getOutputValues() != null) {
            allowedValues = oe.getOutputValues().getText();
        } else {
            QName outputTypeRef = (oe.getTypeRef() == null && dt.getOutput().size() == 1) ? dt.getTypeRef() : oe.getTypeRef();
            if (outputTypeRef != null) {
                QName typeRef = DMNCompilerImpl.getNamespaceAndName(dt, ((DMNModelImpl) model).getImportAliasesForNS(), outputTypeRef, model.getNamespace());
                allowedValues = findAllowedValues(model, typeRef);
            }
        }
        if (allowedValues != null) {
            ProcessedUnaryTest compileUnaryTests = (ProcessedUnaryTest) FEEL.compileUnaryTests(allowedValues, FEEL.newCompilerContext());
            UnaryTestInterpretedExecutableExpression interpreted = compileUnaryTests.getInterpreted();
            UnaryTestListNode utln = (UnaryTestListNode) interpreted.getASTNode();
            if (utln.getElements().size() != 1) {
                verifyUnaryTestsAllEQ(utln, dt);
                List<Comparable<?>> discreteValues = getDiscreteValues(utln);
                List<Comparable<?>> outputOrder = new ArrayList<>(discreteValues);
                Collections.sort((List) discreteValues);
                Interval discreteDomainMinMax = new Interval(RangeBoundary.CLOSED, discreteValues.get(0), discreteValues.get(discreteValues.size() - 1), RangeBoundary.CLOSED, 0, jColIdx + 1);
                DDTAOutputClause ic = new DDTAOutputClause(discreteDomainMinMax, discreteValues, outputOrder);
                ddtaTable.getOutputs().add(ic);
            } else if (utln.getElements().size() == 1) {
                UnaryTestNode utn0 = (UnaryTestNode) utln.getElements().get(0);
                Interval interval = utnToInterval(utn0, infDomain, null, 0, jColIdx + 1);
                DDTAOutputClause ic = new DDTAOutputClause(interval);
                ddtaTable.getOutputs().add(ic);
            } else {
                throw new IllegalStateException("inputValues not null but utln: " + utln);
            }
        } else {
            DDTAOutputClause ic = new DDTAOutputClause(infDomain);
            ddtaTable.getOutputs().add(ic);
        }
    }
}
Also used : UnaryTestNode(org.kie.dmn.feel.lang.ast.UnaryTestNode) QName(javax.xml.namespace.QName) ArrayList(java.util.ArrayList) ProcessedUnaryTest(org.kie.dmn.feel.codegen.feel11.ProcessedUnaryTest) DDTAOutputClause(org.kie.dmn.validation.dtanalysis.model.DDTAOutputClause) OutputClause(org.kie.dmn.model.api.OutputClause) DDTAOutputClause(org.kie.dmn.validation.dtanalysis.model.DDTAOutputClause) UnaryTestInterpretedExecutableExpression(org.kie.dmn.feel.lang.impl.UnaryTestInterpretedExecutableExpression) UnaryTestListNode(org.kie.dmn.feel.lang.ast.UnaryTestListNode) Interval(org.kie.dmn.validation.dtanalysis.model.Interval)

Example 3 with UnaryTestNode

use of org.kie.dmn.feel.lang.ast.UnaryTestNode in project drools by kiegroup.

the class DMNDTAnalyser method getDiscreteValues.

/**
 * Transform a UnaryTestListNode into a List of discrete values for input/output clause enumeration
 */
private List<Comparable<?>> getDiscreteValues(UnaryTestListNode utln) {
    List<Comparable<?>> discreteValues = new ArrayList<>();
    for (BaseNode e : utln.getElements()) {
        BaseNode value = ((UnaryTestNode) e).getValue();
        if (!(value instanceof NullNode)) {
            // to retrieve value from input/output clause enumeration, null is ignored.
            Comparable<?> v = valueFromNode(value);
            discreteValues.add(v);
        }
    }
    return discreteValues;
}
Also used : UnaryTestNode(org.kie.dmn.feel.lang.ast.UnaryTestNode) ArrayList(java.util.ArrayList) BaseNode(org.kie.dmn.feel.lang.ast.BaseNode) NullNode(org.kie.dmn.feel.lang.ast.NullNode)

Example 4 with UnaryTestNode

use of org.kie.dmn.feel.lang.ast.UnaryTestNode in project drools by kiegroup.

the class FEELImpl method evaluateUnaryTests.

@Override
public List<UnaryTest> evaluateUnaryTests(String expression, Map<String, Type> variableTypes) {
    // DMN defines a special case where, unless the expressions are unary tests
    // or ranges, they need to be converted into an equality test unary expression.
    // This way, we have to compile and check the low level AST nodes to properly
    // deal with this case
    CompilerContext ctx = newCompilerContext();
    for (Map.Entry<String, Type> e : variableTypes.entrySet()) {
        ctx.addInputVariableType(e.getKey(), e.getValue());
    }
    CompiledExpressionImpl compiledExpression = (CompiledExpressionImpl) compileExpressionList(expression, ctx);
    if (compiledExpression != null) {
        ListNode listNode = (ListNode) compiledExpression.getExpression();
        List<BaseNode> tests = new ArrayList<>();
        for (BaseNode o : listNode.getElements()) {
            if (o == null) {
                // not much we can do, so just skip it. Error was reported somewhere else
                continue;
            } else if (o instanceof UnaryTestNode || o instanceof DashNode) {
                tests.add(o);
            } else if (o instanceof RangeNode || o instanceof ListNode) {
                tests.add(new UnaryTestNode("in", o));
            } else {
                tests.add(new UnaryTestNode("=", o));
            }
        }
        listNode.setElements(tests);
        compiledExpression.setExpression(listNode);
        // now we can evaluate the expression to build the list of unary tests
        List<UnaryTest> uts = (List<UnaryTest>) evaluate(compiledExpression, FEELImpl.EMPTY_INPUT);
        return uts;
    }
    return Collections.emptyList();
}
Also used : UnaryTestNode(org.kie.dmn.feel.lang.ast.UnaryTestNode) CompilerContext(org.kie.dmn.feel.lang.CompilerContext) BaseNode(org.kie.dmn.feel.lang.ast.BaseNode) ArrayList(java.util.ArrayList) ListNode(org.kie.dmn.feel.lang.ast.ListNode) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) Type(org.kie.dmn.feel.lang.Type) ArrayList(java.util.ArrayList) List(java.util.List) DashNode(org.kie.dmn.feel.lang.ast.DashNode) HashMap(java.util.HashMap) Map(java.util.Map) RangeNode(org.kie.dmn.feel.lang.ast.RangeNode)

Example 5 with UnaryTestNode

use of org.kie.dmn.feel.lang.ast.UnaryTestNode in project drools by kiegroup.

the class DMNDTAnalyser method toIntervals.

private List<Interval> toIntervals(List<BaseNode> elements, boolean isNegated, Interval minMax, List discreteValues, int rule, int col) {
    List<Interval> results = new ArrayList<>();
    if (elements.size() == 1 && elements.get(0) instanceof UnaryTestNode && ((UnaryTestNode) elements.get(0)).getValue() instanceof NullNode) {
        return Collections.emptyList();
    }
    if (discreteValues != null && !discreteValues.isEmpty() && areAllEQUnaryTest(elements) && elements.size() > 1) {
        // JDK BitSet size will always be larger.
        int bitsetLogicalSize = discreteValues.size();
        BitSet hitValues = new BitSet(bitsetLogicalSize);
        for (BaseNode n : elements) {
            Comparable<?> thisValue = valueFromNode(((UnaryTestNode) n).getValue());
            int indexOf = discreteValues.indexOf(thisValue);
            if (indexOf < 0) {
                throw new IllegalStateException("Unable to determine discreteValue index for: " + n);
            }
            hitValues.set(indexOf);
        }
        if (isNegated) {
            hitValues.flip(0, bitsetLogicalSize);
        }
        int lowerBoundIdx = -1;
        int upperBoundIdx = -1;
        for (int i = 0; i < hitValues.length(); i++) {
            boolean curValue = hitValues.get(i);
            if (curValue) {
                if (lowerBoundIdx < 0) {
                    lowerBoundIdx = i;
                    upperBoundIdx = i;
                } else {
                    upperBoundIdx = i;
                }
            } else {
                if (lowerBoundIdx >= 0 && upperBoundIdx >= 0) {
                    results.add(createIntervalOfRule(discreteValues, rule, col, lowerBoundIdx, upperBoundIdx));
                    lowerBoundIdx = -1;
                    upperBoundIdx = -1;
                }
            }
        }
        if (lowerBoundIdx >= 0 && upperBoundIdx >= 0) {
            results.add(createIntervalOfRule(discreteValues, rule, col, lowerBoundIdx, upperBoundIdx));
        }
    } else {
        for (BaseNode n : elements) {
            if (n instanceof DashNode) {
                results.add(new Interval(minMax.getLowerBound().getBoundaryType(), minMax.getLowerBound().getValue(), minMax.getUpperBound().getValue(), minMax.getUpperBound().getBoundaryType(), rule, col));
                continue;
            }
            UnaryTestNode ut = (UnaryTestNode) n;
            Interval interval = utnToInterval(ut, minMax, discreteValues, rule, col);
            if (isNegated) {
                results.addAll(Interval.invertOverDomain(interval, minMax));
            } else {
                results.add(interval);
            }
        }
    }
    return results;
}
Also used : UnaryTestNode(org.kie.dmn.feel.lang.ast.UnaryTestNode) ArrayList(java.util.ArrayList) BitSet(java.util.BitSet) BaseNode(org.kie.dmn.feel.lang.ast.BaseNode) DashNode(org.kie.dmn.feel.lang.ast.DashNode) NullNode(org.kie.dmn.feel.lang.ast.NullNode) Interval(org.kie.dmn.validation.dtanalysis.model.Interval)

Aggregations

UnaryTestNode (org.kie.dmn.feel.lang.ast.UnaryTestNode)5 ArrayList (java.util.ArrayList)4 BaseNode (org.kie.dmn.feel.lang.ast.BaseNode)3 Interval (org.kie.dmn.validation.dtanalysis.model.Interval)3 QName (javax.xml.namespace.QName)2 ProcessedUnaryTest (org.kie.dmn.feel.codegen.feel11.ProcessedUnaryTest)2 DashNode (org.kie.dmn.feel.lang.ast.DashNode)2 NullNode (org.kie.dmn.feel.lang.ast.NullNode)2 UnaryTestListNode (org.kie.dmn.feel.lang.ast.UnaryTestListNode)2 UnaryTestInterpretedExecutableExpression (org.kie.dmn.feel.lang.impl.UnaryTestInterpretedExecutableExpression)2 BitSet (java.util.BitSet)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 CompilerContext (org.kie.dmn.feel.lang.CompilerContext)1 Type (org.kie.dmn.feel.lang.Type)1 ListNode (org.kie.dmn.feel.lang.ast.ListNode)1 RangeNode (org.kie.dmn.feel.lang.ast.RangeNode)1 UnaryTest (org.kie.dmn.feel.runtime.UnaryTest)1 InputClause (org.kie.dmn.model.api.InputClause)1