public RuleConditionElement build()

in drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java [79:231]


    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<>();

        ObjectType argsObjectType = ClassObjectType.ObjectArray_ObjectType;
        ReadAccessor arrayReader = new SelfReferenceClassFieldReader( Object[].class );
        Pattern pattern = new Pattern( context.getNextPatternId(),
                                       0, // tupleIndex is 0 by default
                                       0, // patternIndex is 0 by default
                                       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<>();
        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();

            // with queries invoking each other, we won't know until runtime whether a declaration is input, output or else
            // 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() );
    }