Search in sources :

Example 1 with HitPolicy

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);
}
Also used : HitPolicyViolationEvent(org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent) DecisionTableImpl.checkResults(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl.checkResults) DecisionTableRulesMatchedEvent(org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent) DecisionTable(org.kie.dmn.feel.runtime.decisiontables.DecisionTable) HitPolicy(org.kie.dmn.feel.runtime.decisiontables.HitPolicy) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) List(java.util.List) Function1(org.drools.model.functions.Function1) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) TreeMap(java.util.TreeMap) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) EvaluationContext(org.kie.dmn.feel.lang.EvaluationContext) Map(java.util.Map) Collections(java.util.Collections) Indexed(org.kie.dmn.feel.runtime.decisiontables.Indexed) DecisionTableRulesMatchedEvent(org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent) ArrayList(java.util.ArrayList) HitPolicyViolationEvent(org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent)

Example 2 with HitPolicy

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);
}
Also used : IntStream(java.util.stream.IntStream) FEEL(org.kie.dmn.feel.FEEL) FEELEventBase(org.kie.dmn.feel.runtime.events.FEELEventBase) FEELEventListener(org.kie.dmn.api.feel.runtime.events.FEELEventListener) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) Logger(org.slf4j.Logger) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) HitPolicy(org.kie.dmn.feel.runtime.decisiontables.HitPolicy) LoggerFactory(org.slf4j.LoggerFactory) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) GwtIncompatible(org.kie.dmn.model.api.GwtIncompatible) Range(org.kie.dmn.feel.runtime.Range) ArrayList(java.util.ArrayList) List(java.util.List) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) EvaluationContext(org.kie.dmn.feel.lang.EvaluationContext) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) Msg(org.kie.dmn.feel.util.Msg) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) Collections(java.util.Collections) FEEL(org.kie.dmn.feel.FEEL) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 FEELEvent (org.kie.dmn.api.feel.runtime.events.FEELEvent)2 EvaluationContext (org.kie.dmn.feel.lang.EvaluationContext)2 HitPolicy (org.kie.dmn.feel.runtime.decisiontables.HitPolicy)2 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 UUID (java.util.UUID)1 Collectors.toList (java.util.stream.Collectors.toList)1 IntStream (java.util.stream.IntStream)1 Stream (java.util.stream.Stream)1 Function1 (org.drools.model.functions.Function1)1 FEELEventListener (org.kie.dmn.api.feel.runtime.events.FEELEventListener)1 FEEL (org.kie.dmn.feel.FEEL)1 CompiledExpression (org.kie.dmn.feel.lang.CompiledExpression)1 Range (org.kie.dmn.feel.runtime.Range)1 UnaryTest (org.kie.dmn.feel.runtime.UnaryTest)1 DTDecisionRule (org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule)1