/*
* The JTS Topology Suite is a collection of Java classes that
* implement the fundamental operations required to validate a given
* geo-spatial data set to a known topological specification.
*
* Copyright (C) 2001 Vivid Solutions
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.revolsys.geometry.test.function;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import com.revolsys.geometry.model.Geometry;
/**
* A registry to manage a collection of {@link GeometryFunction}s.
*
* @author Martin Davis
*
*/
public class GeometryFunctionRegistry {
public static boolean hasGeometryResult(final GeometryFunction func) {
return Geometry.class.isAssignableFrom(func.getReturnType());
}
public static GeometryFunctionRegistry newTestBuilderRegistry() {
final GeometryFunctionRegistry funcRegistry = new GeometryFunctionRegistry();
funcRegistry.add(GeometryFunctions.class);
funcRegistry.add(BufferFunctions.class);
funcRegistry.add(BufferByUnionFunctions.class);
funcRegistry.add(ConstructionFunctions.class);
funcRegistry.add(LinearReferencingFunctions.class);
funcRegistry.add(LineHandlingFunctions.class);
funcRegistry.add(NodingFunctions.class);
funcRegistry.add(PolygonizeFunctions.class);
funcRegistry.add(PolygonOverlayFunctions.class);
funcRegistry.add(PrecisionFunctions.class);
funcRegistry.add(PreparedGeometryFunctions.class);
funcRegistry.add(SelectionFunctions.class);
funcRegistry.add(SimplificationFunctions.class);
funcRegistry.add(AffineTransformationFunctions.class);
funcRegistry.add(DissolveFunctions.class);
funcRegistry.add(DistanceFunctions.class);
funcRegistry.add(CreateFractalShapeFunctions.class);
funcRegistry.add(CreateRandomShapeFunctions.class);
funcRegistry.add(JTSFunctions.class);
funcRegistry.add(CGAlgorithmFunctions.class);
funcRegistry.add(OverlayFunctions.class);
funcRegistry.add(OverlayNoSnapFunctions.class);
funcRegistry.add(SnappingFunctions.class);
funcRegistry.add(SortingFunctions.class);
funcRegistry.add(TriangulationFunctions.class);
funcRegistry.add(TriangleFunctions.class);
funcRegistry.add(ValidationFunctions.class);
return funcRegistry;
}
private final DoubleKeyMap categorizedFunctions = new DoubleKeyMap();
private final DoubleKeyMap categorizedGeometryFunctions = new DoubleKeyMap();
private final List functions = new ArrayList();
private final Map sortedFunctions = new TreeMap();
public GeometryFunctionRegistry() {
}
public GeometryFunctionRegistry(final Class clz) {
add(clz);
}
/**
* Adds functions for all the static methods in the given class.
*
* @param geomFuncClass
*/
public void add(final Class geomFuncClass) {
final List funcs = newFunctions(geomFuncClass);
// sort list of functions so they appear nicely in the UI list
Collections.sort(funcs);
add(funcs);
}
public void add(final Collection funcs) {
for (final Iterator i = funcs.iterator(); i.hasNext();) {
final GeometryFunction f = (GeometryFunction)i.next();
add(f);
}
}
/**
* Adds a function if it does not currently
* exist in the registry, or replaces the existing one
* with the same signature.
*
* @param func a function
*/
public void add(final GeometryFunction func) {
this.functions.add(func);
this.sortedFunctions.put(func.getName(), func);
this.categorizedFunctions.put(func.getCategory(), func.getName(), func);
if (hasGeometryResult(func)) {
this.categorizedGeometryFunctions.put(func.getCategory(), func.getName(), func);
}
}
/**
* Adds functions for all the static methods in the given class.
*
* @param geomFuncClassname the name of the class to load and extract functions from
*/
public void add(final String geomFuncClassname) throws ClassNotFoundException {
Class geomFuncClass = null;
geomFuncClass = this.getClass().getClassLoader().loadClass(geomFuncClassname);
add(geomFuncClass);
}
/**
* Finds the first function which matches the given name.
*
* @param name
* @return a matching function, or null
*/
public GeometryFunction find(final String name) {
for (final Iterator i = this.functions.iterator(); i.hasNext();) {
final GeometryFunction func = (GeometryFunction)i.next();
final String funcName = func.getName();
if (funcName.equalsIgnoreCase(name)) {
return func;
}
}
return null;
}
/**
* Finds the first function which matches the given signature.
*
* @param name
* @param paramTypes
* @return a matching function, or null
*/
public GeometryFunction find(final String name, final Class[] paramTypes) {
return null;
}
/**
* Finds the first function which matches the given name and argument count.
*
* @param name
* @return a matching function, or null
*/
public GeometryFunction find(final String name, final int argCount) {
for (final Iterator i = this.functions.iterator(); i.hasNext();) {
final GeometryFunction func = (GeometryFunction)i.next();
final String funcName = func.getName();
if (funcName.equalsIgnoreCase(name) && func.getParameterTypes().length == argCount) {
return func;
}
}
return null;
}
public Collection getCategories() {
return this.categorizedFunctions.keySet();
}
public DoubleKeyMap getCategorizedGeometryFunctions() {
return this.categorizedGeometryFunctions;
}
public List getFunctions() {
return this.functions;
}
public Collection getFunctions(final String category) {
return this.categorizedFunctions.values(category);
}
/*
* int index = functions.indexOf(func); if (index == -1) { sortedFunctions.put(func.getName(),
* func); } else { functions.set(index, func); } }
*/
public List getGeometryFunctions() {
final List funList = new ArrayList();
for (final Iterator i = this.sortedFunctions.values().iterator(); i.hasNext();) {
final GeometryFunction fun = (GeometryFunction)i.next();
if (hasGeometryResult(fun)) {
funList.add(fun);
}
}
return funList;
}
public List getScalarFunctions() {
final List scalarFun = new ArrayList();
for (final Iterator i = this.sortedFunctions.values().iterator(); i.hasNext();) {
final GeometryFunction fun = (GeometryFunction)i.next();
if (!hasGeometryResult(fun)) {
scalarFun.add(fun);
}
}
return scalarFun;
}
/**
* Create {@link GeometryFunction}s for all the static
* methods in the given class
*
* @param functionClass
* @return a list of the functions created
*/
public List newFunctions(final Class functionClass) {
final List funcs = new ArrayList();
final Method[] method = functionClass.getMethods();
for (final Method element : method) {
final int mod = element.getModifiers();
if (Modifier.isStatic(mod) && Modifier.isPublic(mod)) {
funcs.add(StaticMethodGeometryFunction.newFunction(element));
}
}
return funcs;
}
}