private boolean evaluateDecision()

in kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNRuntimeImpl.java [556:737]


    private boolean evaluateDecision(DMNContext context, DMNResultImpl result, DecisionNode d, boolean typeCheck) {
        DecisionNodeImpl decision = (DecisionNodeImpl) d;
        String decisionId = d.getModelNamespace().equals(result.getModel().getNamespace()) ? decision.getId() : decision.getModelNamespace() + "#" + decision.getId();
        if (isNodeValueDefined(result, decision, decision)) {
            // already resolved
            return true;
        } else {
            // check if the decision was already evaluated before and returned error
            DMNDecisionResult.DecisionEvaluationStatus status = Optional.ofNullable(result.getDecisionResultById(decisionId))
                                                                        .map(DMNDecisionResult::getEvaluationStatus)
                                                                        .orElse(DMNDecisionResult.DecisionEvaluationStatus.NOT_EVALUATED); // it might be an imported Decision.
            if ( FAILED == status || SKIPPED == status || EVALUATING == status ) {
                return false;
            }
        }
        BeforeEvaluateDecisionEvent beforeEvaluateDecisionEvent = null;
        try {
            beforeEvaluateDecisionEvent = DMNRuntimeEventManagerUtils.fireBeforeEvaluateDecision(eventManager, decision, result);
            boolean missingInput = false;
            DMNDecisionResultImpl dr = (DMNDecisionResultImpl) result.getDecisionResultById(decisionId);
            if (dr == null) { // an imported Decision now evaluated, requires the creation of the decision result:
                String decisionResultName = d.getName();
                Optional<String> importAliasFor = ((DMNModelImpl) result.getModel()).getImportAliasFor(d.getModelNamespace(), d.getModelName());
                if (importAliasFor.isPresent()) {
                    decisionResultName = importAliasFor.get() + "." + d.getName();
                }
                dr = new DMNDecisionResultImpl(decisionId, decisionResultName);
                if (importAliasFor.isPresent()) { // otherwise is a transitive, skipped and not to be added to the results:
                    result.addDecisionResult(dr);
                }
            }
            dr.setEvaluationStatus(DMNDecisionResult.DecisionEvaluationStatus.EVALUATING);
            for( DMNNode dep : decision.getDependencies().values() ) {
                try {
                    if (typeCheck && !checkDependencyValueIsValid(dep, result)) {
                        missingInput = true;
                        DMNMessage message = MsgUtil.reportMessage( logger,
                                DMNMessage.Severity.ERROR,
                                ((DMNBaseNode) dep).getSource(),
                                result,
                                null,
                                null,
                                Msg.ERROR_EVAL_NODE_DEP_WRONG_TYPE,
                                getIdentifier( decision ),
                                getDependencyIdentifier(decision, dep),
                                MsgUtil.clipString(Objects.toString(result.getContext().get(dep.getName())), 50),
                                ((DMNBaseNode) dep).getType()
                                );
                        reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.SKIPPED );
                    }
                } catch ( Exception e ) {
                    MsgUtil.reportMessage( logger,
                                           DMNMessage.Severity.ERROR,
                                           ((DMNBaseNode)dep).getSource(),
                                           result,
                                           e,
                                           null,
                                           Msg.ERROR_CHECKING_ALLOWED_VALUES,
                                           getDependencyIdentifier(decision, dep),
                                           e.getMessage() );
                }
                if (!isNodeValueDefined(result, decision, dep)) {
                    boolean walkingIntoScope = walkIntoImportScope(result, decision, dep);
                    if( dep instanceof DecisionNode ) {
                        if (!evaluateDecision(context, result, (DecisionNode) dep, typeCheck)) {
                            missingInput = true;
                            DMNMessage message = MsgUtil.reportMessage( logger,
                                                                        DMNMessage.Severity.ERROR,
                                                                        decision.getSource(),
                                                                        result,
                                                                        null,
                                                                        null,
                                                                        Msg.UNABLE_TO_EVALUATE_DECISION_REQ_DEP,
                                                                        getIdentifier( decision ),
                                                                        getDependencyIdentifier(decision, dep) );
                            reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.SKIPPED );
                        }
                    } else if( dep instanceof BusinessKnowledgeModelNode ) {
                        evaluateBKM(context, result, (BusinessKnowledgeModelNode) dep, typeCheck);
                    } else if (dep instanceof DecisionServiceNode) {
                        evaluateDecisionService(context, result, (DecisionServiceNode) dep, typeCheck);
                    } else {
                        missingInput = true;
                        DMNMessage message = MsgUtil.reportMessage( logger,
                                                                    DMNMessage.Severity.ERROR,
                                                                    decision.getSource(),
                                                                    result,
                                                                    null,
                                                                    null,
                                                                    Msg.REQ_DEP_NOT_FOUND_FOR_NODE,
                                                                    getDependencyIdentifier(decision, dep),
                                                                    getIdentifier( decision )
                                                                    );
                        reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.SKIPPED );
                    }
                    if (walkingIntoScope) {
                        result.getContext().popScope();
                    }
                }
            }
            if( missingInput ) {
                return false;
            }
            if( decision.getEvaluator() == null ) {
                DMNMessage message = MsgUtil.reportMessage( logger,
                                                            DMNMessage.Severity.WARN,
                                                            decision.getSource(),
                                                            result,
                                                            null,
                                                            null,
                                                            Msg.MISSING_EXPRESSION_FOR_DECISION,
                                                            getIdentifier( decision ) );

                reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.SKIPPED );
                return false;
            }
            try {
                EvaluatorResult er = decision.getEvaluator().evaluate( this, result);
                if( er.getResultType() == EvaluatorResult.ResultType.SUCCESS ||
                        (((DMNModelImpl)result.getModel()).getFeelDialect().equals(FEELDialect.BFEEL) && er.getResult() != null)) {
                    Object value = coerceValue(decision.getResultType(), er.getResult());
                    try {
                        if (typeCheck && !d.getResultType().isAssignableValue(value)) {
                            DMNMessage message = MsgUtil.reportMessage( logger,
                                    DMNMessage.Severity.ERROR,
                                    decision.getSource(),
                                    result,
                                    null,
                                    null,
                                    Msg.ERROR_EVAL_NODE_RESULT_WRONG_TYPE,
                                    getIdentifier( decision ),
                                    decision.getResultType(),
                                    value);
                            reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.FAILED );
                            return false;
                        }
                    } catch ( Exception e ) {
                        MsgUtil.reportMessage( logger,
                                               DMNMessage.Severity.ERROR,
                                               decision.getSource(),
                                               result,
                                               e,
                                               null,
                                               Msg.ERROR_CHECKING_ALLOWED_VALUES,
                                               getIdentifier( decision ),
                                               e.getMessage() );
                        return false;
                    }

                    result.getContext().set(decision.getDecision().getVariable().getName(), value);
                    dr.setResult( value );
                    dr.setEvaluationStatus( DMNDecisionResult.DecisionEvaluationStatus.SUCCEEDED );
                } else {
                    DMNMessage message = MsgUtil.reportMessage( logger,
                            DMNMessage.Severity.ERROR,
                            decision.getSource(),
                            result,
                            null,
                            null,
                            Msg.ERROR_EVAL_DECISION_NODE,
                            getIdentifier( decision ),
                            decision.getResultType() );
                    reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.FAILED );
                    return false;
                }
            } catch( Throwable t ) {
                DMNMessage message = MsgUtil.reportMessage( logger,
                                                            DMNMessage.Severity.ERROR,
                                                            decision.getSource(),
                                                            result,
                                                            t,
                                                            null,
                                                            Msg.ERROR_EVAL_DECISION_NODE,
                                                            getIdentifier( decision ),
                                                            t.getMessage() );
                reportFailure( dr, message, DMNDecisionResult.DecisionEvaluationStatus.FAILED );
            }
            return true;
        } finally {
            DMNRuntimeEventManagerUtils.fireAfterEvaluateDecision( eventManager, decision, result, beforeEvaluateDecisionEvent);
        }
    }