Search in sources :

Example 51 with Declaration

use of org.drools.core.rule.Declaration in project drools by kiegroup.

the class RuleContext method getDeclaration.

Declaration getDeclaration(Variable variable) {
    if (variable.isFact()) {
        Declaration declaration = innerDeclaration.get(variable);
        if (declaration == null) {
            declaration = queryDeclaration.get(variable);
        }
        if (declaration == null) {
            Pattern pattern = patterns.get(variable);
            declaration = pattern != null ? pattern.getDeclaration() : null;
        }
        return declaration;
    } else {
        Global global = ((Global) variable);
        ObjectType objectType = builder.getObjectType(global);
        InternalReadAccessor globalExtractor = new GlobalExtractor(global.getName(), objectType);
        return new Declaration(global.getName(), globalExtractor, new Pattern(0, objectType));
    }
}
Also used : Pattern(org.drools.core.rule.Pattern) ObjectType(org.drools.core.spi.ObjectType) GlobalExtractor(org.drools.core.spi.GlobalExtractor) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) Declaration(org.drools.core.rule.Declaration) Global(org.drools.model.Global)

Example 52 with Declaration

use of org.drools.core.rule.Declaration in project drools by kiegroup.

the class QueryElementBuilder method processPositional.

private void processPositional(RuleBuildContext context, QueryImpl query, Declaration[] params, QueryArgument[] arguments, List<Declaration> requiredDeclarations, InternalReadAccessor arrayReader, Pattern pattern, BaseDescr base, String expression, ConstraintConnectiveDescr result) {
    int pos = ((ExprConstraintDescr) base).getPosition();
    if (pos >= arguments.length) {
        context.addError(new DescrBuildError(context.getParentDescr(), base, null, "Unable to parse query '" + query.getName() + "', as postion " + pos + " for expression '" + expression + "' does not exist on query size " + arguments.length));
        return;
    }
    boolean isVariable = isVariable(expression);
    DeclarationScopeResolver declarationResolver = context.getDeclarationResolver();
    Declaration declr = isVariable ? declarationResolver.getDeclaration(expression) : null;
    if (declr != null) {
        // it exists, so it's an input
        requiredDeclarations.add(declr);
        arguments[pos] = new QueryArgument.Declr(declr);
    } else if (isVariable && expression.indexOf('.') < 0) {
        arguments[pos] = getVariableQueryArgument(arrayReader, params, pos, pattern, expression);
    } else {
        // it's an expression and thus an input
        AnalysisResult analysisResult = analyzeExpression(context, base, expression);
        if (analysisResult == null || analysisResult.getIdentifiers().isEmpty()) {
            arguments[pos] = getLiteralQueryArgument(context, base, result);
        } else {
            List<Declaration> declarations = new ArrayList<Declaration>();
            for (String identifier : analysisResult.getIdentifiers()) {
                Declaration declaration = declarationResolver.getDeclaration(identifier);
                if (declaration != null) {
                    declarations.add(declaration);
                }
            }
            if (declarations.size() == analysisResult.getIdentifiers().size()) {
                arguments[pos] = new QueryArgument.Expression(declarations, expression, getParserContext(context));
            } else {
                arguments[pos] = getLiteralQueryArgument(context, base, result);
            }
        }
    }
}
Also used : QueryArgument(org.drools.core.rule.QueryArgument) DeclarationScopeResolver(org.drools.core.spi.DeclarationScopeResolver) AnalysisResult(org.drools.compiler.compiler.AnalysisResult) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) ArrayList(java.util.ArrayList) List(java.util.List) Declaration(org.drools.core.rule.Declaration) ExprConstraintDescr(org.drools.compiler.lang.descr.ExprConstraintDescr)

Example 53 with Declaration

use of org.drools.core.rule.Declaration in project drools by kiegroup.

the class QueryElementBuilder method processBinding.

@SuppressWarnings("unchecked")
private void processBinding(RuleBuildContext context, BaseDescr descr, Declaration[] params, QueryArgument[] arguments, List<Declaration> requiredDeclarations, InternalReadAccessor arrayReader, Pattern pattern, BindingDescr bind) {
    Declaration declr = context.getDeclarationResolver().getDeclaration(bind.getVariable());
    if (declr != null) {
        // check right maps to a slot, otherwise we can't reverse this and should error
        int pos = getPos(bind.getExpression(), params);
        if (pos >= 0) {
            // slot exist, reverse and continue
            String slot = bind.getExpression();
            String var = bind.getVariable();
            bind.setVariable(slot);
            bind.setExpression(var);
        } else {
        // else error, we cannot find the slot to unify against
        }
    }
    // left does not already exist, is it a slot?
    int pos = getPos(bind.getVariable(), params);
    if (pos >= 0) {
        // it's an input on a slot, is the input using bindings?
        declr = context.getDeclarationResolver().getDeclaration(bind.getExpression());
        if (declr != null) {
            requiredDeclarations.add(declr);
            arguments[pos] = new QueryArgument.Declr(declr);
        } else {
            // it must be a literal/expression
            // it's an expression and thus an input
            DrlExprParser parser = new DrlExprParser(context.getConfiguration().getLanguageLevel());
            ConstraintConnectiveDescr bresult = parser.parse(bind.getExpression());
            if (parser.hasErrors()) {
                for (DroolsParserException error : parser.getErrors()) {
                    context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Unable to parser pattern expression:\n" + error.getMessage()));
                }
                return;
            }
            arguments[pos] = getLiteralQueryArgument(context, descr, bresult);
        }
    } else {
        // this is creating a new output binding
        // we know it doesn't exist, as we already checked for left == var
        pos = getPos(bind.getExpression(), params);
        if (pos < 0) {
            // error this must be a binding on a slot
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "named argument does not exist:\n" + bind.getExpression()));
            return;
        }
        arguments[pos] = getVariableQueryArgument(arrayReader, params, pos, pattern, bind.getVariable());
    }
}
Also used : QueryArgument(org.drools.core.rule.QueryArgument) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) Declaration(org.drools.core.rule.Declaration) ConstraintConnectiveDescr(org.drools.compiler.lang.descr.ConstraintConnectiveDescr) DrlExprParser(org.drools.compiler.compiler.DrlExprParser) DroolsParserException(org.drools.compiler.compiler.DroolsParserException)

Example 54 with Declaration

use of org.drools.core.rule.Declaration 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 55 with Declaration

use of org.drools.core.rule.Declaration in project drools by kiegroup.

the class DialectUtil method rewriteDescr.

private static boolean rewriteDescr(final RuleBuildContext context, final String originalCode, final MVELDialect mvel, final StringBuilder consequence, final JavaBlockDescr d, final BoundIdentifiers bindings, final Map<String, Declaration> decls) {
    if (d.getEnd() == 0) {
        // do nothing, it was incorrectly parsed, but this error should be picked up else where
        return false;
    }
    boolean typeSafety = context.isTypesafe();
    // we have to analyse in dynamic mode for now, as we cannot safely determine all input vars
    context.setTypesafe(false);
    Map<String, Class<?>> localTypes = d.getInputs();
    if (d.getInScopeLocalVars() != null && !d.getInScopeLocalVars().isEmpty()) {
        localTypes = new HashMap<String, Class<?>>(d.getInputs() != null ? d.getInputs() : Collections.EMPTY_MAP);
        for (JavaLocalDeclarationDescr local : d.getInScopeLocalVars()) {
            // these are variables declared in the code itself that are in the scope for this expression
            try {
                Class<?> type = context.getDialect("java").getPackageRegistry().getTypeResolver().resolveType(local.getRawType());
                for (IdentifierDescr id : local.getIdentifiers()) {
                    localTypes.put(id.getIdentifier(), type);
                }
            } catch (ClassNotFoundException e) {
                context.addError(new DescrBuildError(context.getRuleDescr(), context.getParentDescr(), null, "Unable to resolve type " + local.getRawType() + ":\n" + e.getMessage()));
            }
        }
    }
    MVELAnalysisResult mvelAnalysis = (MVELAnalysisResult) mvel.analyzeBlock(context, d.getTargetExpression(), bindings, localTypes, "drools", KnowledgeHelper.class);
    context.setTypesafe(typeSafety);
    if (mvelAnalysis == null) {
        // something bad happened, issue already logged in errors
        return false;
    }
    Class ret = mvelAnalysis.getReturnType();
    if (ret == null) {
        // not possible to evaluate expression return value
        context.addError(new DescrBuildError(context.getParentDescr(), context.getRuleDescr(), originalCode, "Unable to determine the resulting type of the expression: " + d.getTargetExpression() + "\n"));
        return false;
    }
    // adding modify expression
    String retString = ClassUtils.canonicalName(ret);
    String declrString;
    if (d.getTargetExpression().charAt(0) == '(') {
        declrString = d.getTargetExpression().substring(1, d.getTargetExpression().length() - 1).trim();
    } else {
        declrString = d.getTargetExpression();
    }
    String obj = declrString;
    Declaration declr = decls.get(declrString);
    consequence.append("{ ");
    if (declr == null) {
        obj = "__obj__";
        consequence.append(retString);
        consequence.append(" ");
        consequence.append(obj);
        consequence.append(" = ");
        consequence.append(d.getTargetExpression());
        consequence.append("; ");
    }
    if (declr == null || declr.isInternalFact()) {
        consequence.append("org.kie.api.runtime.rule.FactHandle ");
        consequence.append(obj);
        consequence.append("__Handle2__ = drools.getFactHandle(");
        consequence.append(obj);
        consequence.append(");");
    }
    // the following is a hack to preserve line breaks.
    String originalBlock = originalCode.substring(d.getStart() - 1, d.getEnd());
    switch(d.getType()) {
        case MODIFY:
            rewriteModifyDescr(context, d, originalBlock, consequence, declr, obj);
            break;
        case UPDATE:
            rewriteUpdateDescr(context, d, consequence, declr, obj);
            break;
        case DELETE:
            rewriteDeleteDescr(context, d, consequence, declr, obj);
            break;
    }
    return declr != null;
}
Also used : DescrBuildError(org.drools.compiler.compiler.DescrBuildError) MVELAnalysisResult(org.drools.compiler.rule.builder.dialect.mvel.MVELAnalysisResult) JavaLocalDeclarationDescr(org.drools.compiler.rule.builder.dialect.java.parser.JavaLocalDeclarationDescr) KnowledgeHelper(org.drools.core.spi.KnowledgeHelper) TypeDeclaration(org.drools.core.rule.TypeDeclaration) Declaration(org.drools.core.rule.Declaration) IdentifierDescr(org.drools.compiler.rule.builder.dialect.java.parser.JavaLocalDeclarationDescr.IdentifierDescr)

Aggregations

Declaration (org.drools.core.rule.Declaration)115 Pattern (org.drools.core.rule.Pattern)42 ClassObjectType (org.drools.core.base.ClassObjectType)29 InternalReadAccessor (org.drools.core.spi.InternalReadAccessor)27 TypeDeclaration (org.drools.core.rule.TypeDeclaration)24 InternalFactHandle (org.drools.core.common.InternalFactHandle)22 ArrayList (java.util.ArrayList)19 HashMap (java.util.HashMap)17 BoundIdentifiers (org.drools.compiler.compiler.BoundIdentifiers)17 DescrBuildError (org.drools.compiler.compiler.DescrBuildError)16 Test (org.junit.Test)16 KnowledgeHelper (org.drools.core.spi.KnowledgeHelper)14 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)12 WorkingMemory (org.drools.core.WorkingMemory)11 MVELCompilationUnit (org.drools.core.base.mvel.MVELCompilationUnit)11 RuleImpl (org.drools.core.definitions.rule.impl.RuleImpl)11 MvelConstraint (org.drools.core.rule.constraint.MvelConstraint)10 Consequence (org.drools.core.spi.Consequence)10 Constraint (org.drools.core.spi.Constraint)10 AnalysisResult (org.drools.compiler.compiler.AnalysisResult)9