@SuppressWarnings("unchecked") public RuleConditionElement build( RuleBuildContext context, BaseDescr descr, Pattern prefixPattern, Query query) { PatternDescr patternDescr = (PatternDescr) descr; Declaration[] params = query.getParameters(); List<BaseDescr> args = (List<BaseDescr>) patternDescr.getDescrs(); List<Integer> declrIndexes = new ArrayList<Integer>(); List<Integer> varIndexes = new ArrayList<Integer>(); List<Object> arguments = new ArrayList<Object>(params.length); for (int i = 0; i < params.length; i++) { // as these could be set in any order, initialise first, to allow setting later. arguments.add(null); } List<Declaration> requiredDeclarations = new ArrayList<Declaration>(); ObjectType argsObjectType = ClassObjectType.ObjectArray_ObjectType; InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class, "this"); Pattern pattern = new Pattern(context.getNextPatternId(), 0, argsObjectType, null); // Deal with the constraints, both positional and bindings for (int i = 0, length = args.size(); i < length; i++) { BaseDescr base = args.get(i); 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)); continue; } 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)); continue; } else if (isPositional) { processPositional( context, query, params, declrIndexes, varIndexes, arguments, requiredDeclarations, arrayReader, pattern, base, expression, result); } else { // it is binding processBinding( context, descr, params, declrIndexes, varIndexes, arguments, requiredDeclarations, arrayReader, pattern, bind, result); } } Declaration[] declrsArray = requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]); int[] declrIndexArray = new int[declrIndexes.size()]; for (int i = 0; i < declrsArray.length; i++) { declrIndexArray[i] = declrIndexes.get(i); } int[] varIndexesArray = new int[varIndexes.size()]; for (int i = 0; i < varIndexesArray.length; i++) { varIndexesArray[i] = varIndexes.get(i); } return new QueryElement( pattern, query.getName(), arguments.toArray(new Object[arguments.size()]), declrsArray, declrIndexArray, varIndexesArray, !patternDescr.isQuery()); }
private void processPositional( RuleBuildContext context, Query query, Declaration[] params, List<Integer> declrIndexes, List<Integer> varIndexes, List<Object> arguments, List<Declaration> requiredDeclarations, InternalReadAccessor arrayReader, Pattern pattern, BaseDescr base, String expression, ConstraintConnectiveDescr result) { int position = ((ExprConstraintDescr) base).getPosition(); if (position >= arguments.size()) { context.addError( new DescrBuildError( context.getParentDescr(), base, null, "Unable to parse query '" + query.getName() + "', as postion " + (position - 1) + " for expression '" + expression + "' does not exist on query size " + arguments.size())); return; } if (isVariable(expression)) { // is this already bound? Declaration declr = context.getDeclarationResolver().getDeclaration(query, expression); if (declr != null) { // it exists, so it's an input arguments.set(position, declr); declrIndexes.add(position); requiredDeclarations.add(declr); } else { // it doesn't exist, so it's an output arguments.set(position, Variable.v); varIndexes.add(position); declr = pattern.addDeclaration(expression); // this bit is different, notice its the ArrayElementReader that we wire up to, not the // declaration. ArrayElementReader reader = new ArrayElementReader( arrayReader, position, params[position].getExtractor().getExtractToClass()); declr.setReadAccessor(reader); } } else { // it's an expression and thus an input MVELDumper.MVELDumperContext mvelCtx = new MVELDumper.MVELDumperContext(); String rewrittenExpr = context.getCompilerFactory().getExpressionProcessor().dump(result, mvelCtx); arguments.set(position, MVEL.eval(rewrittenExpr)); // for now we just work with literals } }