All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mentabean.util.PropertiesProxy Maven / Gradle / Ivy

There is a newer version: 2.2.4
Show newest version
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;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy