1 /** 2 * 3 */ 4 package ar.com.jiji.kaya.reflect; 5 6 import java.lang.reflect.Constructor; 7 import java.lang.reflect.InvocationTargetException; 8 import java.lang.reflect.Method; 9 import java.util.ArrayList; 10 import java.util.List; 11 import java.util.Map; 12 import java.util.regex.Matcher; 13 import java.util.regex.Pattern; 14 15 import org.apache.commons.beanutils.BeanUtils; 16 17 import ar.com.jiji.kaya.utils.ValidateUtils; 18 19 /** 20 * @author lparra 21 * @version $Revision$ $Date$ 22 */ 23 public class ReflectionService { 24 25 private ReflectionService() { 26 } 27 28 public static Object newInstance(Class clazz) throws ReflectionException { 29 return newInstance(clazz, (Class[]) null, null); 30 } 31 32 public static Object newInstance(Class clazz, Class argType, Object arg) 33 throws ReflectionException { 34 return newInstance(clazz, new Class[] { argType }, new Object[] { arg }); 35 } 36 37 @SuppressWarnings("unchecked") 38 public static Object newInstance(Class clazz, Class[] argTypes, 39 Object[] args) throws ReflectionException { 40 try { 41 Object result; 42 if (argTypes == null || argTypes.length == 0) 43 result = clazz.newInstance(); 44 else { 45 Constructor c = clazz.getConstructor(argTypes); 46 result = c.newInstance(args); 47 } 48 return result; 49 } catch (InstantiationException e) { 50 throw new ReflectionException(e); 51 } catch (IllegalAccessException e) { 52 throw new ReflectionException(e); 53 } catch (SecurityException e) { 54 throw new ReflectionException(e); 55 } catch (NoSuchMethodException e) { 56 throw new ReflectionException(e); 57 } catch (IllegalArgumentException e) { 58 throw new ReflectionException(e); 59 } catch (InvocationTargetException e) { 60 throw new ReflectionException(e); 61 } 62 } 63 64 public static Object invoke(String methodName, Object obj) 65 throws ReflectionException { 66 return invoke(methodName, (Class) null, obj, null); 67 } 68 69 public static Object invoke(String methodName, Class argClass, Object obj, 70 Object arg) throws ReflectionException { 71 Class[] argsClasses = (argClass == null ? (Class[]) null 72 : new Class[] { argClass }); 73 Object[] args = (arg == null ? (Object[]) null : new Object[] { arg }); 74 return invoke(methodName, argsClasses, obj, args); 75 } 76 77 private static Method getMethod(Object obj, String methodName, 78 Class[] argsClasses) throws ReflectionException { 79 ValidateUtils.notNull(obj); 80 ValidateUtils.notNull(methodName); 81 82 try { 83 return obj.getClass().getMethod(methodName, argsClasses); 84 } catch (SecurityException e) { 85 throw new ReflectionException(e); 86 } catch (NoSuchMethodException e) { 87 throw new ReflectionException(e); 88 } 89 } 90 91 public static Object invoke(String methodName, Class[] argsClasses, 92 Object obj, Object[] args) throws ReflectionException { 93 ValidateUtils.notNull(obj); 94 ValidateUtils.notNull(methodName); 95 96 try { 97 final Method m = getMethod(obj, methodName, argsClasses); 98 return m.invoke(obj, args); 99 } catch (SecurityException e) { 100 throw new ReflectionException(e); 101 } catch (IllegalArgumentException e) { 102 throw new ReflectionException(e); 103 } catch (IllegalAccessException e) { 104 throw new ReflectionException(e); 105 } catch (InvocationTargetException e) { 106 throw new ReflectionException(e); 107 } 108 } 109 110 public static Object invoke(String methodName, Class argClass, Object obj, 111 Object arg, Class returningType) throws ReflectionException { 112 Class[] argsClasses = (argClass == null ? (Class[]) null 113 : new Class[] { argClass }); 114 Object[] args = (arg == null ? (Object[]) null : new Object[] { arg }); 115 return invoke(methodName, argsClasses, obj, args, returningType); 116 } 117 118 public static Object invoke(String methodName, Class[] argsClasses, 119 Object obj, Object[] args, Class returningType) 120 throws ReflectionException { 121 try { 122 final Method m = getMethod(obj, methodName, argsClasses); 123 final Object result = m.invoke(obj, args); 124 if (result != null && !returningType.isInstance(result)) 125 throw new ReflectionException(obj.getClass() + "." + methodName 126 + " no devuelve " + returningType); 127 return result; 128 } catch (IllegalArgumentException e) { 129 throw new ReflectionException(e); 130 } catch (IllegalAccessException e) { 131 throw new ReflectionException(e); 132 } catch (InvocationTargetException e) { 133 throw new ReflectionException(e); 134 } 135 } 136 137 /** 138 * Devuelve el valor de un property de un objeto. 139 * 140 * @param obj 141 * No puede ser null 142 * @param property 143 * No puede ser null 144 * @return 145 */ 146 public static Object getProperty(Object obj, String property) { 147 return ReflectionService.invoke(MethodNames.getAccessor(property), obj); 148 } 149 150 /** 151 * Obtiene el valor de un property y lo convierte a String antes de 152 * devolverlo. 153 * 154 * @param obj 155 * No puede ser null 156 * @param property 157 * No puede ser null 158 * @return 159 * @see #getProperty(Object, String) 160 */ 161 public static String getPropertyAsString(Object obj, String property) { 162 Object o = getProperty(obj, property); 163 164 String result = null; 165 if (o != null) 166 result = o.toString(); 167 return result; 168 } 169 170 /** 171 * Devuelve el id del objeto. Supone que el objeto tiene una propiedad 172 * llamada <code>id<code> que es un numero entero (Short, Byte, Integer, 173 * Long). TODO: revisar con primitivos que pasa. 174 * 175 * @param obj No puede ser null 176 * @return 177 * @see #getProperty(Object, String) 178 */ 179 public static Long getObjectId(Object obj) { 180 Long result = null; 181 182 Object aux = ReflectionService.getProperty(obj, "id"); 183 if (aux != null) { 184 if (!((aux instanceof Short) || (aux instanceof Byte) 185 || (aux instanceof Integer) || (aux instanceof Long))) 186 throw new ReflectionException("La propiedad id es " 187 + aux.getClass() + " y se esperaba algun numero entero" 188 + "(short, byte, int, long) o su wrapper"); 189 result = ((Number) aux).longValue(); 190 } 191 192 return result; 193 } 194 195 /** 196 * Dado un objeto devuelve los nombres de los metodos que devuelven algun 197 * objeto de tipo dao. Se asume que los metodos que devuelven los dao siguen 198 * la convencion <code>getXDao</code> siendo <code>X</code> alguna 199 * cadena no vacia. 200 * 201 * @param obj 202 * El objeto a examinar, no puede ser null. 203 * @return 204 */ 205 public static List<String> getDaoAccessors(Object obj) { 206 ValidateUtils.notNull(obj); 207 208 List<String> accessors = new ArrayList<String>(); 209 210 Method[] facadem = obj.getClass().getMethods(); 211 for (Method fm : facadem) 212 if (MethodNames.isAccessor(fm) && fm.getName().endsWith("Dao")) 213 accessors.add(fm.getName()); 214 215 return accessors; 216 } 217 218 /** 219 * Dado un objeto devuelve los nombres de los properties que devuelven algun 220 * objeto de tipo facade. Se asume que los metodos que devuelven los facade 221 * siguen la convencion <code>getXFacade</code> siendo <code>X</code> 222 * alguna cadena no vacia. 223 * 224 * @param obj 225 * El objeto a examinar, no puede ser null. 226 * @return 227 */ 228 @SuppressWarnings("unchecked") 229 public static List<String> getFacadeAccessors(Object obj) { 230 ValidateUtils.notNull(obj); 231 232 List<String> accessors = new ArrayList<String>(); 233 234 Map<String, Object> servicem; 235 try { 236 servicem = BeanUtils.describe(obj); 237 } catch (IllegalAccessException e) { 238 throw new ReflectionException(e); 239 } catch (InvocationTargetException e) { 240 throw new ReflectionException(e); 241 } catch (NoSuchMethodException e) { 242 throw new ReflectionException(e); 243 } 244 for (String sk : servicem.keySet()) 245 if (sk.endsWith("Facade")) 246 accessors.add(sk); 247 248 return accessors; 249 } 250 251 /** 252 * 253 * @param re 254 * @param obj 255 * @return 256 * @see #getMethods(String, Class, Class) 257 */ 258 public static Method[] getMethods(String re, Object obj) { 259 return getMethods(re, obj, null); 260 } 261 262 /** 263 * Devuelve todos los metodos cuyo nombre matcheen con la expresion regular 264 * que se pasa de argumento. 265 * 266 * @param re 267 * @param obj 268 * El objeto a inspeccionar. 269 * @param returnType 270 * El tipo que devuelve, null si no se desea realizar chequeo 271 * sobre el tipo devuelto. 272 * @return Nunca es null. 273 */ 274 public static Method[] getMethods(String re, Object obj, Class returnType) { 275 ValidateUtils.notNull(re); 276 277 List<Method> aux = new ArrayList<Method>(); 278 279 Pattern p = Pattern.compile(re); 280 for (Method m : obj.getClass().getDeclaredMethods()) { 281 Matcher matcher = p.matcher(m.getName()); 282 if (matcher.matches()) { 283 if (returnType != null && m.getReturnType().equals(returnType)) 284 aux.add(m); 285 } 286 } 287 288 return aux.toArray(new Method[] {}); 289 } 290 }