package org.finra.datagenerator.scaffolding.utils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.reflect.ConstructorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.Advised; import org.springframework.aop.support.AopUtils; import java.lang.reflect.*; /** * Created by dkopel on 6/28/16. */ public class ClassUtils { private static Logger logger = LoggerFactory.getLogger("ClassUtils"); public static Method getMethod(Class clazz, String method, Class[] params) { try { return clazz.getDeclaredMethod(method, params); } catch (NoSuchMethodException e) { logger.error(e.getMessage()); } return null; } public static Class<?> getTargetClass(Object obj) { if (AopUtils.isAopProxy(obj)) { return AopUtils.getTargetClass(obj); } else { return (obj instanceof Class) ? (Class) obj : obj.getClass(); } } public static <T> T getTargetObject(Object candidate) { try { if (AopUtils.isAopProxy(candidate) && (candidate instanceof Advised)) { return (T) ((Advised) candidate).getTargetSource().getTarget(); } } catch (Exception e) { throw new IllegalStateException("Failed to unwrap proxied object.", e); } // else return (T) candidate; } public static <T> T createNewInstance(Class<T> clazz, Object[] arguments, Class[] classes) throws InstantiationException { try { if(arguments.length == 0) { logger.debug("No arguments provided, creating a default {}", clazz.getName()); return clazz.newInstance(); } else { Object[] output = new Object[arguments.length]; for(int x=0; x<arguments.length; x++) { if(classes[x].isInstance(arguments[x])) { output[x] = arguments[x]; } else if(org.springframework.util.ClassUtils.isPrimitiveOrWrapper(classes[x])) { Class cl = classes[x]; logger.debug("Class {} is a primitive", cl); if(cl.isPrimitive() || org.apache.commons.lang3.ClassUtils.getAllSuperclasses(cl).contains(Number.class)) { logger.debug("Class {} is a number", classes[x]); String val = String.valueOf(arguments[x]); Number num = NumberUtils.createNumber(val); switch(classes[x].getSimpleName()) { case "long": case "Long": output[x] = num.longValue(); break; case "double": case "Double": output[x] = num.doubleValue(); break; case "float": case "Float": output[x] = num.floatValue(); break; case "short": case "Short": output[x] = num.shortValue(); break; case "byte": case "Byte": output[x] = num.byteValue(); break; case "int": case "Integer": output[x] = num.intValue(); break; } } else if(org.springframework.util.ClassUtils.hasConstructor(classes[x], String.class)) { output[x] = classes[x].getConstructor(String.class).newInstance(arguments[x]); } } } logger.debug("{} arguments provided, creating with {} values and {} classes {}", arguments.length, clazz.getName(), output, classes ); return ConstructorUtils.invokeConstructor(clazz, output, classes); } } catch (NoSuchMethodException e) { logger.error("Couldn't find a constructor to invoke"); } catch (IllegalAccessException e) { logger.error("Something went wrong with {}", e.getMessage()); } catch (InvocationTargetException e) { logger.error("Something went wrong with {}", e.getMessage()); } return null; } public static Boolean hasIntendedInterface(Class clazz, Class iface) { return org.apache.commons.lang3.ClassUtils.getAllInterfaces(clazz).contains(iface); } public static Boolean hasIntendedInterface(Object obj, Class iface) { return findImplementsInterface(obj.getClass(), iface) != null; } public static Class findImplementsInterface(Class clazz, Class iface) { // Type parameters for(TypeVariable tt : clazz.getTypeParameters()) { for(Type ttt : tt.getBounds()) { if(ttt instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) ttt; Class ptc = (Class) pt.getRawType(); if(hasIntendedInterface(ptc, iface)) { logger.info("The class {} was a types parameter", ptc.getName()); return ptc; } } } } // Interface if(clazz.getGenericInterfaces().length > 0) { for(Type t : clazz.getGenericInterfaces()) { ParameterizedType pt = (ParameterizedType) t; if(pt.getActualTypeArguments().length > 0) { for(Type tt : pt.getActualTypeArguments()) { TypeVariable tv = (TypeVariable) tt; if(tv.getBounds().length > 0) { for(Type ttt : tv.getBounds()) { Class cb = (Class) ttt; if(hasIntendedInterface(cb, iface)) { logger.info("The class {} was found in a generic", cb.getName()); return cb; } } } } } } } return null; } }