Search in sources :

Example 1 with FEELEvent

use of org.kie.dmn.api.feel.runtime.events.FEELEvent in project drools by kiegroup.

the class DMNDTExpressionEvaluator method processEvents.

private EventResults processEvents(List<FEELEvent> events, DMNRuntimeEventManager eventManager, DMNResultImpl result) {
    EventResults r = new EventResults();
    for (FEELEvent e : events) {
        if (e instanceof DecisionTableRulesMatchedEvent) {
            r.matchedRules = ((DecisionTableRulesMatchedEvent) e).getMatches();
        } else if (e instanceof DecisionTableRulesSelectedEvent) {
            r.fired = ((DecisionTableRulesSelectedEvent) e).getFired();
        } else if (e.getSeverity() == FEELEvent.Severity.ERROR) {
            MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, ((DMNBaseNode) node).getSource(), result, null, e, Msg.FEEL_ERROR, e.getMessage());
            r.hasErrors = true;
        } else if (e.getSeverity() == FEELEvent.Severity.WARN) {
            MsgUtil.reportMessage(logger, DMNMessage.Severity.WARN, ((DMNBaseNode) node).getSource(), result, null, e, Msg.FEEL_WARN, e.getMessage());
        }
    }
    events.clear();
    return r;
}
Also used : DecisionTableRulesSelectedEvent(org.kie.dmn.feel.runtime.events.DecisionTableRulesSelectedEvent) DecisionTableRulesMatchedEvent(org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Example 2 with FEELEvent

use of org.kie.dmn.api.feel.runtime.events.FEELEvent in project drools by kiegroup.

the class DMNInvocationEvaluator method hasErrors.

private boolean hasErrors(List<FEELEvent> events, DMNRuntimeEventManager eventManager, DMNResultImpl result) {
    boolean hasErrors = false;
    for (FEELEvent e : events) {
        if (e.getSeverity() == FEELEvent.Severity.ERROR) {
            MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, invocation, result, null, e, Msg.FEEL_ERROR, e.getMessage());
            hasErrors = true;
        }
    }
    events.clear();
    return hasErrors;
}
Also used : FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Example 3 with FEELEvent

use of org.kie.dmn.api.feel.runtime.events.FEELEvent in project drools by kiegroup.

the class DMNFEELHelper method valueMatchesInUnaryTests.

public static boolean valueMatchesInUnaryTests(List<UnaryTest> unaryTests, Object value, DMNContext dmnContext) {
    FEELEventListenersManager manager = new FEELEventListenersManager();
    FEELEventsListenerImpl listener = new FEELEventsListenerImpl();
    manager.addListener(listener);
    EvaluationContextImpl ctx = new EvaluationContextImpl(manager);
    try {
        ctx.enterFrame();
        if (dmnContext != null) {
            // need to set the values for in context variables...
            for (Map.Entry<String, Object> entry : dmnContext.getAll().entrySet()) {
                ctx.setValue(entry.getKey(), entry.getValue());
            }
        }
        for (UnaryTest t : unaryTests) {
            try {
                Boolean applyT = t.apply(ctx, value);
                // the unary test above can actually return null, so we have to handle it here
                if (applyT == null) {
                    return false;
                } else if (applyT) {
                    return true;
                }
            } catch (Throwable e) {
                StringBuilder message = new StringBuilder();
                for (FEELEvent feelEvent : listener.getFeelEvents()) {
                    message.append(feelEvent.getMessage());
                    message.append("\n");
                }
                throw new RuntimeException(message.toString(), e);
            }
        }
    } finally {
        ctx.exitFrame();
    }
    return false;
}
Also used : FEELEventListenersManager(org.kie.dmn.feel.lang.impl.FEELEventListenersManager) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) EvaluationContextImpl(org.kie.dmn.feel.lang.impl.EvaluationContextImpl) HashMap(java.util.HashMap) Map(java.util.Map) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Example 4 with FEELEvent

use of org.kie.dmn.api.feel.runtime.events.FEELEvent in project drools by kiegroup.

the class DecisionTableImpl method evaluate.

/**
 * Evaluates this decision table returning the result
 * @param ctx
 * @param params these are the required information items, not to confuse with the columns of the
 *               decision table that are expressions derived from these parameters
 * @return
 */
public FEELFnResult<Object> evaluate(EvaluationContext ctx, Object[] params) {
    if (decisionRules.isEmpty()) {
        return FEELFnResult.ofError(new FEELEventBase(Severity.WARN, "Decision table is empty", null));
    }
    Object[] actualInputs = resolveActualInputs(ctx, feel);
    Either<FEELEvent, Object> actualInputMatch = actualInputsMatchInputValues(ctx, actualInputs);
    if (actualInputMatch.isLeft()) {
        return actualInputMatch.cata(e -> FEELFnResult.ofError(e), e -> FEELFnResult.ofError(null));
    }
    List<DTDecisionRule> matches = findMatches(ctx, actualInputs);
    if (!matches.isEmpty()) {
        List<Object> results = evaluateResults(ctx, feel, actualInputs, matches);
        Map<Integer, String> msgs = checkResults(ctx, matches, results);
        if (msgs.isEmpty()) {
            Object result = hitPolicy.getDti().dti(ctx, this, actualInputs, matches, results);
            return FEELFnResult.ofResult(result);
        } else {
            List<Integer> offending = msgs.keySet().stream().collect(Collectors.toList());
            return FEELFnResult.ofError(new HitPolicyViolationEvent(Severity.ERROR, "Errors found evaluating decision table '" + getName() + "': \n" + (msgs.values().stream().collect(Collectors.joining("\n"))), name, offending));
        }
    } else {
        // check if there is a default value set for the outputs
        if (hasDefaultValues) {
            Object result = defaultToOutput(ctx, feel);
            return FEELFnResult.ofResult(result);
        } else {
            if (hitPolicy.getDefaultValue() != null) {
                return FEELFnResult.ofResult(hitPolicy.getDefaultValue());
            }
            return FEELFnResult.ofError(new HitPolicyViolationEvent(Severity.WARN, "No rule matched for decision table '" + name + "' and no default values were defined. Setting result to null.", name, Collections.EMPTY_LIST));
        }
    }
}
Also used : FEELEventBase(org.kie.dmn.feel.runtime.events.FEELEventBase) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) HitPolicyViolationEvent(org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent)

Example 5 with FEELEvent

use of org.kie.dmn.api.feel.runtime.events.FEELEvent in project drools by kiegroup.

the class BaseFEELFunction method invokeReflectively.

@Override
public Object invokeReflectively(EvaluationContext ctx, Object[] params) {
    // use reflection to call the appropriate invoke method
    try {
        boolean isNamedParams = params.length > 0 && params[0] instanceof NamedParameter;
        if (!isCustomFunction()) {
            List<String> available = null;
            if (isNamedParams) {
                available = Stream.of(params).map(p -> ((NamedParameter) p).getName()).collect(Collectors.toList());
            }
            CandidateMethod cm = getCandidateMethod(ctx, params, isNamedParams, available);
            if (cm != null) {
                Object result = cm.apply.invoke(this, cm.actualParams);
                if (result instanceof Either) {
                    @SuppressWarnings("unchecked") Either<FEELEvent, Object> either = (Either<FEELEvent, Object>) result;
                    Object eitherResult = either.cata((left) -> {
                        ctx.notifyEvt(() -> {
                            if (left instanceof InvalidParametersEvent) {
                                InvalidParametersEvent invalidParametersEvent = (InvalidParametersEvent) left;
                                invalidParametersEvent.setNodeName(getName());
                                invalidParametersEvent.setActualParameters(Stream.of(cm.apply.getParameters()).map(p -> p.getAnnotation(ParameterName.class).value()).collect(Collectors.toList()), Arrays.asList(cm.actualParams));
                            }
                            return left;
                        });
                        return null;
                    }, Function.identity());
                    return eitherResult;
                }
                return result;
            } else {
                String ps = getClass().toString();
                logger.error("Unable to find function '" + getName() + "( " + ps.substring(1, ps.length() - 1) + " )'");
                ctx.notifyEvt(() -> {
                    return new FEELEventBase(Severity.ERROR, "Unable to find function '" + getName() + "( " + ps.substring(1, ps.length() - 1) + " )'", null);
                });
            }
        } else {
            if (isNamedParams) {
                params = rearrangeParameters(params, this.getParameterNames().get(0));
            }
            Object result = invoke(ctx, params);
            if (result instanceof Either) {
                @SuppressWarnings("unchecked") Either<FEELEvent, Object> either = (Either<FEELEvent, Object>) result;
                final Object[] usedParams = params;
                Object eitherResult = either.cata((left) -> {
                    ctx.notifyEvt(() -> {
                        if (left instanceof InvalidParametersEvent) {
                            InvalidParametersEvent invalidParametersEvent = (InvalidParametersEvent) left;
                            invalidParametersEvent.setNodeName(getName());
                            invalidParametersEvent.setActualParameters(IntStream.of(0, usedParams.length).mapToObj(i -> "arg" + i).collect(Collectors.toList()), Arrays.asList(usedParams));
                        }
                        return left;
                    });
                    return null;
                }, Function.identity());
                return normalizeResult(eitherResult);
            }
            return normalizeResult(result);
        }
    } catch (Exception e) {
        logger.error("Error trying to call function " + getName() + ".", e);
        ctx.notifyEvt(() -> {
            return new FEELEventBase(Severity.ERROR, "Error trying to call function " + getName() + ".", e);
        });
    }
    return null;
}
Also used : NamedParameter(org.kie.dmn.feel.lang.impl.NamedParameter) InvalidParametersEvent(org.kie.dmn.feel.runtime.events.InvalidParametersEvent) FEELEventBase(org.kie.dmn.feel.runtime.events.FEELEventBase) Either(org.kie.dmn.feel.util.Either) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Aggregations

FEELEvent (org.kie.dmn.api.feel.runtime.events.FEELEvent)19 Test (org.junit.Test)5 FEELEventListener (org.kie.dmn.api.feel.runtime.events.FEELEventListener)5 FEELEventBase (org.kie.dmn.feel.runtime.events.FEELEventBase)5 ArrayList (java.util.ArrayList)4 Map (java.util.Map)4 EvaluationContextImpl (org.kie.dmn.feel.lang.impl.EvaluationContextImpl)4 List (java.util.List)3 Severity (org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity)3 FEEL (org.kie.dmn.feel.FEEL)3 HitPolicyViolationEvent (org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent)3 BigDecimal (java.math.BigDecimal)2 Arrays (java.util.Arrays)2 Collection (java.util.Collection)2 HashMap (java.util.HashMap)2 DMNContext (org.kie.dmn.api.core.DMNContext)2 DMNResultImpl (org.kie.dmn.core.impl.DMNResultImpl)2 InvalidInputEvent (org.kie.dmn.feel.runtime.events.InvalidInputEvent)2 InvalidParametersEvent (org.kie.dmn.feel.runtime.events.InvalidParametersEvent)2 Logger (org.slf4j.Logger)2