package org.modeldriven.fuml.common.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ReflectionUtils { private static Log log = LogFactory.getLog(ReflectionUtils.class); public static Method findMethod(Class<?> target, String name, Class<?> arg) throws NoSuchMethodException { return findMethod(target.getMethods(), name, arg); } public static Method getMethod(Class<?> target, String name, Class<?> arg) throws NoSuchMethodException { Method method = findMethod(target.getMethods(), name, arg); if (method == null) throw new NoSuchMethodException(target.getName() + "." + name); return method; } public static Method findMethod(Method[] methods, String name, Class<?> arg) { for (int i = 0; i < methods.length; i++) { if (!methods[i].getName().equals(name)) continue; Class<?>[] types = methods[i].getParameterTypes(); if (types != null && types.length == 1) { if (types[0].isAssignableFrom(arg)) { return methods[i]; } else if (types[0].isPrimitive() || arg.isPrimitive()) { // accommodate conditions where code generators use either primitive type // wrapper classes or primitive types themselves // rather than their respective wrapper classes in the generated code. // This may be for efficiency or other reasons. Yet the source UML model uses UML // primitive types which are [Integer,String,Boolean,...] and don't of course // specify any notion of wrapper classes or otherwise. Code generators // should therefore be allowed to interpret the UML types as they wish. When // determining a method signature isAssignableFrom above will fail when comparing // primitive type classes and their respective wrapper, so below these are // manually compared. if ((Integer.class.equals(types[0]) && int.class.equals(arg)) || (int.class.equals(types[0]) && Integer.class.equals(arg))) { return methods[i]; } else if ((Boolean.class.equals(types[0]) && boolean.class.equals(arg)) || (boolean.class.equals(types[0]) && Boolean.class.equals(arg))) { return methods[i]; } } } } return null; } public static Object instanceForName(String qualifiedName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Object[] args = new Object[0]; Class<?>[] types = new Class<?>[0]; return instanceForName(qualifiedName, args, types); } public static Object instanceForName(String qualifiedName, Object[] args, Class<?>[] types) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Class<?> targetClass = Class.forName(qualifiedName); int mods = targetClass.getModifiers(); if (Modifier.isAbstract(mods)) throw new RuntimeException("attempt to instantiate abstract class, " + qualifiedName); if (!Modifier.isPublic(mods)) throw new RuntimeException("attempt to instantiate non-public class, " + qualifiedName); Constructor<?> defaultConstructor = targetClass.getConstructor(types); Object object = defaultConstructor.newInstance(args); return object; } public static Object invokePublicGetterOrField(Object target, String propertyName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); Object[] args = { }; try { Method getter = target.getClass().getMethod(methodName, new Class[] { }); return getter.invoke(target, args); } catch (NoSuchMethodException e) { try { Field field = target.getClass().getField(propertyName); field.get(target); } catch (NoSuchFieldException e2) { String msg = "no (" + target.getClass().getName() + ") getter method named '" + methodName + "' or public field found for primitive feature " + target.getClass().getName() + "." + propertyName; log.warn(msg); } } return null; } public static void invokePublicSetterOrField(Object target, String propertyName, Class<?> javaType, Object value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); Object[] args = { value }; try { Method setter = target.getClass().getMethod(methodName, new Class[] { javaType }); setter.invoke(target, args); } catch (NoSuchMethodException e) { try { Field field = target.getClass().getField(propertyName); field.set(target, value); } catch (NoSuchFieldException e2) { String msg = "no (" + target.getClass().getName() + ") setter method named '"+methodName+"' or public field found for primitive feature " + "<" + javaType.getName() + "> " + target.getClass().getName() + "." + propertyName; log.warn(msg); } } } }