org.mentabean.util.PropertiesProxy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of menta-bean Show documentation
Show all versions of menta-bean Show documentation
An query helper and simple CRUD ORM.
package org.mentabean.util;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import org.mentabean.BeanException;
public class PropertiesProxy {
private static Class>[] ignored = new Class>[] {
BigDecimal.class, Date.class, Timestamp.class, Time.class
};
private String chainProp;
public PropertiesProxy(String chainProp) {
this.chainProp = chainProp;
}
public static E create(Class klass) {
PropertiesProxy pp = new PropertiesProxy(null);
return pp.createInternal(klass);
}
private static final ThreadLocal> propertyNames = new ThreadLocal>();
private static final ThreadLocal> klassType = new ThreadLocal>();
public static String getPropertyName() {
List list = propertyNames.get();
if (list == null || list.size() != 1) {
throw new BeanException("Was not able to get property name through the proxy!");
}
String propName = list.get(0);
list.clear();
return propName;
}
public static Class> getBeanClass() {
Class> klass = klassType.get();
klassType.remove();
return klass;
}
public static void addPropertyName(String name) {
List list = propertyNames.get();
if (list == null) {
list = new LinkedList();
propertyNames.set(list);
}
list.add(name);
}
public static boolean hasProperties() {
List list = propertyNames.get();
if (list != null && list.size() > 0) return true;
return false;
}
public static String[] getPropertyNames() {
List list = propertyNames.get();
if (list == null || list.size() == 0) {
throw new BeanException("Was not able to get property names through the proxy!");
}
String[] array = new String[list.size()];
array = list.toArray(array);
list.clear();
return array;
}
/**
* Return the property name, if the method is a valid JavaBean getter
*
* @param method the method
* @return the property name of null if not a valid getter
*/
private static String getPropName(Method method) {
String methodName = method.getName();
Class> propType = method.getReturnType();
if (propType.equals(Void.class)) return null; // not a getter
Class>[] params = method.getParameterTypes();
if (params != null && params.length > 0) return null; // not a getter
String propName;
if (methodName.startsWith("get") && methodName.length() > 3) {
propName = methodName.substring(3);
} else if (methodName.startsWith("is") && methodName.length() > 2 && (propType.equals(boolean.class) || propType.equals(Boolean.class))) {
propName = methodName.substring(2);
} else {
return null; // not a getter...
}
propName = propName.substring(0, 1).toLowerCase() + propName.substring(1); // first letter is lower-case
if (propName.equals("class")) return null; // not a property...
return propName;
}
private E createInternal(final Class klass) {
try {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(klass);
factory.setFilter(new MethodFilter() {
@Override
public boolean isHandled(Method m) {
return getPropName(m) != null;
}
});
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
List list = propertyNames.get();
if (list == null) {
list = new LinkedList();
propertyNames.set(list);
}
String propName = getPropName(thisMethod);
if (chainProp != null) {
list.add(chainProp + "." + propName);
// remember to remove original one because it is not really a property
// like "user" in "user.id"
list.remove(chainProp);
} else {
list.add(propName);
}
// add the object type for SQLBuilder column( ... ) method
klassType.set(klass);
Class> propType = thisMethod.getReturnType();
// take care of primitives that cannot be null...
if (propType.equals(boolean.class)) {
return false;
} else if (propType.equals(char.class)) {
return (char) 0;
} else if (propType.equals(byte.class)) {
return (byte) 0;
} else if (propType.equals(long.class)) {
return (long) 0;
} else if (propType.equals(int.class)) {
return (int) 0;
} else if (propType.equals(short.class)) {
return (short) 0;
} else if (propType.equals(float.class)) {
return (float) 0;
} else if (propType.equals(double.class)) {
return (double) 0;
} else {
// Class must NOT be final otherwise javassist does not work!
if (Modifier.isFinal(propType.getModifiers()) || propType.isInterface()) {
return null;
}
// Must be ignored from Javassist
if (isIgnored(propType)) {
return null;
}
// return a new one
PropertiesProxy proxy = new PropertiesProxy(chainProp != null ? chainProp + "." + propName : propName);
return proxy.createInternal(propType);
}
}
};
return (E) factory.create(new Class[0], new Object[0], handler);
} catch(Exception e) {
throw new BeanException(e);
}
}
private static boolean isIgnored(Class> clazz) {
for (Class> ign : ignored) {
if (ign.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
}