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