use of org.kie.dmn.core.ast.DecisionNodeImpl in project drools by kiegroup.
the class DMNRuntimeTest method testCycleDetection.
@Test
public void testCycleDetection() {
final Definitions defs = buildSimplifiedDefinitions("ns", "a", "b");
final DecisionNodeImpl a = buildSimplifiedDecisionNode(defs, "a");
final DecisionNodeImpl b = buildSimplifiedDecisionNode(defs, "b");
a.addDependency("b", b);
b.addDependency("a", b);
final DMNModelImpl model = new DMNModelImpl(defs);
model.setDefinitions(defs);
model.addDecision(a);
model.addDecision(b);
final DMNRuntime runtime = DMNRuntimeUtil.createRuntime(this.getClass());
final DMNResult result = runtime.evaluateAll(model, DMNFactory.newContext());
assertTrue(result.hasErrors());
}
use of org.kie.dmn.core.ast.DecisionNodeImpl in project drools by kiegroup.
the class MultiInstanceDecisionLogicTest method decision.
private DMNBaseNode decision(String id) {
DecisionNodeImpl decision = mock(DecisionNodeImpl.class);
doReturn(id).when(decision).getId();
doReturn(decision).when(model).getDecisionById(id);
return decision;
}
use of org.kie.dmn.core.ast.DecisionNodeImpl in project drools by kiegroup.
the class DMNRuntimeImpl method evaluateDecision.
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(// it might be an imported Decision.
DMNDecisionResult.DecisionEvaluationStatus.NOT_EVALUATED);
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) {
Object value = er.getResult();
if (!decision.getResultType().isCollection() && value instanceof Collection && ((Collection) value).size() == 1) {
// spec defines that "a=[a]", i.e., singleton collections should be treated as the single element
// and vice-versa
value = ((Collection) value).toArray()[0];
}
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 {
dr.setEvaluationStatus(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);
}
}
use of org.kie.dmn.core.ast.DecisionNodeImpl in project drools by kiegroup.
the class DMNRuntimeTest method testCycleDetectionSelfReference.
@Test
public void testCycleDetectionSelfReference() {
final Definitions defs = buildSimplifiedDefinitions("ns", "self");
final DecisionNodeImpl decision = buildSimplifiedDecisionNode(defs, "self");
decision.addDependency("self", decision);
final DMNModelImpl model = new DMNModelImpl(defs);
model.setDefinitions(defs);
model.addDecision(decision);
final DMNRuntime runtime = DMNRuntimeUtil.createRuntime(this.getClass());
final DMNResult result = runtime.evaluateAll(model, DMNFactory.newContext());
assertTrue(result.hasErrors());
}
use of org.kie.dmn.core.ast.DecisionNodeImpl in project drools by kiegroup.
the class DMNCompilerImpl method detectCycles.
private void detectCycles(DMNModelImpl model) {
/*
Boolean.TRUE = node is either safe or already reported for having a cyclic dependency
Boolean.FALSE = node is being checked at the moment
*/
final Map<DecisionNodeImpl, Boolean> registry = new HashMap<>();
for (DecisionNode decision : model.getDecisions()) {
final DecisionNodeImpl decisionNode = (DecisionNodeImpl) decision;
detectCycles(decisionNode, registry, model);
}
}
Aggregations