Last active
August 29, 2015 14:08
-
-
Save garcia-jj/07a0258dbde3f5b98e95 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package br.com.otavio.vraptor.custom; | |
import static java.lang.Character.toUpperCase; | |
import static java.util.Arrays.asList; | |
import java.lang.reflect.AccessibleObject; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
/** | |
* Default implementation for {@link ReflectionProvider} that uses pure Java Reflection API. | |
* | |
* @author Otávio S Garcia | |
*/ | |
public class JdkReflectionProvider implements ReflectionProvider { | |
private static final List<String> GETTER_PREFIX_LIST = asList("is", "get"); | |
@Override | |
public List<Method> getMethodsFor(Class<?> clazz) { | |
checkNotNull(clazz, "Input class can't be null"); | |
List<Method> out = new ArrayList<Method>(); | |
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) { | |
for (Method method : current.getDeclaredMethods()) { | |
makeAcessible(method); | |
out.add(method); | |
} | |
} | |
return out; | |
} | |
@Override | |
public Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) { | |
checkNotNull(clazz, "Input class can't be null"); | |
checkNotNull(methodName, "Method name can't be null"); | |
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) { | |
for (Method method : current.getDeclaredMethods()) { | |
if (method.getName().equals(methodName) && typesAreEquals(method.getParameterTypes(), parameterTypes)) { | |
makeAcessible(method); | |
return method; | |
} | |
} | |
} | |
return null; | |
} | |
@Override | |
public Object invoke(Object instance, Method method, Object... args) { | |
checkNotNull(instance, "Input instance can't be null"); | |
checkNotNull(method, "Input method can't be null"); | |
try { | |
makeAcessible(method); | |
return method.invoke(instance, args); | |
} catch (IllegalAccessException | InvocationTargetException e) { | |
throw new IllegalStateException(e); | |
} | |
} | |
@Override | |
public Object invoke(Object instance, String methodName, Object... args) { | |
checkNotNull(instance, "Input instance can't be null"); | |
checkNotNull(methodName, "Input method name can't be null"); | |
Class<?>[] parameterTypes = extractParameterTypes(args); | |
Method method = getMethod(instance.getClass(), methodName, parameterTypes); | |
checkNotNull(method, "Method %s isn't found on %s", method, instance.getClass()); | |
makeAcessible(method); | |
return invoke(instance, method, args); | |
} | |
@Override | |
public Object invokeGetter(Object instance, String fieldName) { | |
checkNotNull(instance, "Input instance can't be null"); | |
checkNotNull(fieldName, "Field name can't be null"); | |
String capitalizedName = captalize(fieldName); | |
Method method = findGetter(instance, capitalizedName); | |
checkNotNull(method, "A getter for %s isn't found on %s", fieldName, instance.getClass()); | |
return invoke(instance, method); | |
} | |
private Method findGetter(Object instance, String capitalizedName) { | |
for (String prefix : GETTER_PREFIX_LIST) { | |
Method method = getMethod(instance.getClass(), prefix + capitalizedName); | |
if (method != null) { | |
return method; | |
} | |
} | |
return null; | |
} | |
@Override | |
public List<Field> getFieldsFor(Class<?> clazz) { | |
checkNotNull(clazz, "Input class can't be null"); | |
List<Field> out = new ArrayList<Field>(); | |
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) { | |
for (Field field : current.getDeclaredFields()) { | |
makeAcessible(field); | |
out.add(field); | |
} | |
} | |
return out; | |
} | |
@Override | |
public Field getField(Class<?> clazz, String fieldName) { | |
checkNotNull(clazz, "Input class can't be null"); | |
checkNotNull(fieldName, "Field name can't be null"); | |
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) { | |
for (Field field : current.getDeclaredFields()) { | |
if (field.getName().equals(fieldName)) { | |
makeAcessible(field); | |
return field; | |
} | |
} | |
} | |
return null; | |
} | |
/** | |
* Set field or method as acessible to speed up reflection access. | |
*/ | |
private void makeAcessible(AccessibleObject object) { | |
if (!object.isAccessible()) { | |
object.setAccessible(true); | |
} | |
} | |
private Class<?>[] extractParameterTypes(Object... args) { | |
Class<?>[] parameterTypes = new Class<?>[args.length]; | |
for (int j = 0; j < args.length; j++) { | |
parameterTypes[j] = args[j].getClass(); | |
} | |
return parameterTypes; | |
} | |
private String captalize(String fieldName) { | |
if (fieldName.length() == 1) { | |
return fieldName.toUpperCase(); | |
} | |
return toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); | |
} | |
private boolean typesAreEquals(Class<?>[] parameterTypes, Class<?>[] expectedTypes) { | |
return parameterTypes.length == expectedTypes.length | |
&& Arrays.equals(parameterTypes, expectedTypes); | |
} | |
private void checkNotNull(Object object, String message, Object... messageParams) { | |
if (object == null) { | |
throw new NullPointerException(String.format(message, messageParams)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment