Search in sources :

Example 11 with FEELEvent

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

the class DMNDTExpressionEvaluator method evaluate.

@Override
public EvaluatorResult evaluate(DMNRuntimeEventManager dmrem, DMNResult dmnr) {
    final List<FEELEvent> events = new ArrayList<>();
    DMNResultImpl result = (DMNResultImpl) dmnr;
    EventResults r = null;
    try {
        DMNRuntimeEventManagerUtils.fireBeforeEvaluateDecisionTable(dmrem, node.getName(), dt.getName(), result);
        List<String> paramNames = dt.getParameterNames().get(0);
        Object[] params = new Object[paramNames.size()];
        EvaluationContextImpl ctx = feel.newEvaluationContext(Arrays.asList(events::add), Collections.emptyMap());
        ctx.setPerformRuntimeTypeCheck(((DMNRuntimeImpl) dmrem.getRuntime()).performRuntimeTypeCheck(result.getModel()));
        ctx.enterFrame();
        // need to set the values for in context variables...
        for (Map.Entry<String, Object> entry : result.getContext().getAll().entrySet()) {
            ctx.setValue(entry.getKey(), entry.getValue());
        }
        for (int i = 0; i < params.length; i++) {
            EvaluationContextImpl evalCtx = feel.newEvaluationContext(Arrays.asList(events::add), Collections.emptyMap());
            evalCtx.setValues(result.getContext().getAll());
            params[i] = feel.evaluate(paramNames.get(i), evalCtx);
            ctx.setValue(paramNames.get(i), params[i]);
        }
        Object dtr = dt.invoke(ctx, params).cata(e -> {
            events.add(e);
            return null;
        }, Function.identity());
        // since ctx is a local variable that will be discarded, no need for a try/finally,
        // but still wanted to match the enter/exit frame for future maintainability purposes
        ctx.exitFrame();
        r = processEvents(events, dmrem, result);
        return new EvaluatorResultImpl(dtr, r.hasErrors ? ResultType.FAILURE : ResultType.SUCCESS);
    } finally {
        DMNRuntimeEventManagerUtils.fireAfterEvaluateDecisionTable(dmrem, node.getName(), dt.getName(), result, (r != null ? r.matchedRules : null), (r != null ? r.fired : null));
    }
}
Also used : DMNResultImpl(org.kie.dmn.core.impl.DMNResultImpl) ArrayList(java.util.ArrayList) EvaluationContextImpl(org.kie.dmn.feel.lang.impl.EvaluationContextImpl) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) Map(java.util.Map)

Example 12 with FEELEvent

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

the class DMNInvocationEvaluator method evaluate.

@Override
public EvaluatorResult evaluate(DMNRuntimeEventManager eventManager, DMNResult dmnr) {
    final List<FEELEvent> events = new ArrayList<>();
    DMNResultImpl result = (DMNResultImpl) dmnr;
    DMNContext previousContext = result.getContext();
    DMNContextImpl dmnContext = (DMNContextImpl) previousContext.clone();
    result.setContext(dmnContext);
    Object invocationResult = null;
    try {
        FEELFunction function = this.functionLocator.apply(previousContext, functionName);
        if (function == null) {
            // check if it is a configured/built-in function
            Object r = null;
            if (feel != null) {
                r = ((FEELImpl) feel).newEvaluationContext(Collections.emptyList(), Collections.emptyMap()).getValue(functionName);
            } else {
                r = RootExecutionFrame.INSTANCE.getValue(functionName);
            }
            if (r != null && r instanceof FEELFunction) {
                function = (FEELFunction) r;
            }
        }
        if (function == null) {
            MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, node, result, null, null, Msg.FUNCTION_NOT_FOUND, functionName, nodeName);
            return new EvaluatorResultImpl(null, ResultType.FAILURE);
        }
        Object[] namedParams = new Object[parameters.size()];
        int index = 0;
        for (ActualParameter param : parameters) {
            try {
                EvaluatorResult value = param.expression.evaluate(eventManager, result);
                if (value.getResultType() == ResultType.SUCCESS) {
                    namedParams[index++] = new NamedParameter(param.name, value.getResult());
                } else {
                    MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, node, result, null, null, Msg.ERR_EVAL_PARAM_FOR_INVOCATION_ON_NODE, param.name, functionName, nodeName);
                    return new EvaluatorResultImpl(null, ResultType.FAILURE);
                }
            } catch (Exception e) {
                MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, node, result, e, null, Msg.ERR_INVOKING_PARAM_EXPR_FOR_PARAM_ON_NODE, param.name, nodeName);
                return new EvaluatorResultImpl(null, ResultType.FAILURE);
            }
        }
        FEELEventListenersManager listenerMgr = new FEELEventListenersManager();
        listenerMgr.addListener(events::add);
        EvaluationContextImpl ctx = new EvaluationContextImpl(listenerMgr, eventManager.getRuntime());
        invocationResult = function.invokeReflectively(ctx, namedParams);
        boolean hasErrors = hasErrors(events, eventManager, result);
        return new EvaluatorResultImpl(invocationResult, hasErrors ? ResultType.FAILURE : ResultType.SUCCESS);
    } catch (Throwable t) {
        MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, node, result, t, null, Msg.ERR_INVOKING_FUNCTION_ON_NODE, functionName, nodeName);
        return new EvaluatorResultImpl(null, ResultType.FAILURE);
    } finally {
        result.setContext(previousContext);
    }
}
Also used : DMNResultImpl(org.kie.dmn.core.impl.DMNResultImpl) EvaluatorResult(org.kie.dmn.core.api.EvaluatorResult) FEELFunction(org.kie.dmn.feel.runtime.FEELFunction) NamedParameter(org.kie.dmn.feel.lang.impl.NamedParameter) ArrayList(java.util.ArrayList) DMNContext(org.kie.dmn.api.core.DMNContext) FEELEventListenersManager(org.kie.dmn.feel.lang.impl.FEELEventListenersManager) EvaluationContextImpl(org.kie.dmn.feel.lang.impl.EvaluationContextImpl) FEELImpl(org.kie.dmn.feel.lang.impl.FEELImpl) DMNContextImpl(org.kie.dmn.core.impl.DMNContextImpl) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Example 13 with FEELEvent

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

the class DMNFEELHelper method processEvents.

public void processEvents(DMNModelImpl model, DMNElement element, Msg.Message msg, Object... msgParams) {
    Queue<FEELEvent> feelEvents = listener.getFeelEvents();
    while (!feelEvents.isEmpty()) {
        FEELEvent event = feelEvents.remove();
        if (!isDuplicateEvent(model, msg, element)) {
            if (event instanceof SyntaxErrorEvent || event.getSeverity() == FEELEvent.Severity.ERROR) {
                if (msg instanceof Msg.Message2) {
                    MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, element, model, null, event, (Msg.Message2) msg, msgParams[0], msgParams[1]);
                } else if (msg instanceof Msg.Message3) {
                    Object message3 = null;
                    if (msgParams.length == 3) {
                        message3 = msgParams[2];
                    } else {
                        // wrap the originating FEEL error as the last message
                        message3 = event.getMessage();
                    }
                    MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, element, model, null, event, (Msg.Message3) msg, msgParams[0], msgParams[1], message3);
                } else if (msg instanceof Msg.Message4) {
                    String message = null;
                    if (event.getOffendingSymbol() == null) {
                        message = "";
                    } else if (event instanceof UnknownVariableErrorEvent) {
                        message = event.getMessage();
                    } else if (event.getOffendingSymbol() instanceof CommonToken) {
                        message = "syntax error near '" + ((CommonToken) event.getOffendingSymbol()).getText() + "'";
                    } else {
                        message = "syntax error near '" + event.getOffendingSymbol() + "'";
                    }
                    MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, element, model, null, event, (Msg.Message4) msg, msgParams[0], msgParams[1], msgParams[2], message);
                }
            }
        }
    }
}
Also used : Msg(org.kie.dmn.core.util.Msg) SyntaxErrorEvent(org.kie.dmn.feel.runtime.events.SyntaxErrorEvent) UnknownVariableErrorEvent(org.kie.dmn.feel.runtime.events.UnknownVariableErrorEvent) CommonToken(org.antlr.v4.runtime.CommonToken) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent)

Example 14 with FEELEvent

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

the class DecisionTableImpl method actualInputsMatchInputValues.

/**
 * If valid input values are defined, check that all parameters match the respective valid inputs
 * @param ctx
 * @param params
 * @return
 */
private Either<FEELEvent, Object> actualInputsMatchInputValues(EvaluationContext ctx, Object[] params) {
    // check that all the parameters match the input list values if they are defined
    for (int i = 0; i < params.length; i++) {
        final DTInputClause input = inputs.get(i);
        // if a list of values is defined, check the the parameter matches the value
        if (input.getInputValues() != null && !input.getInputValues().isEmpty()) {
            final Object parameter = params[i];
            boolean satisfies = input.getInputValues().stream().map(ut -> ut.apply(ctx, parameter)).filter(Boolean::booleanValue).findAny().orElse(false);
            if (!satisfies) {
                String values = input.getInputValuesText();
                return Either.ofLeft(new InvalidInputEvent(FEELEvent.Severity.ERROR, input.getInputExpression() + "='" + parameter + "' does not match any of the valid values " + values + " for decision table '" + getName() + "'.", getName(), null, values));
            }
        }
    }
    return Either.ofRight(true);
}
Also used : IntStream(java.util.stream.IntStream) FEEL(org.kie.dmn.feel.FEEL) LoggerFactory(org.slf4j.LoggerFactory) Either(org.kie.dmn.feel.util.Either) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) FEELFnResult(org.kie.dmn.feel.runtime.functions.FEELFnResult) Collectors.toMap(java.util.stream.Collectors.toMap) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) EvaluationContext(org.kie.dmn.feel.lang.EvaluationContext) Map(java.util.Map) EvaluationContextImpl(org.kie.dmn.feel.lang.impl.EvaluationContextImpl) InvalidInputEvent(org.kie.dmn.feel.runtime.events.InvalidInputEvent) FEELEventBase(org.kie.dmn.feel.runtime.events.FEELEventBase) HitPolicyViolationEvent(org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) Logger(org.slf4j.Logger) Severity(org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity) DecisionTableRulesMatchedEvent(org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) List(java.util.List) TreeMap(java.util.TreeMap) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) Collections(java.util.Collections) InvalidInputEvent(org.kie.dmn.feel.runtime.events.InvalidInputEvent)

Example 15 with FEELEvent

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

the class MeanFunction method invoke.

public FEELFnResult<BigDecimal> invoke(@ParameterName("list") List list) {
    if (list == null) {
        return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
    }
    FEELFnResult<BigDecimal> s = sum.invoke(list);
    Function<FEELEvent, FEELFnResult<BigDecimal>> ifLeft = (event) -> {
        return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "list", "unable to sum the elements which is required to calculate the mean"));
    };
    Function<BigDecimal, FEELFnResult<BigDecimal>> ifRight = (sum) -> {
        try {
            return FEELFnResult.ofResult(sum.divide(BigDecimal.valueOf(list.size()), MathContext.DECIMAL128));
        } catch (Exception e) {
            return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "unable to perform division to calculate the mean", e));
        }
    };
    return s.cata(ifLeft, ifRight);
}
Also used : BigDecimal(java.math.BigDecimal) Arrays(java.util.Arrays) List(java.util.List) Severity(org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) InvalidParametersEvent(org.kie.dmn.feel.runtime.events.InvalidParametersEvent) MathContext(java.math.MathContext) Function(java.util.function.Function) EvalHelper(org.kie.dmn.feel.util.EvalHelper) InvalidParametersEvent(org.kie.dmn.feel.runtime.events.InvalidParametersEvent) FEELEvent(org.kie.dmn.api.feel.runtime.events.FEELEvent) BigDecimal(java.math.BigDecimal)

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