protected DMNExpressionEvaluator compileDecisionTable()

in kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/DMNEvaluatorCompiler.java [633:819]


    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 = NamespaceUtil.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, dr.getId());
            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()) {
                    expressionText = "null"; // addendum to DROOLS-2075 Allow empty output cell on DTs
                }
                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);
        dtee.setDtNodeId(dt.getId());
        return dtee;
    }