use of org.kie.dmn.feel.runtime.UnaryTest in project drools by kiegroup.
the class DMNCompilerImpl method buildTypeDef.
private DMNType buildTypeDef(DMNCompilerContext ctx, DMNFEELHelper feel, DMNModelImpl dmnModel, DMNNode node, ItemDefinition itemDef, boolean topLevel) {
BaseDMNTypeImpl type = null;
if (itemDef.getTypeRef() != null) {
// this is a reference to an existing type, so resolve the reference
type = (BaseDMNTypeImpl) resolveTypeRef(dmnModel, node, itemDef, itemDef, itemDef.getTypeRef());
if (type != null) {
UnaryTests allowedValuesStr = itemDef.getAllowedValues();
// or if it changes the metadata for the base type
if (topLevel || allowedValuesStr != null || itemDef.isIsCollection() != type.isCollection()) {
// we have to clone this type definition into a new one
BaseDMNTypeImpl baseType = type;
type = type.clone();
type.setBaseType(baseType);
type.setNamespace(dmnModel.getNamespace());
type.setName(itemDef.getName());
type.setAllowedValues(null);
if (allowedValuesStr != null) {
List<UnaryTest> av = feel.evaluateUnaryTests(ctx, allowedValuesStr.getText(), dmnModel, itemDef, Msg.ERR_COMPILING_ALLOWED_VALUES_LIST_ON_ITEM_DEF, allowedValuesStr.getText(), node.getName());
type.setAllowedValues(av);
}
if (itemDef.isIsCollection()) {
type.setCollection(itemDef.isIsCollection());
}
}
if (topLevel) {
DMNType registered = dmnModel.getTypeRegistry().registerType(type);
if (registered != type) {
MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, itemDef, dmnModel, null, null, Msg.DUPLICATED_ITEM_DEFINITION, itemDef.getName());
}
}
}
} else {
// this is a composite type
DMNCompilerHelper.checkVariableName(dmnModel, itemDef, itemDef.getName());
CompositeTypeImpl compType = new CompositeTypeImpl(dmnModel.getNamespace(), itemDef.getName(), itemDef.getId(), itemDef.isIsCollection());
for (ItemDefinition fieldDef : itemDef.getItemComponent()) {
DMNCompilerHelper.checkVariableName(dmnModel, fieldDef, fieldDef.getName());
DMNType fieldType = buildTypeDef(ctx, feel, dmnModel, node, fieldDef, false);
fieldType = fieldType != null ? fieldType : DMNTypeRegistry.UNKNOWN;
compType.addField(fieldDef.getName(), fieldType);
}
type = compType;
if (topLevel) {
DMNType registered = dmnModel.getTypeRegistry().registerType(type);
if (registered != type) {
MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, itemDef, dmnModel, null, null, Msg.DUPLICATED_ITEM_DEFINITION, itemDef.getName());
}
}
}
return type;
}
use of org.kie.dmn.feel.runtime.UnaryTest in project drools by kiegroup.
the class DMNEvaluatorCompiler method compileDecisionTable.
private DMNExpressionEvaluator compileDecisionTable(DMNCompilerContext ctx, DMNModelImpl model, DMNBaseNode node, String dtName, DecisionTable dt) {
java.util.List<DTInputClause> inputs = new ArrayList<>();
int index = 0;
for (InputClause ic : dt.getInput()) {
index++;
String inputExpressionText = ic.getInputExpression().getText();
String inputValuesText = Optional.ofNullable(ic.getInputValues()).map(UnaryTests::getText).orElse(null);
java.util.List<UnaryTest> inputValues = null;
if (inputValuesText != null) {
inputValues = textToUnaryTestList(ctx, inputValuesText, model, ic, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_INPUT_CLAUSE_IDX, inputValuesText, node.getIdentifierString(), index);
} else if (ic.getInputExpression().getTypeRef() != null) {
QName inputExpressionTypeRef = ic.getInputExpression().getTypeRef();
BaseDMNTypeImpl typeRef = (BaseDMNTypeImpl) model.getTypeRegistry().resolveType(resolveNamespaceForTypeRef(inputExpressionTypeRef, ic.getInputExpression()), inputExpressionTypeRef.getLocalPart());
inputValues = typeRef.getAllowedValuesFEEL();
}
CompiledExpression compiledInput = feel.compileFeelExpression(ctx, inputExpressionText, model, dt, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_INPUT_CLAUSE_IDX, inputExpressionText, dtName, index);
inputs.add(new DTInputClause(inputExpressionText, inputValuesText, inputValues, compiledInput));
}
java.util.List<DTOutputClause> outputs = new ArrayList<>();
index = 0;
boolean hasOutputValues = false;
for (OutputClause oc : dt.getOutput()) {
String outputName = oc.getName();
if (outputName != null) {
DMNCompilerHelper.checkVariableName(model, node.getSource(), outputName);
}
String id = oc.getId();
String outputValuesText = Optional.ofNullable(oc.getOutputValues()).map(UnaryTests::getText).orElse(null);
String defaultValue = oc.getDefaultOutputEntry() != null ? oc.getDefaultOutputEntry().getText() : null;
BaseDMNTypeImpl typeRef = (BaseDMNTypeImpl) DMNTypeRegistry.UNKNOWN;
java.util.List<UnaryTest> outputValues = null;
if (oc.getTypeRef() != null) {
QName outputExpressionTypeRef = oc.getTypeRef();
typeRef = (BaseDMNTypeImpl) model.getTypeRegistry().resolveType(resolveNamespaceForTypeRef(outputExpressionTypeRef, oc), outputExpressionTypeRef.getLocalPart());
if (typeRef == null) {
typeRef = (BaseDMNTypeImpl) DMNTypeRegistry.UNKNOWN;
}
} else if (dt.getOutput().size() == 1 && (dt.getParent() instanceof Decision || dt.getParent() instanceof BusinessKnowledgeModel || dt.getParent() instanceof ContextEntry)) {
QName inferredTypeRef = recurseUpToInferTypeRef(model, oc, dt);
// if inferredTypeRef is null, a std err will have been reported
if (inferredTypeRef != null) {
typeRef = (BaseDMNTypeImpl) model.getTypeRegistry().resolveType(resolveNamespaceForTypeRef(inferredTypeRef, oc), inferredTypeRef.getLocalPart());
}
}
if (outputValuesText != null) {
outputValues = textToUnaryTestList(ctx, outputValuesText, model, oc, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_OUTPUT_CLAUSE_IDX, outputValuesText, node.getIdentifierString(), ++index);
} else if (typeRef != DMNTypeRegistry.UNKNOWN) {
outputValues = typeRef.getAllowedValuesFEEL();
}
if (outputValues != null && !outputValues.isEmpty()) {
hasOutputValues = true;
}
outputs.add(new DTOutputClause(outputName, id, outputValues, defaultValue, typeRef.getFeelType(), typeRef.isCollection()));
}
if (dt.getHitPolicy().equals(HitPolicy.PRIORITY) && !hasOutputValues) {
MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, dt.getParent(), model, null, null, Msg.MISSING_OUTPUT_VALUES, dt.getParent());
}
java.util.List<DTDecisionRule> rules = new ArrayList<>();
index = 0;
for (DecisionRule dr : dt.getRule()) {
DTDecisionRule rule = new DTDecisionRule(index);
for (UnaryTests ut : dr.getInputEntry()) {
final java.util.List<UnaryTest> tests;
if (ut == null || ut.getText() == null || ut.getText().isEmpty()) {
tests = Collections.emptyList();
MsgUtil.reportMessage(logger, DMNMessage.Severity.ERROR, ut, model, null, null, Msg.DTABLE_EMPTY_ENTRY, dt.getRule().indexOf(dr) + 1, dr.getInputEntry().indexOf(ut) + 1, dt.getParentDRDElement().getIdentifierString());
} else {
tests = textToUnaryTestList(ctx, ut.getText(), model, dr, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_RULE_IDX, ut.getText(), node.getIdentifierString(), index + 1);
}
rule.getInputEntry().add((c, x) -> tests.stream().anyMatch(t -> {
Boolean result = t.apply(c, x);
return result != null && result == true;
}));
}
for (LiteralExpression le : dr.getOutputEntry()) {
String expressionText = le.getText();
CompiledExpression compiledExpression = feel.compileFeelExpression(ctx, expressionText, model, dr, Msg.ERR_COMPILING_FEEL_EXPR_ON_DT_RULE_IDX, expressionText, dtName, index + 1);
rule.getOutputEntry().add(compiledExpression);
}
rules.add(rule);
index++;
}
String policy = dt.getHitPolicy().value() + (dt.getAggregation() != null ? " " + dt.getAggregation().value() : "");
org.kie.dmn.feel.runtime.decisiontables.HitPolicy hp = org.kie.dmn.feel.runtime.decisiontables.HitPolicy.fromString(policy);
java.util.List<String> parameterNames = new ArrayList<>();
if (node instanceof BusinessKnowledgeModelNode) {
// need to break this statement down and check for nulls
parameterNames.addAll(((BusinessKnowledgeModelNode) node).getBusinessKnowledModel().getEncapsulatedLogic().getFormalParameter().stream().map(f -> f.getName()).collect(toList()));
} else {
parameterNames.addAll(node.getDependencies().keySet());
}
// creates a FEEL instance which will be used by the invoker/impl (s)
FEEL feelInstance = feel.newFEELInstance();
DecisionTableImpl dti = new DecisionTableImpl(dtName, parameterNames, inputs, outputs, rules, hp, feelInstance);
DTInvokerFunction dtf = new DTInvokerFunction(dti);
DMNDTExpressionEvaluator dtee = new DMNDTExpressionEvaluator(node, feelInstance, dtf);
return dtee;
}
use of org.kie.dmn.feel.runtime.UnaryTest 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;
}
use of org.kie.dmn.feel.runtime.UnaryTest in project drools by kiegroup.
the class DecisionTableImpl method checkOneValue.
private void checkOneValue(EvaluationContext ctx, DTDecisionRule rule, Map<Integer, String> msgs, DTOutputClause dtOutputClause, Object value) {
if (((EvaluationContextImpl) ctx).isPerformRuntimeTypeCheck() && !dtOutputClause.getType().isAssignableValue(value)) {
// invalid type
int index = outputs.indexOf(dtOutputClause) + 1;
msgs.put(index, "Invalid result type on rule #" + rule.getIndex() + ", output " + (dtOutputClause.getName() != null ? "'" + dtOutputClause.getName() + "'" : "#" + index) + ". Value " + value + " is not of type " + dtOutputClause.getType().getName() + ".");
return;
}
if (dtOutputClause.getOutputValues() != null && !dtOutputClause.getOutputValues().isEmpty()) {
boolean found = false;
for (UnaryTest test : dtOutputClause.getOutputValues()) {
Boolean succeeded = test.apply(ctx, value);
if (succeeded != null && succeeded) {
found = true;
}
}
if (!found) {
// invalid result
int index = outputs.indexOf(dtOutputClause) + 1;
msgs.put(index, "Invalid result value on rule #" + rule.getIndex() + ", output " + (dtOutputClause.getName() != null ? "'" + dtOutputClause.getName() + "'" : "#" + index) + ". Value " + value + " does not match list of allowed values.");
}
}
}
use of org.kie.dmn.feel.runtime.UnaryTest in project drools by kiegroup.
the class FunctionInvocationNode method evaluate.
@Override
public Object evaluate(EvaluationContext ctx) {
FEELFunction function = null;
Object value = null;
if (name instanceof NameRefNode) {
// simple name
value = ctx.getValue(name.getText());
} else {
QualifiedNameNode qn = (QualifiedNameNode) name;
String[] qns = qn.getPartsAsStringArray();
value = ctx.getValue(qns);
}
if (value instanceof FEELFunction) {
function = (FEELFunction) value;
if (function != null) {
Object[] p = params.getElements().stream().map(e -> e.evaluate(ctx)).toArray(Object[]::new);
Object result = function.invokeReflectively(ctx, p);
return result;
} else {
ctx.notifyEvt(astEvent(Severity.ERROR, Msg.createMessage(Msg.FUNCTION_NOT_FOUND, name.getText())));
}
} else if (value instanceof UnaryTest) {
if (params.getElements().size() == 1) {
Object p = params.getElements().get(0).evaluate(ctx);
return ((UnaryTest) value).apply(ctx, p);
} else {
ctx.notifyEvt(astEvent(Severity.ERROR, Msg.createMessage(Msg.CAN_T_INVOKE_AN_UNARY_TEST_WITH_S_PARAMETERS_UNARY_TESTS_REQUIRE_1_SINGLE_PARAMETER, params.getElements().size())));
}
}
return null;
}
Aggregations