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 }