Search in sources :

Example 1 with SelfReferenceClassFieldReader

use of org.drools.core.base.extractors.SelfReferenceClassFieldReader in project drools by kiegroup.

the class ClassFieldAccessorFactory method getClassFieldReader.

public static BaseClassFieldReader getClassFieldReader(Class<?> clazz, String fieldName, CacheEntry cache) {
    try {
        // if it is a self reference
        if (SELF_REFERENCE_FIELD.equals(fieldName)) {
            // then just create an instance of the special class field extractor
            return new SelfReferenceClassFieldReader(clazz);
        } else {
            // otherwise, bytecode generate a specific extractor
            ClassFieldInspector inspector = getClassFieldInspector(clazz, cache);
            Method getterMethod = inspector.getGetterMethods().get(fieldName);
            Integer index = inspector.getFieldNames().get(fieldName);
            Class<?> fieldType = inspector.getFieldType(fieldName);
            if (fieldType == null && fieldName.length() > 1 && Character.isLowerCase(fieldName.charAt(0)) && Character.isUpperCase(fieldName.charAt(1))) {
                // it might be that odd case of javabeans naming conventions that does not use lower case first letters if the second is uppercase
                String altFieldName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
                fieldType = inspector.getFieldType(altFieldName);
                if (fieldType != null) {
                    // it seems it is the corner case indeed.
                    getterMethod = inspector.getGetterMethods().get(altFieldName);
                    index = inspector.getFieldNames().get(altFieldName);
                }
            }
            if (fieldType != null && getterMethod != null) {
                final String className = ClassFieldAccessorFactory.BASE_PACKAGE + "/" + Type.getInternalName(clazz) + Math.abs(System.identityHashCode(clazz)) + "$" + getterMethod.getName();
                // generating byte array to create target class
                final byte[] bytes = dumpReader(clazz, className, getterMethod, fieldType);
                // use bytes to get a class
                ByteArrayClassLoader byteArrayClassLoader = cache.getByteArrayClassLoader();
                final Class<?> newClass = byteArrayClassLoader.defineClass(className.replace('/', '.'), bytes, PROTECTION_DOMAIN);
                // instantiating target class
                final ValueType valueType = ValueType.determineValueType(fieldType);
                final Object[] params = { index, fieldType, valueType };
                return (BaseClassFieldReader) newClass.getConstructors()[0].newInstance(params);
            } else {
                // must be a public field
                return null;
            }
        }
    } catch (final RuntimeException e) {
        throw e;
    } catch (final Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ByteArrayClassLoader(org.drools.core.util.ByteArrayClassLoader) Method(java.lang.reflect.Method) IOException(java.io.IOException) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) ClassFieldInspector(org.drools.core.util.asm.ClassFieldInspector)

Example 2 with SelfReferenceClassFieldReader

use of org.drools.core.base.extractors.SelfReferenceClassFieldReader 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 3 with SelfReferenceClassFieldReader

use of org.drools.core.base.extractors.SelfReferenceClassFieldReader in project drools by kiegroup.

the class KiePackagesBuilder method buildAccumulate.

private Accumulate buildAccumulate(RuleContext ctx, AccumulatePattern accPattern, RuleConditionElement source, Pattern pattern, List<String> usedVariableName, Binding binding) {
    AccumulateFunction[] accFunctions = accPattern.getAccumulateFunctions();
    Accumulate accumulate;
    if (accFunctions.length == 1) {
        final Class<?> functionClass = accFunctions[0].getFunctionClass();
        final Accumulator accumulator = createAccumulator(usedVariableName, binding, functionClass);
        final Variable boundVar = accPattern.getBoundVariables()[0];
        final Declaration declaration = new Declaration(boundVar.getName(), getReadAcessor(JAVA_CLASS_OBJECT_TYPE), pattern, true);
        pattern.addDeclaration(declaration);
        Declaration[] bindingDeclaration = binding != null ? new Declaration[0] : new Declaration[] { ctx.getPattern(accFunctions[0].getSource()).getDeclaration() };
        accumulate = new SingleAccumulate(source, bindingDeclaration, accumulator);
    } else {
        InternalReadAccessor reader = new SelfReferenceClassFieldReader(Object[].class);
        Accumulator[] accumulators = new Accumulator[accFunctions.length];
        for (int i = 0; i < accFunctions.length; i++) {
            final Class<?> functionClass = accFunctions[i].getFunctionClass();
            final Accumulator accumulator = createAccumulator(usedVariableName, binding, functionClass);
            Variable boundVar = accPattern.getBoundVariables()[i];
            pattern.addDeclaration(new Declaration(boundVar.getName(), new ArrayElementReader(reader, i, boundVar.getType()), pattern, true));
            accumulators[i] = accumulator;
        }
        accumulate = new MultiAccumulate(source, new Declaration[0], accumulators);
    }
    for (Variable boundVar : accPattern.getBoundVariables()) {
        ctx.addAccumulateSource(boundVar, accumulate);
    }
    return accumulate;
}
Also used : LambdaAccumulator(org.drools.modelcompiler.constraints.LambdaAccumulator) Accumulator(org.drools.core.spi.Accumulator) PrototypeVariable(org.drools.model.PrototypeVariable) Variable(org.drools.model.Variable) MultiAccumulate(org.drools.core.rule.MultiAccumulate) SingleAccumulate(org.drools.core.rule.SingleAccumulate) SingleConstraint(org.drools.model.SingleConstraint) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint) LambdaConstraint(org.drools.modelcompiler.constraints.LambdaConstraint) FlowDSL.entryPoint(org.drools.model.FlowDSL.entryPoint) UnificationConstraint(org.drools.modelcompiler.constraints.UnificationConstraint) EntryPoint(org.drools.model.EntryPoint) Constraint(org.drools.model.Constraint) MultiAccumulate(org.drools.core.rule.MultiAccumulate) SingleAccumulate(org.drools.core.rule.SingleAccumulate) Accumulate(org.drools.core.rule.Accumulate) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) ArrayElementReader(org.drools.core.base.extractors.ArrayElementReader) Declaration(org.drools.core.rule.Declaration) WindowDeclaration(org.drools.core.rule.WindowDeclaration) TypeDeclarationUtil.createTypeDeclaration(org.drools.modelcompiler.util.TypeDeclarationUtil.createTypeDeclaration) TypeDeclaration(org.drools.core.rule.TypeDeclaration) AccumulateFunction(org.drools.model.functions.accumulate.AccumulateFunction)

Example 4 with SelfReferenceClassFieldReader

use of org.drools.core.base.extractors.SelfReferenceClassFieldReader in project drools by kiegroup.

the class QueryElementBuilder method build.

@SuppressWarnings("unchecked")
public RuleConditionElement build(RuleBuildContext context, BaseDescr descr, QueryImpl query) {
    PatternDescr patternDescr = (PatternDescr) descr;
    Declaration[] params = query.getParameters();
    List<BaseDescr> args = (List<BaseDescr>) patternDescr.getDescrs();
    List<Declaration> requiredDeclarations = new ArrayList<Declaration>();
    ObjectType argsObjectType = ClassObjectType.ObjectArray_ObjectType;
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class);
    Pattern pattern = new Pattern(context.getNextPatternId(), 0, argsObjectType, null);
    if (!StringUtils.isEmpty(patternDescr.getIdentifier())) {
        if (query.isAbductive()) {
            Declaration declr = context.getDeclarationResolver().getDeclaration(patternDescr.getIdentifier());
            if (declr != null && !patternDescr.isUnification()) {
                context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Duplicate declaration " + patternDescr.getIdentifier() + ", unable to bind abducted value"));
            }
        } else {
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query binding is not supported by non-abductive queries : " + patternDescr.getIdentifier()));
        }
    }
    boolean addAbductiveReturnArgument = query.isAbductive() && !StringUtils.isEmpty(patternDescr.getIdentifier()) && args.size() < params.length;
    if (addAbductiveReturnArgument) {
        ExprConstraintDescr extraDescr = new ExprConstraintDescr(patternDescr.getIdentifier());
        extraDescr.setPosition(patternDescr.getConstraint().getDescrs().size());
        extraDescr.setType(ExprConstraintDescr.Type.POSITIONAL);
        args.add(extraDescr);
    }
    QueryArgument[] arguments = new QueryArgument[params.length];
    // Deal with the constraints, both positional and bindings
    for (BaseDescr base : args) {
        String expression = null;
        boolean isPositional = false;
        boolean isBinding = false;
        BindingDescr bind = null;
        ConstraintConnectiveDescr result = null;
        if (base instanceof BindingDescr) {
            bind = (BindingDescr) base;
            expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression();
            isBinding = true;
        } else {
            if (base instanceof ExprConstraintDescr) {
                ExprConstraintDescr ecd = (ExprConstraintDescr) base;
                expression = ecd.getExpression();
                isPositional = ecd.getType() == ExprConstraintDescr.Type.POSITIONAL;
            } else {
                expression = base.getText();
            }
            result = parseExpression(context, patternDescr, expression);
            if (result == null) {
                // error, can't parse expression.
                context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Unable to parse constraint: \n" + expression));
                continue;
            }
            isBinding = result.getDescrs().size() == 1 && result.getDescrs().get(0) instanceof BindingDescr;
            if (isBinding) {
                bind = (BindingDescr) result.getDescrs().get(0);
            }
        }
        if ((!isPositional) && (!isBinding)) {
            // error, can't have non binding slots.
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query's must use positional or bindings, not field constraints:\n" + expression));
        } else if (isPositional && isBinding) {
            // error, can't have positional binding slots.
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query's can't use positional bindings:\n" + expression));
        } else if (isPositional) {
            processPositional(context, query, params, arguments, requiredDeclarations, arrayReader, pattern, base, expression, result);
        } else {
            // it is binding
            processBinding(context, descr, params, arguments, requiredDeclarations, arrayReader, pattern, bind);
        }
    }
    List<Integer> varIndexList = new ArrayList<Integer>();
    for (int i = 0; i < arguments.length; i++) {
        if (!(arguments[i] instanceof QueryArgument.Declr)) {
            if (arguments[i] instanceof QueryArgument.Var) {
                varIndexList.add(i);
            }
            continue;
        }
        Class actual = ((QueryArgument.Declr) arguments[i]).getArgumentClass();
        Declaration formalArgument = query.getParameters()[i];
        Class formal = formalArgument.getDeclarationClass();
        // input argument require a broader type, while output types require a narrower type, so we check for both.
        if (!ClassUtils.isTypeCompatibleWithArgumentType(actual, formal) && !ClassUtils.isTypeCompatibleWithArgumentType(formal, actual)) {
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query is being invoked with known argument of type " + actual + " at position " + i + ", but the expected query argument is of type " + formal));
        }
    }
    return new QueryElement(pattern, query.getName(), arguments, toIntArray(varIndexList), requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), !patternDescr.isQuery(), query.isAbductive());
}
Also used : BindingDescr(org.drools.compiler.lang.descr.BindingDescr) QueryArgument(org.drools.core.rule.QueryArgument) PatternDescr(org.drools.compiler.lang.descr.PatternDescr) ArrayList(java.util.ArrayList) QueryElement(org.drools.core.rule.QueryElement) ClassObjectType(org.drools.core.base.ClassObjectType) ObjectType(org.drools.core.spi.ObjectType) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) ArrayList(java.util.ArrayList) List(java.util.List) Declaration(org.drools.core.rule.Declaration) ConstraintConnectiveDescr(org.drools.compiler.lang.descr.ConstraintConnectiveDescr) Pattern(org.drools.core.rule.Pattern) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) BaseDescr(org.drools.compiler.lang.descr.BaseDescr) ExprConstraintDescr(org.drools.compiler.lang.descr.ExprConstraintDescr)

Example 5 with SelfReferenceClassFieldReader

use of org.drools.core.base.extractors.SelfReferenceClassFieldReader in project drools by kiegroup.

the class KiePackagesBuilder method buildQueryPattern.

private RuleConditionElement buildQueryPattern(RuleContext ctx, QueryCallPattern queryPattern) {
    Pattern pattern = new Pattern(ctx.getNextPatternIndex(), 0, ClassObjectType.ObjectArray_ObjectType, null);
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class);
    QueryArgument[] arguments = new QueryArgument[queryPattern.getArguments().length];
    List<Integer> varIndexList = new ArrayList<>();
    List<Declaration> requiredDeclarations = new ArrayList<>();
    for (int i = 0; i < queryPattern.getArguments().length; i++) {
        Argument arg = queryPattern.getArguments()[i];
        if (arg instanceof Variable) {
            Variable var = ((Variable) arg);
            Declaration decl = ctx.getDeclaration(var);
            if (decl != null) {
                requiredDeclarations.add(decl);
                arguments[i] = new QueryArgument.Declr(decl);
            } else {
                ArrayElementReader reader = new ArrayElementReader(arrayReader, i, arg.getType());
                pattern.addDeclaration(var.getName()).setReadAccessor(reader);
                arguments[i] = QueryArgument.VAR;
                varIndexList.add(i);
            }
        } else if (arg instanceof Value) {
            arguments[i] = new QueryArgument.Literal(((Value) arg).getValue());
        } else {
            throw new UnsupportedOperationException();
        }
    }
    return new QueryElement(pattern, queryPattern.getQuery().getName(), arguments, varIndexList.stream().mapToInt(i -> i).toArray(), requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), queryPattern.isOpen(), // TODO: query.isAbductive() );
    false);
}
Also used : QueryCallPattern(org.drools.model.patterns.QueryCallPattern) AccumulatePattern(org.drools.model.AccumulatePattern) Pattern(org.drools.core.rule.Pattern) QueryArgument(org.drools.core.rule.QueryArgument) PrototypeVariable(org.drools.model.PrototypeVariable) Variable(org.drools.model.Variable) QueryArgument(org.drools.core.rule.QueryArgument) Argument(org.drools.model.Argument) ArrayList(java.util.ArrayList) QueryElement(org.drools.core.rule.QueryElement) SingleConstraint(org.drools.model.SingleConstraint) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint) LambdaConstraint(org.drools.modelcompiler.constraints.LambdaConstraint) FlowDSL.entryPoint(org.drools.model.FlowDSL.entryPoint) UnificationConstraint(org.drools.modelcompiler.constraints.UnificationConstraint) EntryPoint(org.drools.model.EntryPoint) Constraint(org.drools.model.Constraint) SalienceInteger(org.drools.core.base.SalienceInteger) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) Value(org.drools.model.Value) ArrayElementReader(org.drools.core.base.extractors.ArrayElementReader) Declaration(org.drools.core.rule.Declaration) WindowDeclaration(org.drools.core.rule.WindowDeclaration) TypeDeclarationUtil.createTypeDeclaration(org.drools.modelcompiler.util.TypeDeclarationUtil.createTypeDeclaration) TypeDeclaration(org.drools.core.rule.TypeDeclaration)

Aggregations

SelfReferenceClassFieldReader (org.drools.core.base.extractors.SelfReferenceClassFieldReader)8 Declaration (org.drools.core.rule.Declaration)6 ArrayElementReader (org.drools.core.base.extractors.ArrayElementReader)5 Pattern (org.drools.core.rule.Pattern)5 InternalReadAccessor (org.drools.core.spi.InternalReadAccessor)5 DescrBuildError (org.drools.compiler.compiler.DescrBuildError)3 Accumulator (org.drools.core.spi.Accumulator)3 Constraint (org.drools.core.spi.Constraint)3 ArrayList (java.util.ArrayList)2 AccumulateFunctionCallDescr (org.drools.compiler.lang.descr.AccumulateDescr.AccumulateFunctionCallDescr)2 ClassObjectType (org.drools.core.base.ClassObjectType)2 MultiAccumulate (org.drools.core.rule.MultiAccumulate)2 MutableTypeConstraint (org.drools.core.rule.MutableTypeConstraint)2 QueryArgument (org.drools.core.rule.QueryArgument)2 QueryElement (org.drools.core.rule.QueryElement)2 SingleAccumulate (org.drools.core.rule.SingleAccumulate)2 TypeDeclaration (org.drools.core.rule.TypeDeclaration)2 WindowDeclaration (org.drools.core.rule.WindowDeclaration)2 MvelConstraint (org.drools.core.rule.constraint.MvelConstraint)2 QueryNameConstraint (org.drools.core.rule.constraint.QueryNameConstraint)2