Search in sources :

Example 11 with InternalReadAccessor

use of org.drools.core.spi.InternalReadAccessor in project drools by kiegroup.

the class PatternBuilder method getFieldReadAccessor.

public static InternalReadAccessor getFieldReadAccessor(final RuleBuildContext context, final BaseDescr descr, final Pattern pattern, final ObjectType objectType, String fieldName, final AcceptsReadAccessor target, final boolean reportError) {
    // reportError is needed as some times failure to build accessor is not a failure, just an indication that building is not possible so try something else.
    InternalReadAccessor reader;
    if (ValueType.FACTTEMPLATE_TYPE.equals(objectType.getValueType())) {
        // @todo use accessor cache
        final FactTemplate factTemplate = ((FactTemplateObjectType) objectType).getFactTemplate();
        reader = new FactTemplateFieldExtractor(factTemplate, factTemplate.getFieldTemplateIndex(fieldName));
        if (target != null) {
            target.setReadAccessor(reader);
        }
        return reader;
    }
    boolean isGetter = getterRegexp.matcher(fieldName).matches();
    if (isGetter) {
        fieldName = fieldName.substring(3, fieldName.indexOf('(')).trim();
    }
    if (isGetter || identifierRegexp.matcher(fieldName).matches()) {
        Declaration decl = context.getDeclarationResolver().getDeclarations(context.getRule()).get(fieldName);
        if (decl != null && decl.getExtractor() instanceof ClassFieldReader && "this".equals(((ClassFieldReader) decl.getExtractor()).getFieldName())) {
            return decl.getExtractor();
        }
        try {
            reader = context.getPkg().getClassFieldAccessorStore().getReader(objectType.getClassName(), fieldName, target);
        } catch (final Exception e) {
            if (reportError && context.isTypesafe()) {
                DialectUtil.copyErrorLocation(e, descr);
                registerDescrBuildError(context, descr, e, "Unable to create Field Extractor for '" + fieldName + "'" + e.getMessage());
            }
            // if there was an error, set the reader back to null
            reader = null;
        } finally {
            if (reportError) {
                Collection<KnowledgeBuilderResult> results = context.getPkg().getClassFieldAccessorStore().getWiringResults(objectType.getClassType(), fieldName);
                if (!results.isEmpty()) {
                    for (KnowledgeBuilderResult res : results) {
                        if (res.getSeverity() == ResultSeverity.ERROR) {
                            context.addError(new DroolsErrorWrapper(res));
                        } else {
                            context.addWarning(new DroolsWarningWrapper(res));
                        }
                    }
                }
            }
        }
    } else {
        // we need MVEL extractor for expressions
        Dialect dialect = context.getDialect();
        try {
            MVELDialect mvelDialect = (MVELDialect) context.getDialect("mvel");
            context.setDialect(mvelDialect);
            final AnalysisResult analysis = context.getDialect().analyzeExpression(context, descr, fieldName, new BoundIdentifiers(pattern, context, Collections.EMPTY_MAP, objectType.getClassType()));
            if (analysis == null) {
                // something bad happened
                if (reportError) {
                    registerDescrBuildError(context, descr, "Unable to analyze expression '" + fieldName + "'");
                }
                return null;
            }
            final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();
            if (!usedIdentifiers.getDeclrClasses().isEmpty()) {
                if (reportError && descr instanceof BindingDescr) {
                    registerDescrBuildError(context, descr, "Variables can not be used inside bindings. Variable " + usedIdentifiers.getDeclrClasses().keySet() + " is being used in binding '" + fieldName + "'");
                }
                return null;
            }
            reader = context.getPkg().getClassFieldAccessorStore().getMVELReader(context.getPkg().getName(), objectType.getClassName(), fieldName, context.isTypesafe(), ((MVELAnalysisResult) analysis).getReturnType());
            MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
            ((MVELCompileable) reader).compile(data, context.getRule());
            data.addCompileable((MVELCompileable) reader);
        } catch (final Exception e) {
            int dotPos = fieldName.indexOf('.');
            String varName = dotPos > 0 ? fieldName.substring(0, dotPos).trim() : fieldName;
            if (context.getKnowledgeBuilder().getGlobals().containsKey(varName)) {
                return null;
            }
            if (reportError) {
                DialectUtil.copyErrorLocation(e, descr);
                registerDescrBuildError(context, descr, e, "Unable to create reader for '" + fieldName + "':" + e.getMessage());
            }
            // if there was an error, set the reader back to null
            reader = null;
        } finally {
            context.setDialect(dialect);
        }
    }
    return reader;
}
Also used : FactTemplateFieldExtractor(org.drools.core.facttemplates.FactTemplateFieldExtractor) BindingDescr(org.drools.compiler.lang.descr.BindingDescr) MVELCompileable(org.drools.core.base.mvel.MVELCompileable) DroolsErrorWrapper(org.drools.compiler.compiler.DroolsErrorWrapper) MVELDialect(org.drools.compiler.rule.builder.dialect.mvel.MVELDialect) DroolsParserException(org.drools.compiler.compiler.DroolsParserException) AnalysisResult(org.drools.compiler.compiler.AnalysisResult) MVELAnalysisResult(org.drools.compiler.rule.builder.dialect.mvel.MVELAnalysisResult) BoundIdentifiers(org.drools.compiler.compiler.BoundIdentifiers) MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) MVELAnalysisResult(org.drools.compiler.rule.builder.dialect.mvel.MVELAnalysisResult) ClassFieldReader(org.drools.core.base.ClassFieldReader) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) Dialect(org.drools.compiler.compiler.Dialect) MVELDialect(org.drools.compiler.rule.builder.dialect.mvel.MVELDialect) JavaDialect(org.drools.compiler.rule.builder.dialect.java.JavaDialect) FactTemplateObjectType(org.drools.core.facttemplates.FactTemplateObjectType) DroolsWarningWrapper(org.drools.compiler.compiler.DroolsWarningWrapper) Declaration(org.drools.core.rule.Declaration) TypeDeclaration(org.drools.core.rule.TypeDeclaration) FactTemplate(org.drools.core.facttemplates.FactTemplate) KnowledgeBuilderResult(org.kie.internal.builder.KnowledgeBuilderResult)

Example 12 with InternalReadAccessor

use of org.drools.core.spi.InternalReadAccessor in project drools by kiegroup.

the class PatternBuilder method buildRuleBindings.

protected void buildRuleBindings(RuleBuildContext context, PatternDescr patternDescr, Pattern pattern, BindingDescr fieldBindingDescr, TypeDeclaration typeDeclaration) {
    if (context.getDeclarationResolver().isDuplicated(context.getRule(), fieldBindingDescr.getVariable(), null)) {
        processDuplicateBindings(fieldBindingDescr.isUnification(), patternDescr, pattern, fieldBindingDescr, fieldBindingDescr.getBindingField(), fieldBindingDescr.getVariable(), context);
        if (fieldBindingDescr.isUnification()) {
            return;
        }
    }
    Declaration declr = pattern.addDeclaration(fieldBindingDescr.getVariable());
    final InternalReadAccessor extractor = getFieldReadAccessor(context, fieldBindingDescr, pattern, fieldBindingDescr.getBindingField(), declr, true);
    if (extractor == null) {
        registerDescrBuildError(context, patternDescr, "Field Reader does not exist for declaration '" + fieldBindingDescr.getVariable() + "' in '" + fieldBindingDescr + "' in the rule '" + context.getRule().getName() + "'");
        return;
    }
    declr.setReadAccessor(extractor);
    if (typeDeclaration != null && extractor instanceof ClassFieldReader) {
        addFieldToPatternWatchlist(pattern, typeDeclaration, ((ClassFieldReader) extractor).getFieldName());
    }
}
Also used : ClassFieldReader(org.drools.core.base.ClassFieldReader) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) Declaration(org.drools.core.rule.Declaration) TypeDeclaration(org.drools.core.rule.TypeDeclaration)

Example 13 with InternalReadAccessor

use of org.drools.core.spi.InternalReadAccessor in project drools by kiegroup.

the class MVELAccumulateBuilder method buildExternalFunctions.

private Accumulator[] buildExternalFunctions(final RuleBuildContext context, final AccumulateDescr accumDescr, MVELDialect dialect, Map<String, Declaration> decls, Map<String, Declaration> sourceOuterDeclr, BoundIdentifiers boundIds, boolean readLocalsFromTuple) {
    Accumulator[] accumulators;
    List<AccumulateFunctionCallDescr> functions = accumDescr.getFunctions();
    accumulators = new Accumulator[functions.size()];
    // creating the custom array reader
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class);
    int index = 0;
    Pattern pattern = (Pattern) context.getDeclarationResolver().peekBuildStack();
    for (AccumulateFunctionCallDescr func : functions) {
        // build an external function executor
        AccumulateFunction function = context.getConfiguration().getAccumulateFunction(func.getFunction());
        if (function == null) {
            // might have been imported in the package
            function = context.getPkg().getAccumulateFunctions().get(func.getFunction());
        }
        if (function == null) {
            context.addError(new DescrBuildError(accumDescr, context.getRuleDescr(), null, "Unknown accumulate function: '" + func.getFunction() + "' on rule '" + context.getRuleDescr().getName() + "'. All accumulate functions must be registered before building a resource."));
            return null;
        }
        final AnalysisResult analysis = dialect.analyzeExpression(context, accumDescr, func.getParams().length > 0 ? func.getParams()[0] : "\"\"", boundIds);
        MVELCompilationUnit unit = dialect.getMVELCompilationUnit(func.getParams().length > 0 ? func.getParams()[0] : "\"\"", analysis, getUsedDeclarations(decls, analysis), getUsedDeclarations(sourceOuterDeclr, analysis), null, context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT);
        accumulators[index] = new MVELAccumulatorFunctionExecutor(unit, function);
        // if there is a binding, create the binding
        if (func.getBind() != null) {
            if (context.getDeclarationResolver().isDuplicated(context.getRule(), func.getBind(), function.getResultType().getName())) {
                if (!func.isUnification()) {
                    context.addError(new DescrBuildError(context.getParentDescr(), accumDescr, null, "Duplicate declaration for variable '" + func.getBind() + "' in the rule '" + context.getRule().getName() + "'"));
                } else {
                    Declaration inner = context.getDeclarationResolver().getDeclaration(func.getBind());
                    Constraint c = new MvelConstraint(Collections.singletonList(context.getPkg().getName()), accumDescr.isMultiFunction() ? "this[ " + index + " ] == " + func.getBind() : "this == " + func.getBind(), new Declaration[] { inner }, null, null, IndexUtil.ConstraintType.EQUAL, context.getDeclarationResolver().getDeclaration(func.getBind()), accumDescr.isMultiFunction() ? new ArrayElementReader(arrayReader, index, function.getResultType()) : new SelfReferenceClassFieldReader(function.getResultType()), true);
                    ((MutableTypeConstraint) c).setType(Constraint.ConstraintType.BETA);
                    pattern.addConstraint(c);
                    index++;
                }
            } else {
                Declaration declr = pattern.addDeclaration(func.getBind());
                if (accumDescr.isMultiFunction()) {
                    declr.setReadAccessor(new ArrayElementReader(arrayReader, index, function.getResultType()));
                } else {
                    declr.setReadAccessor(new SelfReferenceClassFieldReader(function.getResultType()));
                }
            }
        }
        index++;
    }
    return accumulators;
}
Also used : MVELAccumulator(org.drools.core.base.mvel.MVELAccumulator) Accumulator(org.drools.core.spi.Accumulator) MvelAccumulator(org.drools.core.spi.MvelAccumulator) Pattern(org.drools.core.rule.Pattern) MVELAccumulatorFunctionExecutor(org.drools.core.base.accumulators.MVELAccumulatorFunctionExecutor) MutableTypeConstraint(org.drools.core.rule.MutableTypeConstraint) MvelConstraint(org.drools.core.rule.constraint.MvelConstraint) Constraint(org.drools.core.spi.Constraint) MVELCompilationUnit(org.drools.core.base.mvel.MVELCompilationUnit) MvelConstraint(org.drools.core.rule.constraint.MvelConstraint) MutableTypeConstraint(org.drools.core.rule.MutableTypeConstraint) MutableTypeConstraint(org.drools.core.rule.MutableTypeConstraint) MvelConstraint(org.drools.core.rule.constraint.MvelConstraint) Constraint(org.drools.core.spi.Constraint) AnalysisResult(org.drools.compiler.compiler.AnalysisResult) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) AccumulateFunctionCallDescr(org.drools.compiler.lang.descr.AccumulateDescr.AccumulateFunctionCallDescr) ArrayElementReader(org.drools.core.base.extractors.ArrayElementReader) Declaration(org.drools.core.rule.Declaration) AccumulateFunction(org.kie.api.runtime.rule.AccumulateFunction)

Example 14 with InternalReadAccessor

use of org.drools.core.spi.InternalReadAccessor in project drools by kiegroup.

the class QueryBuilder method build.

public Pattern build(final RuleBuildContext context, final QueryDescr queryDescr) {
    ObjectType queryObjectType = ClassObjectType.DroolsQuery_ObjectType;
    final Pattern pattern = new Pattern(context.getNextPatternId(), // offset is 0 by default
    0, queryObjectType, null);
    final InternalReadAccessor extractor = PatternBuilder.getFieldReadAccessor(context, queryDescr, pattern, "name", null, true);
    final QueryNameConstraint constraint = new QueryNameConstraint(extractor, queryDescr.getName());
    PatternBuilder.registerReadAccessor(context, queryObjectType, "name", constraint);
    // adds appropriate constraint to the pattern
    pattern.addConstraint(constraint);
    ObjectType argsObjectType = ClassObjectType.DroolsQuery_ObjectType;
    InternalReadAccessor arrayExtractor = PatternBuilder.getFieldReadAccessor(context, queryDescr, null, argsObjectType, "elements", null, true);
    QueryImpl query = ((QueryImpl) context.getRule());
    String[] params;
    String[] types;
    int numParams = queryDescr.getParameters().length;
    if (query.isAbductive()) {
        params = Arrays.copyOf(queryDescr.getParameters(), queryDescr.getParameters().length + 1);
        types = Arrays.copyOf(queryDescr.getParameterTypes(), queryDescr.getParameterTypes().length + 1);
    } else {
        params = queryDescr.getParameters();
        types = queryDescr.getParameterTypes();
    }
    Declaration[] declarations = new Declaration[params.length];
    Class<?> abductionReturnKlass = null;
    if (query.isAbductive()) {
        Abductive abductive = queryDescr.getTypedAnnotation(Abductive.class);
        abductionReturnKlass = abductive.target();
        params[numParams] = "";
        types[numParams] = abductionReturnKlass.getName();
    }
    int i = 0;
    try {
        for (i = 0; i < params.length; i++) {
            Declaration declr = pattern.addDeclaration(params[i]);
            // this bit is different, notice its the ArrayElementReader that we wire up to, not the declaration.
            ArrayElementReader reader = new ArrayElementReader(arrayExtractor, i, context.getDialect().getTypeResolver().resolveType(types[i]));
            PatternBuilder.registerReadAccessor(context, argsObjectType, "elements", reader);
            declr.setReadAccessor(reader);
            declarations[i] = declr;
        }
        query.setParameters(declarations);
    } catch (ClassNotFoundException e) {
        context.addError(new DescrBuildError(context.getParentDescr(), queryDescr, e, "Unable to resolve type '" + types[i] + " for parameter" + params[i]));
    }
    context.setPrefixPattern(pattern);
    if (query.isAbductive()) {
        String returnName = "";
        try {
            AnnotationDescr ann = queryDescr.getAnnotation(Abductive.class);
            Object[] argsVal = ((Object[]) ann.getValue("args"));
            String[] args = argsVal != null ? Arrays.copyOf(argsVal, argsVal.length, String[].class) : null;
            returnName = types[numParams];
            ObjectType objectType = new ClassObjectType(abductionReturnKlass, false);
            objectType = context.getPkg().getClassFieldAccessorStore().wireObjectType(objectType, (AbductiveQuery) query);
            ((AbductiveQuery) query).setReturnType(objectType, params, args, declarations);
        } catch (NoSuchMethodException e) {
            context.addError(new DescrBuildError(context.getParentDescr(), queryDescr, e, "Unable to resolve abducible constructor for type : " + returnName + " with types " + Arrays.toString(types)));
        } catch (IllegalArgumentException e) {
            context.addError(new DescrBuildError(context.getParentDescr(), queryDescr, e, e.getMessage()));
        }
    }
    return pattern;
}
Also used : Pattern(org.drools.core.rule.Pattern) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint) ClassObjectType(org.drools.core.base.ClassObjectType) Abductive(org.drools.core.beliefsystem.abductive.Abductive) AnnotationDescr(org.drools.compiler.lang.descr.AnnotationDescr) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint) ClassObjectType(org.drools.core.base.ClassObjectType) ObjectType(org.drools.core.spi.ObjectType) QueryImpl(org.drools.core.rule.QueryImpl) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) ArrayElementReader(org.drools.core.base.extractors.ArrayElementReader) Declaration(org.drools.core.rule.Declaration) AbductiveQuery(org.drools.core.rule.AbductiveQuery)

Example 15 with InternalReadAccessor

use of org.drools.core.spi.InternalReadAccessor in project drools by kiegroup.

the class TemporalEvaluatorFactoryTest method runEvaluatorTest.

private void runEvaluatorTest(final Object[][] data, final ValueType valueType) {
    final InternalReadAccessor extractor = new MockExtractor();
    for (int i = 0; i < data.length; i++) {
        final Object[] row = data[i];
        boolean isNegated = ((String) row[1]).startsWith("not ");
        // System.out.println((String) row[1]);
        String evaluatorStr = isNegated ? ((String) row[1]).substring(4) : (String) row[1];
        boolean isConstrained = evaluatorStr.endsWith("]");
        String parameters = null;
        if (isConstrained) {
            parameters = evaluatorStr.split("\\[")[1];
            evaluatorStr = evaluatorStr.split("\\[")[0];
            parameters = parameters.split("\\]")[0];
        }
        EvaluatorDefinition evalDef = registry.getEvaluatorDefinition(evaluatorStr);
        assertNotNull(evalDef);
        final Evaluator evaluator = evalDef.getEvaluator(valueType, evaluatorStr, isNegated, parameters);
        // System.out.println(evaluator);
        checkEvaluatorMethodWith2Extractors(valueType, extractor, row, evaluator);
        checkEvaluatorMethodCachedRight(valueType, extractor, row, evaluator);
        checkEvaluatorMethodCachedLeft(valueType, extractor, row, evaluator);
        checkEvaluatorMethodWithFieldValue(valueType, extractor, row, evaluator);
        assertEquals(valueType, evaluator.getValueType());
    }
}
Also used : InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) DuringEvaluatorDefinition(org.drools.core.base.evaluators.DuringEvaluatorDefinition) CoincidesEvaluatorDefinition(org.drools.core.base.evaluators.CoincidesEvaluatorDefinition) BeforeEvaluatorDefinition(org.drools.core.base.evaluators.BeforeEvaluatorDefinition) MetByEvaluatorDefinition(org.drools.core.base.evaluators.MetByEvaluatorDefinition) AfterEvaluatorDefinition(org.drools.core.base.evaluators.AfterEvaluatorDefinition) EvaluatorDefinition(org.drools.core.base.evaluators.EvaluatorDefinition) MeetsEvaluatorDefinition(org.drools.core.base.evaluators.MeetsEvaluatorDefinition) Evaluator(org.drools.core.spi.Evaluator) DisconnectedWorkingMemoryEntryPoint(org.drools.core.common.DisconnectedWorkingMemoryEntryPoint)

Aggregations

InternalReadAccessor (org.drools.core.spi.InternalReadAccessor)58 Declaration (org.drools.core.rule.Declaration)27 Test (org.junit.Test)27 ClassObjectType (org.drools.core.base.ClassObjectType)26 Pattern (org.drools.core.rule.Pattern)23 Cheese (org.drools.core.test.model.Cheese)15 MvelConstraintTestUtil (org.drools.core.rule.MvelConstraintTestUtil)14 MvelConstraint (org.drools.core.rule.constraint.MvelConstraint)10 InternalFactHandle (org.drools.core.common.InternalFactHandle)9 FieldValue (org.drools.core.spi.FieldValue)9 DefaultFactHandle (org.drools.core.common.DefaultFactHandle)8 TypeDeclaration (org.drools.core.rule.TypeDeclaration)7 FieldIndex (org.drools.core.util.AbstractHashTable.FieldIndex)7 TupleIndexHashTable (org.drools.core.util.index.TupleIndexHashTable)7 InternalKnowledgePackage (org.drools.core.definitions.InternalKnowledgePackage)6 KnowledgePackageImpl (org.drools.core.definitions.impl.KnowledgePackageImpl)6 LeftTupleImpl (org.drools.core.reteoo.LeftTupleImpl)6 RightTupleImpl (org.drools.core.reteoo.RightTupleImpl)6 BindingDescr (org.drools.compiler.lang.descr.BindingDescr)5 ClassFieldAccessorStore (org.drools.core.base.ClassFieldAccessorStore)5