/* * 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.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import com.revolsys.beans.Classes; import com.revolsys.geometry.model.Geometry; import com.revolsys.geometry.test.testrunner.StringUtil; import junit.framework.Assert; /** * A {@link GeometryFunction} which calls a static * {@link Method}. * * @author Martin Davis * */ public class StaticMethodGeometryFunction extends BaseGeometryFunction { private static final String DESCRIPTION_SUFFIX = "Description"; private static final String FUNCTIONS_SUFFIX = "Functions"; private static final String PARAMETERS_SUFFIX = "Parameters"; public static Object dynamicCall(final String clzName, final String methodName, final Class[] methodParamTypes, final Object[] methodArgs) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { final Class clz = Class.forName(clzName); final Class[] constParTypes = new Class[] { String.class, String.class }; final Constructor constr = clz.getConstructor(new Class[0]); final Object dummyto = constr.newInstance(new Object[0]); final Method meth = clz.getMethod(methodName, methodParamTypes); final Object result = meth.invoke(dummyto, methodArgs); return result; } private static String extractCategory(final String className) { final String trim = StringUtil.removeFromEnd(className, FUNCTIONS_SUFFIX); return trim; } private static String extractDescription(final Method method) { // try to get names from predefined ones first final String paramsName = method.getName() + DESCRIPTION_SUFFIX; return StaticMethodGeometryFunction.getStringClassField(method.getDeclaringClass(), paramsName); } /** * Java doesn't permit accessing the original code parameter names, unfortunately. * * @param method * @return */ private static String[] extractParamNames(final Method method) { // try to get names from predefined ones first final String paramsName = method.getName() + PARAMETERS_SUFFIX; final String[] codeName = StaticMethodGeometryFunction .getStringArrayClassField(method.getDeclaringClass(), paramsName); if (codeName != null) { return codeName; } // Synthesize default names final String[] name = new String[method.getParameterTypes().length - 1]; // Skip first parameter - it is the target geometry for (int i = 1; i < name.length; i++) { name[i] = "arg" + i; } return name; } private static Class[] extractParamTypes(final Method method) { final Class[] methodParamTypes = method.getParameterTypes(); final Class[] types = new Class[methodParamTypes.length - 1]; for (int i = 1; i < methodParamTypes.length; i++) { types[i - 1] = methodParamTypes[i]; } return types; } public static String getClassname(final Class javaClass) { final String jClassName = javaClass.getName(); final int lastDotPos = jClassName.lastIndexOf("."); return jClassName.substring(lastDotPos + 1, jClassName.length()); } public static String[] getStringArrayClassField(final Class clz, final String name) { try { final Field field = clz.getField(name); final String[] str = (String[])field.get(null); return str; } catch (final NoSuchFieldException ex) { } catch (final IllegalAccessException ex) { } return null; } public static String getStringClassField(final Class clz, final String name) { try { final Field field = clz.getField(name); final String str = (String)field.get(null); return str; } catch (final NoSuchFieldException ex) { } catch (final IllegalAccessException ex) { } return null; } private static String invocationErrMsg(final InvocationTargetException ex) { final Throwable targetEx = ex.getTargetException(); final String msg = getClassname(targetEx.getClass()) + ": " + targetEx.getMessage(); return msg; } public static Object invoke(final Method method, final Object target, final Object[] args) { Object result; try { result = method.invoke(target, args); } catch (final InvocationTargetException ex) { final Throwable t = ex.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException)t; } throw new RuntimeException(invocationErrMsg(ex)); } catch (final Exception ex) { System.out.println(ex.getMessage()); throw new RuntimeException(ex.getMessage()); } return result; } /** * Creates an arg array which includes the target geometry as the first argument * * @param g * @param arg * @return */ private static Object[] newFullArgs(final Geometry g, final Object[] arg) { int fullArgLen = 1; if (arg != null) { fullArgLen = arg.length + 1; } final Object[] fullArg = new Object[fullArgLen]; fullArg[0] = g; for (int i = 1; i < fullArgLen; i++) { fullArg[i] = arg[i - 1]; } return fullArg; } public static StaticMethodGeometryFunction newFunction(final Method method) { Assert.assertTrue(Geometry.class.isAssignableFrom(method.getParameterTypes()[0])); final Class clz = method.getDeclaringClass(); final String category = extractCategory(Classes.className(clz)); final String funcName = method.getName(); final String description = extractDescription(method); final String[] paramNames = extractParamNames(method); final Class[] paramTypes = extractParamTypes(method); final Class returnType = method.getReturnType(); return new StaticMethodGeometryFunction(category, funcName, description, paramNames, paramTypes, returnType, method); } private final Method method; public StaticMethodGeometryFunction(final String category, final String name, final String description, final String[] parameterNames, final Class[] parameterTypes, final Class returnType, final Method method) { super(category, name, description, parameterNames, parameterTypes, returnType); this.method = method; } @Override public Object invoke(final Geometry g, final Object[] arg) { return invoke(this.method, null, newFullArgs(g, arg)); } }