View Javadoc

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 }