Search in sources :

Example 6 with Binding

use of org.kie.dmn.model.api.Binding in project drools by kiegroup.

the class DMNEvaluatorCompiler method compileDecisionTable.

protected DMNExpressionEvaluator compileDecisionTable(DMNCompilerContext ctx, DMNModelImpl model, DMNBaseNode node, String dtName, DecisionTable dt) {
    java.util.List<DTInputClause> inputs = new ArrayList<>();
    java.util.List<DMNType> inputTypes = new ArrayList<>();
    int index = 0;
    for (InputClause ic : dt.getInput()) {
        index++;
        String inputExpressionText = ic.getInputExpression().getText();
        String inputValuesText = Optional.ofNullable(ic.getInputValues()).map(UnaryTests::getText).orElse(null);
        java.util.List<UnaryTest> inputValues = null;
        DMNType inputType = model.getTypeRegistry().unknown();
        if (inputValuesText != null) {
            inputValues = textToUnaryTestList(ctx, inputValuesText, model, ic, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_INPUT_CLAUSE_IDX, inputValuesText, node.getIdentifierString(), index);
        } else if (ic.getInputExpression().getTypeRef() != null) {
            QName inputExpressionTypeRef = ic.getInputExpression().getTypeRef();
            QName resolvedInputExpressionTypeRef = DMNCompilerImpl.getNamespaceAndName(ic.getInputExpression(), model.getImportAliasesForNS(), inputExpressionTypeRef, model.getNamespace());
            BaseDMNTypeImpl typeRef = (BaseDMNTypeImpl) model.getTypeRegistry().resolveType(resolvedInputExpressionTypeRef.getNamespaceURI(), resolvedInputExpressionTypeRef.getLocalPart());
            inputType = typeRef;
            if (inputType == null) {
                MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, dt, model, null, null, Msg.WRONG_TYPEREF_FOR_COLUMN, index, inputExpressionText, inputExpressionTypeRef);
                inputType = model.getTypeRegistry().unknown();
            } else {
                inputValues = typeRef.getAllowedValuesFEEL();
            }
        }
        CompiledExpression compiledInput = ctx.getFeelHelper().compileFeelExpression(ctx, inputExpressionText, model, dt, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_INPUT_CLAUSE_IDX, inputExpressionText, dtName, index);
        inputs.add(new DTInputClause(inputExpressionText, inputValuesText, inputValues, compiledInput, inputType.isCollection()));
        inputTypes.add(inputType);
    }
    java.util.List<DTOutputClause> outputs = new ArrayList<>();
    index = 0;
    boolean hasOutputValues = false;
    for (OutputClause oc : dt.getOutput()) {
        String outputName = oc.getName();
        if (outputName != null) {
            DMNCompilerHelper.checkVariableName(model, node.getSource(), outputName);
        }
        String id = oc.getId();
        String outputValuesText = Optional.ofNullable(oc.getOutputValues()).map(UnaryTests::getText).orElse(null);
        String defaultValue = Optional.ofNullable(oc.getDefaultOutputEntry()).map(LiteralExpression::getText).filter(t -> !t.isEmpty()).orElse(null);
        BaseDMNTypeImpl typeRef = inferTypeRef(model, dt, oc);
        java.util.List<UnaryTest> outputValues = null;
        if (outputValuesText != null) {
            outputValues = textToUnaryTestList(ctx, outputValuesText, model, oc, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_OUTPUT_CLAUSE_IDX, outputValuesText, node.getIdentifierString(), ++index);
        } else if (typeRef != model.getTypeRegistry().unknown()) {
            outputValues = typeRef.getAllowedValuesFEEL();
        }
        if (outputValues != null && !outputValues.isEmpty()) {
            hasOutputValues = true;
        }
        outputs.add(new DTOutputClause(outputName, id, outputValues, defaultValue, typeRef.getFeelType(), typeRef.isCollection()));
    }
    if (dt.getHitPolicy().equals(HitPolicy.PRIORITY) && !hasOutputValues) {
        MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, dt.getParent(), model, null, null, Msg.MISSING_OUTPUT_VALUES, dtName);
    }
    java.util.List<DTDecisionRule> rules = new ArrayList<>();
    index = 0;
    for (DecisionRule dr : dt.getRule()) {
        DTDecisionRule rule = new DTDecisionRule(index);
        for (int i = 0; i < dr.getInputEntry().size(); i++) {
            UnaryTests ut = dr.getInputEntry().get(i);
            final java.util.List<UnaryTest> tests;
            if (ut == null || ut.getText() == null || ut.getText().isEmpty()) {
                tests = Collections.emptyList();
                MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, ut, model, null, null, Msg.DTABLE_EMPTY_ENTRY, dt.getRule().indexOf(dr) + 1, dr.getInputEntry().indexOf(ut) + 1, dt.getParentDRDElement().getIdentifierString());
            } else {
                ctx.enterFrame();
                try {
                    ctx.setVariable("?", inputTypes.get(i));
                    tests = textToUnaryTestList(ctx, ut.getText(), model, dr, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_RULE_IDX, ut.getText(), node.getIdentifierString(), index + 1);
                } finally {
                    ctx.exitFrame();
                }
            }
            rule.getInputEntry().add((c, x) -> tests.stream().anyMatch(t -> {
                Boolean result = t.apply(c, x);
                return result != null && result;
            }));
        }
        for (LiteralExpression le : dr.getOutputEntry()) {
            String expressionText = le.getText();
            if (expressionText == null || expressionText.isEmpty()) {
                // addendum to DROOLS-2075 Allow empty output cell on DTs
                expressionText = "null";
            }
            CompiledExpression compiledExpression = ctx.getFeelHelper().compileFeelExpression(ctx, expressionText, model, dr, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_RULE_IDX, expressionText, dtName, index + 1);
            rule.getOutputEntry().add(compiledExpression);
        }
        rules.add(rule);
        index++;
    }
    String policy = dt.getHitPolicy().value() + (dt.getAggregation() != null ? " " + dt.getAggregation().value() : "");
    org.kie.dmn.feel.runtime.decisiontables.HitPolicy hp = org.kie.dmn.feel.runtime.decisiontables.HitPolicy.fromString(policy);
    java.util.List<String> parameterNames = getParameters(model, node, dt);
    // DROOLS-2799 DMN Optimize DT parameter binding for compilation:
    java.util.List<CompiledExpression> compiledParameterNames = new ArrayList<>();
    for (String pName : parameterNames) {
        CompiledExpression compiledExpression = ctx.getFeelHelper().compileFeelExpression(ctx, pName, model, dt, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_PARAM, pName, dtName);
        compiledParameterNames.add(compiledExpression);
    }
    // creates a FEEL instance which will be used by the invoker/impl (s)
    FEEL feelInstance = ctx.getFeelHelper().newFEELInstance();
    DecisionTableImpl dti = new DecisionTableImpl(dtName, parameterNames, inputs, outputs, rules, hp, feelInstance);
    dti.setCompiledParameterNames(compiledParameterNames);
    DTInvokerFunction dtf = new DTInvokerFunction(dti);
    DMNDTExpressionEvaluator dtee = new DMNDTExpressionEvaluator(node, feelInstance, dtf);
    return dtee;
}
Also used : PMMLModelInfo(org.kie.dmn.core.pmml.PMMLModelInfo) DMNConditionalEvaluator(org.kie.dmn.core.ast.DMNConditionalEvaluator) DecisionTable(org.kie.dmn.model.api.DecisionTable) DMNMessage(org.kie.dmn.api.core.DMNMessage) Quantified(org.kie.dmn.model.api.Quantified) LoggerFactory(org.slf4j.LoggerFactory) DMNExpressionEvaluator(org.kie.dmn.core.api.DMNExpressionEvaluator) LiteralExpression(org.kie.dmn.model.api.LiteralExpression) DMNElement(org.kie.dmn.model.api.DMNElement) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) EvaluatorResult(org.kie.dmn.core.api.EvaluatorResult) DMNIteratorEvaluator(org.kie.dmn.core.ast.DMNIteratorEvaluator) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) DMNNode(org.kie.dmn.api.core.ast.DMNNode) BaseDMNTypeImpl(org.kie.dmn.core.impl.BaseDMNTypeImpl) OutputClause(org.kie.dmn.model.api.OutputClause) DMNModelImpl(org.kie.dmn.core.impl.DMNModelImpl) Import(org.kie.dmn.model.api.Import) UUID(java.util.UUID) FunctionKind(org.kie.dmn.model.api.FunctionKind) DMNRelationEvaluator(org.kie.dmn.core.ast.DMNRelationEvaluator) Collectors(java.util.stream.Collectors) BusinessKnowledgeModelNode(org.kie.dmn.api.core.ast.BusinessKnowledgeModelNode) HitPolicy(org.kie.dmn.model.api.HitPolicy) Objects(java.util.Objects) Resource(org.kie.api.io.Resource) List(java.util.List) DMNDTExpressionEvaluator(org.kie.dmn.core.ast.DMNDTExpressionEvaluator) Filter(org.kie.dmn.model.api.Filter) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) Expression(org.kie.dmn.model.api.Expression) Entry(java.util.Map.Entry) Optional(java.util.Optional) QName(javax.xml.namespace.QName) InformationItem(org.kie.dmn.model.api.InformationItem) Iterator(org.kie.dmn.model.api.Iterator) DMNLiteralExpressionEvaluator(org.kie.dmn.core.ast.DMNLiteralExpressionEvaluator) RootExecutionFrame(org.kie.dmn.feel.lang.impl.RootExecutionFrame) Relation(org.kie.dmn.model.api.Relation) FEEL(org.kie.dmn.feel.FEEL) MsgUtil(org.kie.dmn.core.util.MsgUtil) DMNType(org.kie.dmn.api.core.DMNType) DMNContextEvaluator(org.kie.dmn.core.ast.DMNContextEvaluator) Binding(org.kie.dmn.model.api.Binding) InputClause(org.kie.dmn.model.api.InputClause) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) EvaluatorResultImpl(org.kie.dmn.core.ast.EvaluatorResultImpl) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) ArrayList(java.util.ArrayList) DecisionRule(org.kie.dmn.model.api.DecisionRule) DecisionNode(org.kie.dmn.api.core.ast.DecisionNode) DMNFilterEvaluator(org.kie.dmn.core.ast.DMNFilterEvaluator) FEELFunction(org.kie.dmn.feel.runtime.FEELFunction) For(org.kie.dmn.model.api.For) DMNBaseNode(org.kie.dmn.core.ast.DMNBaseNode) Decision(org.kie.dmn.model.api.Decision) FunctionDefinition(org.kie.dmn.model.api.FunctionDefinition) DMNInvocationEvaluator(org.kie.dmn.core.ast.DMNInvocationEvaluator) Logger(org.slf4j.Logger) DMNListEvaluator(org.kie.dmn.core.ast.DMNListEvaluator) AbstractPMMLInvocationEvaluator(org.kie.dmn.core.pmml.AbstractPMMLInvocationEvaluator) DTInvokerFunction(org.kie.dmn.feel.runtime.functions.DTInvokerFunction) ContextEntry(org.kie.dmn.model.api.ContextEntry) Invocation(org.kie.dmn.model.api.Invocation) DMNAlphaNetworkEvaluatorCompiler(org.kie.dmn.core.compiler.alphanetbased.DMNAlphaNetworkEvaluatorCompiler) Collectors.toList(java.util.stream.Collectors.toList) PMMLInvocationEvaluatorFactory(org.kie.dmn.core.pmml.AbstractPMMLInvocationEvaluator.PMMLInvocationEvaluatorFactory) DMNImportPMMLInfo(org.kie.dmn.core.pmml.DMNImportPMMLInfo) BusinessKnowledgeModel(org.kie.dmn.model.api.BusinessKnowledgeModel) DMNFunctionDefinitionEvaluator(org.kie.dmn.core.ast.DMNFunctionDefinitionEvaluator) UnaryTests(org.kie.dmn.model.api.UnaryTests) CompositeTypeImpl(org.kie.dmn.core.impl.CompositeTypeImpl) Conditional(org.kie.dmn.model.api.Conditional) Msg(org.kie.dmn.core.util.Msg) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) Collections(java.util.Collections) Context(org.kie.dmn.model.api.Context) BaseFEELFunction(org.kie.dmn.feel.runtime.functions.BaseFEELFunction) FEEL(org.kie.dmn.feel.FEEL) ArrayList(java.util.ArrayList) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) DecisionRule(org.kie.dmn.model.api.DecisionRule) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) InputClause(org.kie.dmn.model.api.InputClause) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) QName(javax.xml.namespace.QName) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) LiteralExpression(org.kie.dmn.model.api.LiteralExpression) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) DMNDTExpressionEvaluator(org.kie.dmn.core.ast.DMNDTExpressionEvaluator) BaseDMNTypeImpl(org.kie.dmn.core.impl.BaseDMNTypeImpl) OutputClause(org.kie.dmn.model.api.OutputClause) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) DTInvokerFunction(org.kie.dmn.feel.runtime.functions.DTInvokerFunction) UnaryTests(org.kie.dmn.model.api.UnaryTests) DMNType(org.kie.dmn.api.core.DMNType)

Example 7 with Binding

use of org.kie.dmn.model.api.Binding in project drools by kiegroup.

the class InvocationConverter method writeChildren.

@Override
protected void writeChildren(HierarchicalStreamWriter writer, MarshallingContext context, Object parent) {
    super.writeChildren(writer, context, parent);
    Invocation i = (Invocation) parent;
    if (i.getExpression() != null)
        writeChildrenNode(writer, context, i.getExpression(), MarshallingUtils.defineExpressionNodeName(i.getExpression()));
    for (Binding b : i.getBinding()) {
        writeChildrenNode(writer, context, b, BINDING);
    }
}
Also used : Binding(org.kie.dmn.model.api.Binding) Invocation(org.kie.dmn.model.api.Invocation) TInvocation(org.kie.dmn.model.v1_2.TInvocation)

Example 8 with Binding

use of org.kie.dmn.model.api.Binding in project drools by kiegroup.

the class DMNEvaluatorCompiler method compileInvocation.

private DMNExpressionEvaluator compileInvocation(DMNCompilerContext ctx, DMNModelImpl model, DMNBaseNode node, Invocation expression) {
    Invocation invocation = expression;
    // expression must be a literal text with the name of the function
    if (invocation.getExpression() == null || ((LiteralExpression) invocation.getExpression()).getText().isEmpty()) {
        MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, invocation, model, null, null, Msg.MISSING_EXPRESSION_FOR_INVOCATION, node.getIdentifierString());
        return null;
    }
    String functionName = ((LiteralExpression) invocation.getExpression()).getText();
    String[] fnameParts = functionName.split("\\.");
    Optional<DMNNode> findAsDep = Optional.empty();
    if (fnameParts.length > 1) {
        findAsDep = node.getDependencies().values().stream().filter(dmnNode -> dmnNode.getModelImportAliasFor(dmnNode.getModelNamespace(), dmnNode.getModelName()).map(alias -> Objects.equals(functionName, alias + "." + dmnNode.getName())).orElse(false)).findFirst();
    } else {
        findAsDep = node.getDependencies().values().stream().filter(d -> d.getName().equals(functionName)).findAny();
    }
    boolean findAsBuiltin = RootExecutionFrame.INSTANCE.getValue(functionName) != null;
    boolean findAsCustomFunction = ctx.getFeelHelper().newCompilerContext().getFEELFunctions().stream().anyMatch(f -> f.getName().equals(functionName));
    boolean findInContext = ctx.getVariables().get(functionName) != null;
    if (!findAsDep.isPresent() && !findAsBuiltin && !findAsCustomFunction && !findInContext) {
        MsgUtil.reportMessage(logger, DMNMessage.Severity.WARN, invocation, model, null, null, Msg.EXPRESSION_FOR_INVOCATION_NOT_RESOLVED, functionName, node.getIdentifierString(), node.getDependencies().values().stream().map(DMNNode::getName).collect(Collectors.toList()));
    }
    DMNInvocationEvaluator invEval = new DMNInvocationEvaluator(node.getName(), node.getSource(), functionName, invocation, null, ctx.getFeelHelper().newFEELInstance());
    for (Binding binding : invocation.getBinding()) {
        if (binding.getParameter() == null) {
            // error, missing binding parameter
            MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, binding, model, null, null, Msg.MISSING_PARAMETER_FOR_INVOCATION, node.getIdentifierString());
            return null;
        }
        if (binding.getExpression() == null) {
            MsgUtil.reportMessage(logger, DMNMessage.Severity.WARN, binding, model, null, null, Msg.MISSING_EXPRESSION_FOR_PARAM_OF_INVOCATION, binding.getParameter().getIdentifierString(), node.getIdentifierString());
            return null;
        }
        invEval.addParameter(binding.getParameter().getName(), compiler.resolveTypeRef(model, binding.getParameter(), binding.getParameter(), binding.getParameter().getTypeRef()), compileExpression(ctx, model, node, binding.getParameter().getName(), binding.getExpression()));
    }
    return invEval;
}
Also used : Binding(org.kie.dmn.model.api.Binding) Invocation(org.kie.dmn.model.api.Invocation) LiteralExpression(org.kie.dmn.model.api.LiteralExpression) DMNNode(org.kie.dmn.api.core.ast.DMNNode) DMNInvocationEvaluator(org.kie.dmn.core.ast.DMNInvocationEvaluator)

Example 9 with Binding

use of org.kie.dmn.model.api.Binding in project drools by kiegroup.

the class BindingConverter method writeChildren.

@Override
protected void writeChildren(HierarchicalStreamWriter writer, MarshallingContext context, Object parent) {
    super.writeChildren(writer, context, parent);
    Binding b = (Binding) parent;
    writeChildrenNode(writer, context, b.getParameter(), PARAMETER);
    if (b.getExpression() != null)
        writeChildrenNode(writer, context, b.getExpression(), MarshallingUtils.defineExpressionNodeName(b.getExpression()));
}
Also used : Binding(org.kie.dmn.model.api.Binding) TBinding(org.kie.dmn.model.v1_1.TBinding)

Example 10 with Binding

use of org.kie.dmn.model.api.Binding in project drools by kiegroup.

the class BindingConverter method writeChildren.

@Override
protected void writeChildren(HierarchicalStreamWriter writer, MarshallingContext context, Object parent) {
    super.writeChildren(writer, context, parent);
    Binding b = (Binding) parent;
    writeChildrenNode(writer, context, b.getParameter(), PARAMETER);
    if (b.getExpression() != null)
        writeChildrenNode(writer, context, b.getExpression(), MarshallingUtils.defineExpressionNodeName(xstream, b.getExpression()));
}
Also used : TBinding(org.kie.dmn.model.v1_4.TBinding) Binding(org.kie.dmn.model.api.Binding)

Aggregations

Binding (org.kie.dmn.model.api.Binding)10 Invocation (org.kie.dmn.model.api.Invocation)6 DMNNode (org.kie.dmn.api.core.ast.DMNNode)2 DMNInvocationEvaluator (org.kie.dmn.core.ast.DMNInvocationEvaluator)2 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 List (java.util.List)1 Entry (java.util.Map.Entry)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 UUID (java.util.UUID)1 Collectors (java.util.stream.Collectors)1 Collectors.toList (java.util.stream.Collectors.toList)1 QName (javax.xml.namespace.QName)1 Resource (org.kie.api.io.Resource)1 DMNMessage (org.kie.dmn.api.core.DMNMessage)1 DMNType (org.kie.dmn.api.core.DMNType)1 BusinessKnowledgeModelNode (org.kie.dmn.api.core.ast.BusinessKnowledgeModelNode)1 DecisionNode (org.kie.dmn.api.core.ast.DecisionNode)1 DMNExpressionEvaluator (org.kie.dmn.core.api.DMNExpressionEvaluator)1