use of org.kie.dmn.feel.runtime.events.FEELEventBase in project drools by kiegroup.
the class CustomFEELFunction method invoke.
public FEELFnResult<Object> invoke(EvaluationContext ctx, Object[] params) {
if (params.length != parameters.size()) {
return FEELFnResult.ofError(new InvalidInputEvent(Severity.ERROR, "Illegal invocation of function", getName(), getName() + "( " + Arrays.asList(params) + " )", getSignature()));
}
FEELEvent capturedException = null;
try {
ctx.enterFrame();
for (int i = 0; i < parameters.size(); i++) {
ctx.setValue(parameters.get(i), params[i]);
}
Object result = this.body.evaluate(ctx);
return FEELFnResult.ofResult(result);
} catch (Exception e) {
capturedException = new FEELEventBase(Severity.ERROR, "Error invoking function", new RuntimeException("Error invoking function " + getSignature() + ".", e));
} finally {
ctx.exitFrame();
}
return FEELFnResult.ofError(capturedException);
}
use of org.kie.dmn.feel.runtime.events.FEELEventBase 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, 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));
}
}
}
use of org.kie.dmn.feel.runtime.events.FEELEventBase in project drools by kiegroup.
the class InvokeFunction method invoke.
@Deprecated
public FEELFnResult<Object> invoke(@ParameterName("ctx") EvaluationContext ctx, @ParameterName("namespace") String namespace, @ParameterName("model name") String modelName, @ParameterName("decision name") String decisionName, @ParameterName("parameters") Map<String, Object> parameters) {
DMNRuntime dmnRuntime = ctx.getDMNRuntime();
if (namespace == null) {
return FEELFnResult.ofError(new InvalidParametersEvent(FEELEvent.Severity.ERROR, "namespace", "cannot be null"));
}
if (modelName == null) {
return FEELFnResult.ofError(new InvalidParametersEvent(FEELEvent.Severity.ERROR, "model name", "cannot be null"));
}
if (decisionName == null) {
return FEELFnResult.ofError(new InvalidParametersEvent(FEELEvent.Severity.ERROR, "decision name", "cannot be null"));
}
if (parameters == null) {
return FEELFnResult.ofError(new InvalidParametersEvent(FEELEvent.Severity.ERROR, "parameters", "cannot be null"));
}
FEELEvent capturedException = null;
try {
ctx.enterFrame();
DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);
if (dmnModel == null) {
return FEELFnResult.ofError(new FEELEventBase(FEELEvent.Severity.ERROR, "Cannot find model '" + modelName + "' in namespace " + namespace, null));
}
if (dmnModel.getDecisionByName(decisionName) == null) {
return FEELFnResult.ofError(new FEELEventBase(FEELEvent.Severity.ERROR, "Cannot find decision '" + decisionName + "' in the model", null));
}
DMNContext dmnContext = dmnRuntime.newContext();
dmnContext.getAll().putAll(parameters);
DMNResult requiredDecisionResult = dmnRuntime.evaluateByName(dmnModel, dmnContext, decisionName);
if (requiredDecisionResult.hasErrors()) {
return FEELFnResult.ofError(new FEELEventBase(FEELEvent.Severity.ERROR, "Errors occurred while invoking the external decision: " + requiredDecisionResult.getMessages(), null));
}
return FEELFnResult.ofResult(requiredDecisionResult.getContext().get(decisionName));
} catch (Exception e) {
capturedException = new FEELEventBase(FEELEvent.Severity.ERROR, "Error invoking function", new RuntimeException("Error invoking function " + getName() + ".", e));
} finally {
ctx.exitFrame();
}
return FEELFnResult.ofError(capturedException);
}
use of org.kie.dmn.feel.runtime.events.FEELEventBase in project drools by kiegroup.
the class BaseFEELFunction method invokeReflectively.
@Override
@GwtIncompatible
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 {
// CandidateMethod cm could be null also if reflection failed on Platforms not supporting getClass().getDeclaredMethods()
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.getParameters().get(0).stream().map(Param::getName).collect(Collectors.toList()));
}
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;
}
use of org.kie.dmn.feel.runtime.events.FEELEventBase in project drools by kiegroup.
the class AbstractCustomFEELFunction method invoke.
public FEELFnResult<Object> invoke(EvaluationContext ctx, Object[] params) {
if (params.length != parameters.size()) {
return FEELFnResult.ofError(new InvalidInputEvent(Severity.ERROR, "Illegal invocation of function", getName(), getName() + "( " + Arrays.asList(params) + " )", getSignature()));
}
FEELEvent capturedException = null;
try {
ctx.enterFrame();
for (int i = 0; i < parameters.size(); i++) {
final String paramName = parameters.get(i).name;
if (parameters.get(i).type.isAssignableValue(params[i])) {
ctx.setValue(paramName, params[i]);
} else {
ctx.setValue(paramName, null);
ctx.notifyEvt(() -> {
InvalidParametersEvent evt = new InvalidParametersEvent(Severity.WARN, paramName, "not conformant");
evt.setNodeName(getName());
evt.setActualParameters(parameters.stream().map(FEELFunction.Param::getName).collect(Collectors.toList()), Arrays.asList(params));
return evt;
});
}
}
Object result = internalInvoke(ctx);
return FEELFnResult.ofResult(result);
} catch (Exception e) {
capturedException = new FEELEventBase(Severity.ERROR, "Error invoking function", new RuntimeException("Error invoking function " + getSignature() + ".", e));
} finally {
ctx.exitFrame();
}
return FEELFnResult.ofError(capturedException);
}
Aggregations