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