Search in sources :

Example 1 with UnaryTest

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;
}
Also used : ItemDefinition(org.kie.dmn.model.v1_1.ItemDefinition) BaseDMNTypeImpl(org.kie.dmn.core.impl.BaseDMNTypeImpl) UnaryTests(org.kie.dmn.model.v1_1.UnaryTests) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) CompositeTypeImpl(org.kie.dmn.core.impl.CompositeTypeImpl) DMNType(org.kie.dmn.api.core.DMNType)

Example 2 with UnaryTest

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;
}
Also used : InformationItem(org.kie.dmn.model.v1_1.InformationItem) DMNMessage(org.kie.dmn.api.core.DMNMessage) ContextEntry(org.kie.dmn.model.v1_1.ContextEntry) OutputClause(org.kie.dmn.model.v1_1.OutputClause) FunctionDefinition(org.kie.dmn.model.v1_1.FunctionDefinition) LoggerFactory(org.slf4j.LoggerFactory) LiteralExpression(org.kie.dmn.model.v1_1.LiteralExpression) DMNExpressionEvaluator(org.kie.dmn.core.api.DMNExpressionEvaluator) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) EvaluatorResult(org.kie.dmn.core.api.EvaluatorResult) Binding(org.kie.dmn.model.v1_1.Binding) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) DMNModelInstrumentedBase(org.kie.dmn.model.v1_1.DMNModelInstrumentedBase) BaseDMNTypeImpl(org.kie.dmn.core.impl.BaseDMNTypeImpl) DMNModelImpl(org.kie.dmn.core.impl.DMNModelImpl) DecisionTable(org.kie.dmn.model.v1_1.DecisionTable) DMNRelationEvaluator(org.kie.dmn.core.ast.DMNRelationEvaluator) Collectors(java.util.stream.Collectors) BusinessKnowledgeModelNode(org.kie.dmn.api.core.ast.BusinessKnowledgeModelNode) Context(org.kie.dmn.model.v1_1.Context) List(java.util.List) DMNDTExpressionEvaluator(org.kie.dmn.core.ast.DMNDTExpressionEvaluator) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) Invocation(org.kie.dmn.model.v1_1.Invocation) Optional(java.util.Optional) QName(javax.xml.namespace.QName) DMNLiteralExpressionEvaluator(org.kie.dmn.core.ast.DMNLiteralExpressionEvaluator) BusinessKnowledgeModel(org.kie.dmn.model.v1_1.BusinessKnowledgeModel) DMNElement(org.kie.dmn.model.v1_1.DMNElement) FEEL(org.kie.dmn.feel.FEEL) MsgUtil(org.kie.dmn.core.util.MsgUtil) DMNType(org.kie.dmn.api.core.DMNType) DMNContextEvaluator(org.kie.dmn.core.ast.DMNContextEvaluator) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) EvaluatorResultImpl(org.kie.dmn.core.ast.EvaluatorResultImpl) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) ArrayList(java.util.ArrayList) HitPolicy(org.kie.dmn.model.v1_1.HitPolicy) Relation(org.kie.dmn.model.v1_1.Relation) DecisionNode(org.kie.dmn.api.core.ast.DecisionNode) FEELFunction(org.kie.dmn.feel.runtime.FEELFunction) DMNBaseNode(org.kie.dmn.core.ast.DMNBaseNode) DecisionRule(org.kie.dmn.model.v1_1.DecisionRule) UnaryTests(org.kie.dmn.model.v1_1.UnaryTests) Expression(org.kie.dmn.model.v1_1.Expression) DMNInvocationEvaluator(org.kie.dmn.core.ast.DMNInvocationEvaluator) Logger(org.slf4j.Logger) DMNListEvaluator(org.kie.dmn.core.ast.DMNListEvaluator) DTInvokerFunction(org.kie.dmn.feel.runtime.functions.DTInvokerFunction) Decision(org.kie.dmn.model.v1_1.Decision) Collectors.toList(java.util.stream.Collectors.toList) DMNFunctionDefinitionEvaluator(org.kie.dmn.core.ast.DMNFunctionDefinitionEvaluator) InputClause(org.kie.dmn.model.v1_1.InputClause) Msg(org.kie.dmn.core.util.Msg) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) Collections(java.util.Collections) BaseFEELFunction(org.kie.dmn.feel.runtime.functions.BaseFEELFunction) FEEL(org.kie.dmn.feel.FEEL) ArrayList(java.util.ArrayList) BusinessKnowledgeModelNode(org.kie.dmn.api.core.ast.BusinessKnowledgeModelNode) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) CompiledExpression(org.kie.dmn.feel.lang.CompiledExpression) ContextEntry(org.kie.dmn.model.v1_1.ContextEntry) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) DecisionRule(org.kie.dmn.model.v1_1.DecisionRule) DTDecisionRule(org.kie.dmn.feel.runtime.decisiontables.DTDecisionRule) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) DTInputClause(org.kie.dmn.feel.runtime.decisiontables.DTInputClause) InputClause(org.kie.dmn.model.v1_1.InputClause) QName(javax.xml.namespace.QName) DecisionTableImpl(org.kie.dmn.feel.runtime.decisiontables.DecisionTableImpl) LiteralExpression(org.kie.dmn.model.v1_1.LiteralExpression) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) DMNDTExpressionEvaluator(org.kie.dmn.core.ast.DMNDTExpressionEvaluator) BaseDMNTypeImpl(org.kie.dmn.core.impl.BaseDMNTypeImpl) Decision(org.kie.dmn.model.v1_1.Decision) OutputClause(org.kie.dmn.model.v1_1.OutputClause) DTOutputClause(org.kie.dmn.feel.runtime.decisiontables.DTOutputClause) BusinessKnowledgeModel(org.kie.dmn.model.v1_1.BusinessKnowledgeModel) DTInvokerFunction(org.kie.dmn.feel.runtime.functions.DTInvokerFunction) UnaryTests(org.kie.dmn.model.v1_1.UnaryTests)

Example 3 with UnaryTest

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;
}
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 UnaryTest

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.");
        }
    }
}
Also used : UnaryTest(org.kie.dmn.feel.runtime.UnaryTest)

Example 5 with UnaryTest

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;
}
Also used : UnaryTest(org.kie.dmn.feel.runtime.UnaryTest) Severity(org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity) FEELFunction(org.kie.dmn.feel.runtime.FEELFunction) EvaluationContext(org.kie.dmn.feel.lang.EvaluationContext) Msg(org.kie.dmn.feel.util.Msg) ParserRuleContext(org.antlr.v4.runtime.ParserRuleContext) Type(org.kie.dmn.feel.lang.Type) FEELFunction(org.kie.dmn.feel.runtime.FEELFunction) UnaryTest(org.kie.dmn.feel.runtime.UnaryTest)

Aggregations

UnaryTest (org.kie.dmn.feel.runtime.UnaryTest)7 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Collections (java.util.Collections)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 Collectors (java.util.stream.Collectors)2 DMNType (org.kie.dmn.api.core.DMNType)2 FEELEvent (org.kie.dmn.api.feel.runtime.events.FEELEvent)2 BaseDMNTypeImpl (org.kie.dmn.core.impl.BaseDMNTypeImpl)2 FEEL (org.kie.dmn.feel.FEEL)2 CompiledExpression (org.kie.dmn.feel.lang.CompiledExpression)2 EvaluationContext (org.kie.dmn.feel.lang.EvaluationContext)2 Type (org.kie.dmn.feel.lang.Type)2 FEELFunction (org.kie.dmn.feel.runtime.FEELFunction)2 UnaryTests (org.kie.dmn.model.v1_1.UnaryTests)2 Optional (java.util.Optional)1 UUID (java.util.UUID)1 Collectors.toList (java.util.stream.Collectors.toList)1 IntStream (java.util.stream.IntStream)1