/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 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.process.function; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.geotools.data.Parameter; import org.geotools.filter.FunctionFactory; import org.geotools.filter.capability.FunctionNameImpl; import org.geotools.process.ProcessFactory; import org.geotools.process.Processors; import org.geotools.process.RenderingProcess; import org.opengis.feature.type.Name; import org.opengis.filter.capability.FunctionName; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Function; import org.opengis.filter.expression.Literal; /** * A bridge between the process world and the filter function world: any process returning a single * value can be seen as a filter function * * @author Andrea Aime - GeoSolutions * * * * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/ProcessFunctionFactory.java $ */ public class ProcessFunctionFactory implements FunctionFactory { /** * Parameter used to indicate a certain output is the primary one for the process */ public static final String PRIMARY_OUTPUT = "PRIMARY"; /** * Compares process factories by their title */ static final Comparator<ProcessFactory> FACTORY_COMPARATOR = new Comparator<ProcessFactory>() { public int compare(ProcessFactory pf1, ProcessFactory pf2) { if (pf1.getTitle() == null) { if (pf2.getTitle() == null) { return 0; } else { return -1; } } else { if (pf2.getTitle() == null) { return 1; } else { return pf1.getTitle().compareTo(pf2.getTitle()); } } } }; /** * Maps from function to process name */ HashMap<String, Name> functionToProcess; /** * The cache list of functions wrapping processes */ private ArrayList<FunctionName> functionNames; public Function function(String name, List<Expression> args, Literal fallback) { // if the param function just return it if(name.equals(ParameterFunction.NAME)) { return new ParameterFunction(fallback, args); } // lookup the process if(functionToProcess == null) { init(); } Name processName = functionToProcess.get(name); if(processName == null) { // no such function return null; } else { // wrap the process org.geotools.process.Process process = Processors.createProcess(processName); Map<String, Parameter<?>> parameters = Processors.getParameterInfo(processName); if (process instanceof RenderingProcess){ return new RenderingProcessFunction(name, processName, args, parameters, (RenderingProcess) process, fallback); } else { return new ProcessFunction(name, processName, args, parameters, process, fallback); } } } public List<FunctionName> getFunctionNames() { if(functionNames == null) { init(); } return functionNames; } private synchronized void init() { if(functionNames == null || functionToProcess == null) { // collect and sort the factories to have a reproducable list of function names List<ProcessFactory> factories = new ArrayList<ProcessFactory>(Processors .getProcessFactories()); Collections.sort(factories, FACTORY_COMPARATOR); // collect name and params of all processes resulting in a single output functionToProcess = new HashMap<String, Name>(); functionNames = new ArrayList<FunctionName>(); for (ProcessFactory factory : factories) { for (Name processName : factory.getNames()) { String functionName = processName.getURI(); Map<String, Parameter<?>> resultInfo = factory.getResultInfo(processName, null); // check there is a single output if(getPrimary(resultInfo) != null) { Map<String, Parameter<?>> parameterInfo = factory.getParameterInfo(processName); List<String> argumentNames = new ArrayList<String>(parameterInfo.keySet()); functionNames.add(new FunctionNameImpl(functionName, argumentNames)); functionToProcess.put(functionName, processName); } } } // add the parameter function functionNames.add(new FunctionNameImpl(ParameterFunction.NAME, -1)); } } private String getPrimary(Map<String, Parameter<?>> resultInfo) { if(resultInfo.size() == 1) { return resultInfo.values().iterator().next().getName(); } else { for (Parameter<?> param : resultInfo.values()) { if(param.isRequired()) { return param.getName(); } } } return null; } /** * Clears the caches forcing the system to do another lookup */ public void clear() { functionNames = null; functionToProcess = null; } }