/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2010, 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. * * reated on October 27, 2004, 11:27 AM */ package org.geotools.filter.function; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.FunctionExpression; import org.geotools.filter.FunctionFactory; import org.geotools.filter.FunctionImpl; import org.geotools.util.logging.Logging; import org.opengis.filter.FilterFactory; import org.opengis.filter.capability.FunctionName; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Function; import org.opengis.filter.expression.Literal; /** * Filter function facotry that uses the spi lookup mechanism to create functions. * * @author Justin Deoliveira, OpenGeo * * * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/build/maven/javadoc/../../../modules/library/main/src/main/java/org/geotools/filter/function/DefaultFunctionFactory.java $ */ public class DefaultFunctionFactory implements FunctionFactory { private static final Logger LOGGER = Logging.getLogger("org.geotools.filter"); private FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory(null); private Map<String,FunctionDescriptor> functionCache; public List<FunctionName> getFunctionNames() { ArrayList list = new ArrayList(functionCache().size()); for (FunctionDescriptor fd : functionCache().values()) { list.add(fd.name); } return list; } public Function function(String name, List<Expression> parameters, Literal fallback) { // cache lookup FunctionDescriptor fd = functionCache().get(functionName(name)); if (fd == null) { //no such function return null; } try { return fd.newFunction(parameters, fallback); } catch(Exception e){ LOGGER.log( Level.FINER, "Unable to create function " + name + "Function", e); //just continue on to return null } return null; } private Map<String,FunctionDescriptor> functionCache() { if (functionCache == null) { synchronized(this) { if (functionCache == null) { loadFunctions(); } } } return functionCache; } private void loadFunctions() { functionCache = new HashMap(); // Get all the GeoTools FunctionExpression implementations // and store in functionExpressionCache // (these are implementations of the legacy GeoTools FunctionExpression // interface) Set functions = CommonFactoryFinder.getFunctionExpressions(null); for (Iterator it = functions.iterator(); it.hasNext();) { FunctionExpression function = (FunctionExpression) it.next(); FunctionDescriptor fd = new FunctionDescriptor( filterFactory.functionName(function.getName(), function.getArgCount()), function.getClass()); functionCache.put(functionName(function.getName()), fd); } // Get all the GeoAPI Function implementations functions = CommonFactoryFinder.getFunctions(null); for (Iterator i = functions.iterator(); i.hasNext();) { Function function = (Function) i.next(); int argc = function instanceof FunctionExpression ? ((FunctionExpression)function).getArgCount() : function.getParameters().size(); FunctionDescriptor fd = new FunctionDescriptor( filterFactory.functionName(function.getName(), argc), function.getClass()); functionCache.put(functionName(function.getName()), fd); } } private String functionName(String name) { //strip off "Function" prefix int index = -1; if ((index = name.indexOf("Function")) != -1) { name = name.substring(0, index); } //convert to lower case name = name.toLowerCase().trim(); //JD: not sure why the first character is converted back to upper case, disabling this and // just keeping everything lower case, as this is only used internally to store functions // it should affect any existing clients //char c = name.charAt(0); //name = name.replaceFirst("" + c, "" + Character.toUpperCase(c)); return name; } static class FunctionDescriptor { FunctionName name; Class clazz; FunctionDescriptor(FunctionName name, Class clazz) { this.name = name; this.clazz = clazz; } Function newFunction(List<Expression> parameters, Literal fallback) throws Exception { // cache lookup if (FunctionExpression.class.isAssignableFrom(clazz)) { FunctionExpression function = (FunctionExpression) clazz.newInstance(); if(parameters != null) { function.setParameters(parameters); } if( fallback != null && function instanceof ClassificationFunction){ ClassificationFunction classification = (ClassificationFunction) function; classification.setFallbackValue( fallback ); } return function; } if(FunctionImpl.class.isAssignableFrom(clazz)) { FunctionImpl function = (FunctionImpl) clazz.newInstance(); if(parameters != null){ function.setParameters( (List) parameters ); } if(fallback != null) function.setFallbackValue( fallback ); return function; } //Function function = (Function) functionClass.newInstance(); Constructor<Function> constructor = clazz.getConstructor( new Class[]{ List.class, Literal.class} ); return constructor.newInstance( parameters, fallback ); } } }