use of org.kie.dmn.feel.runtime.decisiontables.HitPolicy in project drools by kiegroup.
the class Results method applyHitPolicy.
public Object applyHitPolicy(EvaluationContext evaluationContext, HitPolicy hitPolicy, DecisionTable decisionTable) {
if (items.hasNoIndexes()) {
// }
if (hitPolicy.getDefaultValue() != null) {
return hitPolicy.getDefaultValue();
}
events.add(new HitPolicyViolationEvent(FEELEvent.Severity.WARN, String.format("No rule matched for decision table '%s' and no default values were defined. Setting result to null.", decisionTable.getName()), decisionTable.getName(), Collections.emptyList()));
}
List<? extends Indexed> matchIndexes = items.matches();
evaluationContext.notifyEvt(() -> {
List<Integer> matchedIndexes = matchIndexes.stream().map(dr -> dr.getIndex() + 1).collect(Collectors.toList());
return new DecisionTableRulesMatchedEvent(FEELEvent.Severity.INFO, String.format("Rules matched for decision table '%s': %s", decisionTable.getName(), matchIndexes), decisionTable.getName(), decisionTable.getName(), matchedIndexes);
});
List<Object> resultObjects = items.evaluateResults(evaluationContext);
Map<Integer, String> errorMessages = checkResults(decisionTable.getOutputs(), evaluationContext, matchIndexes, resultObjects);
if (!errorMessages.isEmpty()) {
List<Integer> offending = new ArrayList<>(errorMessages.keySet());
events.add(new HitPolicyViolationEvent(FEELEvent.Severity.ERROR, String.format("Errors found evaluating decision table '%s': \n%s", decisionTable.getName(), String.join("\n", errorMessages.values())), decisionTable.getName(), offending));
return null;
}
return hitPolicy.getDti().dti(evaluationContext, decisionTable, matchIndexes, resultObjects);
}
use of org.kie.dmn.feel.runtime.decisiontables.HitPolicy in project drools by kiegroup.
the class DecisionTableFunction method invoke.
/**
* @param inputExpressionList a list of the N>=0 input expressions in display order
* @param inputValuesList * a list of N input values, corresponding to the input expressions. Each
* list element is a unary tests literal (see below).
* @param outputs * a name (a string matching grammar rule 27) or a list of M>0 names
* @param outputValues * if outputs is a list, then output values is a list of lists of values, one list
* per output; else output values is a list of values for the one output.
* Each value is a string.
* @param ruleList a list of R>0 rules. A rule is a list of N input entries followed by M
* output entries. An input entry is a unary tests literal. An output entry is
* an expression represented as a string.
* @param hitPolicy * one of: "U", "A", “P”, “F”, "R", "O", "C", "C+", "C#", "C<", “C>”
* (default is "U")
* @param defaultOutputValue * if outputs is a list, then default output value is a context with entries
* composed of outputs and output values; else default output value is one
* of the output values.
*/
public Object invoke(@ParameterName("ctx") EvaluationContext ctx, @ParameterName("outputs") Object outputs, @ParameterName("input expression list") Object inputExpressionList, @ParameterName("input values list") List<?> inputValuesList, @ParameterName("output values") Object outputValues, @ParameterName("rule list") List<List> ruleList, @ParameterName("hit policy") String hitPolicy, @ParameterName("default output value") Object defaultOutputValue) {
// input expression list can have a single element or be a list
// TODO isn't ^ conflicting with the specs page 136 "input expression list: a LIST of the"
List<String> inputExpressions = inputExpressionList instanceof List ? (List) inputExpressionList : Collections.singletonList((String) inputExpressionList);
List<DTInputClause> inputs;
if (inputValuesList != null) {
List<UnaryTest> inputValues = inputValuesList.stream().map(o -> toUnaryTest(ctx, o)).collect(Collectors.toList());
if (inputValues.size() != inputExpressions.size()) {
// TODO handle compilation error
}
// zip inputExpression with its inputValue
inputs = IntStream.range(0, inputExpressions.size()).mapToObj(i -> new DTInputClause(inputExpressions.get(i), inputValuesList.toString(), Collections.singletonList(inputValues.get(i)), null, false)).collect(Collectors.toList());
} else {
inputs = inputExpressions.stream().map(ie -> new DTInputClause(ie, null, null, null, false)).collect(Collectors.toList());
}
List<String> parseOutputs = outputs instanceof List ? (List) outputs : Collections.singletonList((String) outputs);
List<DTOutputClause> outputClauses;
if (outputValues != null) {
if (parseOutputs.size() == 1) {
outputClauses = new ArrayList<>();
List<UnaryTest> outputValuesCompiled = objectToUnaryTestList(ctx, Collections.singletonList((List<Object>) outputValues)).get(0);
outputClauses.add(new DTOutputClause(parseOutputs.get(0), outputValuesCompiled));
} else {
List<List<UnaryTest>> listOfList = objectToUnaryTestList(ctx, (List<List<Object>>) outputValues);
// zip inputExpression with its inputValue
outputClauses = IntStream.range(0, parseOutputs.size()).mapToObj(i -> new DTOutputClause(parseOutputs.get(i), listOfList.get(i))).collect(Collectors.toList());
}
} else {
outputClauses = parseOutputs.stream().map(out -> new DTOutputClause(out, null)).collect(Collectors.toList());
}
// TODO parse default output value.
FEEL feel = FEEL.newInstance();
List<DTDecisionRule> decisionRules = IntStream.range(0, ruleList.size()).mapToObj(index -> toDecisionRule(ctx, feel, index, ruleList.get(index), inputExpressions.size())).collect(Collectors.toList());
// TODO is there a way to avoid UUID and get from _evaluation_ ctx the name of the wrapping context?
// TODO also in this case it is using an ad-hoc created FEEL instance instead of the "hosted" one.
DecisionTableImpl dti = new DecisionTableImpl(UUID.randomUUID().toString(), inputExpressions, inputs, outputClauses, decisionRules, HitPolicy.fromString(hitPolicy), FEEL.newInstance());
return new DTInvokerFunction(dti);
}
Aggregations