package com.bitkiller.nullsafety;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class NullSafety<T> {
@SuppressWarnings("unchecked")
public static <T> T unbox(T instance) {
if (instance == null) {
return null;
} else if (Enhancer.isEnhanced(instance.getClass())) {
NullProxyInterface np = (NullProxyInterface) instance;
return (T)np.getProxiedInstance();
} else {
return instance;
}
}
@SuppressWarnings("unchecked")
public static <T> T of(final T instance) {
return of(instance, (Class<T>) instance.getClass());
}
private static <T> T of(final T instance, Class<?> instanceClass) {
@SuppressWarnings("unchecked")
T proxy = (T) Enhancer.create(instanceClass, new Class[] { NullProxyInterface.class }, new MethodInterceptor() {
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
if (method.getDeclaringClass() == NullProxyInterface.class) {
return instance;
}
//System.out.println("-- started " + method + " - " + method.getDeclaringClass());
Class<?> methodResultType = method.getReturnType();
if (instance != null) {
Object result = proxy.invoke(instance, args);
if (void.class == methodResultType) {
return result;
} else if (Modifier.isFinal(methodResultType.getModifiers())) {
return result;
} else {
return NullSafety.of(result, methodResultType);
}
} else {
//if (void.class == methodResultType) {
// return null;
//} else if (boolean.class == methodResultType) {
// return false;
//} else if (long.class == methodResultType) {
// return 0;
//} else {
return null;
//}
}
}
});
return proxy;
}
}