package org.geotools.filter.expression;
import java.util.ArrayList;
import java.util.List;
import org.geotools.Builder;
import org.geotools.factory.CommonFactoryFinder;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;
public class FunctionBuilder implements Builder<Function> {
class ParamBuilder extends ChildExpressionBuilder<FunctionBuilder>{
int index;
ParamBuilder( int index ){
super( FunctionBuilder.this, index < args.size()? args.get(index) : null );
this.index = index;
}
public Expression build() {
return put( index, super.build() );
}
public ParamBuilder param(){
build();
return new ParamBuilder( index+1 );
}
}
protected FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
LiteralBuilder literal = new LiteralBuilder();
boolean unset = false;
private String name = null; // ie unset!
List<Expression> args = new ArrayList<Expression>();
public FunctionBuilder(){
reset();
}
public FunctionBuilder(Function origional) {
reset( origional );
}
Expression put(int index, Expression expr) {
if( index < args.size() ){
args.set(index, expr);
}
else if( index == args.size() ){
args.add( expr );
}
else {
// fine we will just add to the end?
while( args.size()<index){
args.add(null); // placeholders so we can add at the correct index
}
args.add( expr ); // add at the correct index
}
return expr;
}
public ParamBuilder param(){
return param( args.size() );
}
public FunctionBuilder literal( Object literal ){
put( args.size(), ff.literal( literal ));
return this;
}
public FunctionBuilder property( String xpath ){
put( args.size(), ff.property( xpath ));
return this;
}
public ParamBuilder param(int index){
return new ParamBuilder( index );
}
public FunctionBuilder name( String function ){
this.name = function;
return this;
}
/** Inline fallback value to use if named function is not implemented */
public FunctionBuilder fallback( Object obj ){
literal.value( obj );
return this;
}
/** Literal fallback value to use if named function is not implemented */
public LiteralBuilder fallback(){
return literal;
}
public Function build() {
if( name == null ){
return null; // unset!
}
Expression[] arguments = new Expression[ args.size() ];
for( int index = 0; index < args.size(); index++){
arguments[index] = args.get( index );
}
return ff.function(name, arguments);
}
public FunctionBuilder reset() {
name = null;
args.clear();
literal.unset();
return this;
}
public FunctionBuilder reset(Function original) {
name = original.getName();
args.clear();
args.addAll( original.getParameters() );
literal.reset( original.getFallbackValue() );
return this;
}
public FunctionBuilder unset() {
name = null;
args.clear();
literal.unset();
return this;
}
}