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);
}
}