public RuleConditionElement build( RuleBuildContext context,
BaseDescr descr,
Pattern prefixPattern ) {
PatternDescr patternDescr = (PatternDescr) descr;
Query query = (Query) context.getPkg().getRule( patternDescr.getObjectType() );
if ( query == null ) {
// we already checked this before, so we know it's either in the package or recursive on itself
query = (Query) context.getRule();
}
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 = new ClassObjectType( Object[].class );
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.getErrors().add( 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.getErrors().add( 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.getErrors().add( 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() );