/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.filter; import java.awt.RenderingHints.Key; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import org.geotools.feature.NameImpl; import org.geotools.filter.capability.FunctionNameImpl; import org.opengis.feature.type.Name; import org.opengis.filter.capability.FunctionName; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.ExpressionVisitor; import org.opengis.filter.expression.Literal; /** * Abstract class for a function expression implementation * <p> * By default this implementation returns the provided {@link #fallback} value. To implement * a function please override the {@link #evaluate(Object)} method. * * @author James Macgill, PSU * * @source $URL$ */ public abstract class FunctionExpressionImpl extends org.geotools.filter.DefaultExpression implements FunctionExpression { /** function name **/ protected String name; /** function params **/ protected List<org.opengis.filter.expression.Expression> params; protected Literal fallback; /** FunctionName provided by subclass; or lazely created */ protected FunctionName functionName; /** * Preferred constructor to ensure name and functionName match. * <p> * Recommended use:<pre> * import static org.geotools.filter.capability.FunctionNameImpl.*; * public class AreaFunction extends FunctionExpressionImpl { * * public static FunctionName NAME = new FunctionNameImpl("Area", * parameter("area",Double.class), * parameter("geometry",Geometry.class)); * * public AreaFunction() { * super(NAME); * } * </pre> * * @param functionName FunctionName describing subclass */ protected FunctionExpressionImpl(FunctionName functionName){ this( functionName.getName(), null ); this.functionName = functionName; } protected FunctionExpressionImpl(String name ){ this(new NameImpl(name)); } protected FunctionExpressionImpl(Name name){ this( name, null ); } /** * Creates a new instance of FunctionExpression */ protected FunctionExpressionImpl(String name, Literal fallback) { this(new NameImpl(name), fallback); } /** * Creates a new instance of FunctionExpression */ protected FunctionExpressionImpl(Name name, Literal fallback) { this.functionName = new FunctionNameImpl(name, (Class<?>) null); this.name = name.getLocalPart(); this.fallback = fallback; params = new ArrayList<org.opengis.filter.expression.Expression>(); } /** * Gets the name of this function. * * @return the name of the function. * */ public String getName() { return name; } public synchronized FunctionName getFunctionName() { if( functionName == null ){ functionName = new FunctionNameImpl( getName(), functionName.getArgumentCount() ); } return functionName; } public Literal getFallbackValue() { return fallback; } public void setFallbackValue(Literal fallback) { this.fallback = fallback; } /** * Returns the function parameters. */ public List<org.opengis.filter.expression.Expression> getParameters() { return params; } /** * Sets the function parameters. */ public void setParameters(List<Expression> params) { if(params == null){ throw new NullPointerException("Function parameters required"); } final int argCount = functionName.getArgumentCount(); final int paramsSize = params.size(); if(argCount > 0 && argCount != paramsSize){ throw new IllegalArgumentException("Function "+name+" expected " + argCount + " arguments, got " + paramsSize); } this.params = new ArrayList<Expression>(params); } /** * @see org.opengis.filter.expression.Expression#accept(ExpressionVisitor, Object) */ public Object accept(ExpressionVisitor visitor, Object extraData) { return visitor.visit(this, extraData); } /** * Returns the implementation hints. The default implementation returns an empty map. */ public Map<Key, ?> getImplementationHints() { return Collections.emptyMap(); } /** * Convenience method for creating a function name. * @see FunctionImpl#functionName(String, String, String...) */ protected static FunctionName functionName(String name, String ret, String... args) { return FunctionImpl.functionName(name, ret, args); } /** * Creates a String representation of this Function with * the function name and the arguments. The String created * should be good for most subclasses */ public String toString(){ StringBuffer sb = new StringBuffer(); sb.append(getName()); sb.append("("); List<org.opengis.filter.expression.Expression> params = getParameters(); if(params != null){ org.opengis.filter.expression.Expression exp; for(Iterator<org.opengis.filter.expression.Expression> it = params.iterator(); it.hasNext();){ exp = it.next(); sb.append("["); sb.append(exp); sb.append("]"); if(it.hasNext()){ sb.append(", "); } } } sb.append(")"); return sb.toString(); } /** * Utility method for subclasses to ask for an argument at a given index * * @param index * @return */ protected org.opengis.filter.expression.Expression getExpression(int index){ org.opengis.filter.expression.Expression exp; exp = getParameters().get(index); return exp; } @Override public Object evaluate(Object object) { if( fallback != null ){ return fallback.evaluate( object ); } throw new UnsupportedOperationException( "Function "+name+" not implemented"); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((fallback == null) ? 0 : fallback.hashCode()); result = prime * result + ((functionName == null) ? 0 : functionName.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((params == null) ? 0 : params.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; FunctionExpressionImpl other = (FunctionExpressionImpl) obj; if (fallback == null) { if (other.fallback != null) return false; } else if (!fallback.equals(other.fallback)) return false; if (functionName == null) { if (other.functionName != null) return false; } else if (!functionName.equals(other.functionName)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (params == null) { if (other.params != null) return false; } else if (!params.equals(other.params)) return false; return true; } }