package org.hivedb.util.functional;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.hivedb.util.AccessorFunction;
import org.hivedb.util.classgen.ReflectionTools;
public class GetSetReflectionFunction {
public static<T> AccessorFunction<Object> CreateFunction(final Class fieldClass, final T instance, final String memberName) {
return new AccessorFunction<Object>() {
public Object get() {
return invokeGetter(instance, ReflectionTools.capitalize(memberName));
}
public void set(Object value) {
invokeSetter(instance, ReflectionTools.capitalize(memberName), value);
}
public Class getFieldClass() {
return getGetterMethod(instance, ReflectionTools.capitalize(memberName)).getReturnType();
}
};
}
private static Object invokeGetter(Object instance, final String memberName)
{
try {
return getGetterMethod(instance, memberName).invoke(instance, new Object[] {});
} catch (Exception exception) {
throw new RuntimeException("Exception invoiking method get" + memberName, exception);
}
}
private static Method getGetterMethod(Object instance, final String memberName) {
try {
return instance.getClass().getMethod("get"+memberName, new Class[] {});
} catch (Exception exception) {
throw new RuntimeException("Exception looking up method get" + memberName, exception);
}
}
private static void invokeSetter(Object instance, String memberName, Object value)
{
String setterName = "set"+memberName;
final String memberNameFinal = memberName;
// try to match on the value's type
try {
instance.getClass().getMethod(setterName, new Class[] {value.getClass()})
.invoke(instance, new Object[] {value});
}
catch (Exception exception) {
// iterate through all methods until a name-matched setter is found
try {
Filter.grepSingle(
new Predicate<Method>() { public boolean f(Method m) {
return m.getName().equals("set"+memberNameFinal);
}},
Arrays.asList(instance.getClass().getMethods()))
.invoke(instance, new Object[] {value});
}
catch (Exception e)
{
throw new RuntimeException("Exception calling method set" + memberName
+ " with a value of type " + value.getClass(), e);
}
}
}
}