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

panda.bean.Beans Maven / Gradle / Ivy

package panda.bean;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import panda.bean.handler.ArrayBeanHandler;
import panda.bean.handler.CollectionBeanHandler;
import panda.bean.handler.IterableBeanHandler;
import panda.bean.handler.JavaBeanHandler;
import panda.bean.handler.ListBeanHandler;
import panda.bean.handler.MapBeanHandler;
import panda.lang.Arrays;
import panda.lang.Classes;
import panda.lang.Strings;
import panda.lang.reflect.Fields;
import panda.lang.reflect.Methods;
import panda.lang.reflect.Types;

public class Beans {
	private static Map, Map> accessors = new ConcurrentHashMap, Map>();
	
	/**
	 * instance
	 */
	private static Beans i = new Beans();

	/**
	 * @return singleton instance
	 */
	public static Beans i() {
		return i;
	}

	/**
	 * @return instance
	 */
	public static Beans getInstance() {
		return i;
	}

	/**
	 * @param instance the instance to set
	 */
	public static void setInstance(Beans instance) {
		Beans.i = instance;
	}

	// ------------------------------------------------------------------------
	public final static String[] RESERVED_PROPERTY_NAMES = { "class", "declaringClass", "metaClass" };

	public static boolean isReservedProperty(String propertyName) {
		return Arrays.contains(RESERVED_PROPERTY_NAMES, propertyName);
	}
	
	/**
	 * get bean name from method.
	 * the method must like getXXX, setXXX, isXXX
	 * 
	 * @param method method
	 * @return bean name if the method is a getter or setter
	 */
	public static String getGetterBeanName(Method method) {
		String name = method.getName();

		if (name.startsWith("get") && method.getParameterTypes().length == 0) {
			name = Strings.uncapitalize(name.substring(3));
		}
		else if (name.startsWith("is") && Classes.isBoolean(method.getReturnType())
				&& method.getParameterTypes().length == 0) {
			name = Strings.uncapitalize(name.substring(2));
		}
		else {
			name = null;
		}
		return name;
	}
	
	/**
	 * get bean name from method.
	 * the method must like getXXX, setXXX, isXXX
	 * 
	 * @param method method
	 * @return bean name if the method is a getter or setter
	 */
	public static String getSetterBeanName(Method method) {
		String name = method.getName();

		if (name.startsWith("set") && method.getParameterTypes().length == 1) {
			name = Strings.uncapitalize(name.substring(3));
		}
		else {
			name = null;
		}
		return name;
	}
	
	/**
	 * get bean name from method.
	 * the method must like getXXX, setXXX, isXXX
	 * 
	 * @param method method
	 * @return bean name if the method is a getter or setter
	 */
	public static String getBeanName(Method method) {
		String name = getGetterBeanName(method);
		if (name == null) {
			name = getSetterBeanName(method);
		}

		return name;
	}

	protected static void assertBeanAndName(Object bean, String name) {
		if (bean == null) {
			throw new IllegalArgumentException("argument bean is null.");
		}
		if (name == null) {
			throw new IllegalArgumentException("argument name is null.");
		}
	}
	
	/**
	 * 

* Return the value of the property of the specified name, * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be extracted * @param name the property to be extracted * @return the property value * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public static Object getBean(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = i().getBeanHandler(bean.getClass()); return bh.getBeanValue(bean, name); } /** *

* set the value of the property of the specified name. * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be set * @param name the property name * @param value the property value to be set * * @return true if set value successfully * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public static boolean setBean(Object bean, String name, Object value) { assertBeanAndName(bean, name); BeanHandler bh = i().getBeanHandler(bean.getClass()); return bh.setBeanValue(bean, name, value); } /** *

* Return the value of the property of the specified name, * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be extracted * @param name the property to be extracted * @return the property value * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public static Object getProperty(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = i().getBeanHandler(bean.getClass()); return bh.getPropertyValue(bean, name); } /** *

* set the value of the property of the specified name. * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be set * @param name the property name * @param value the property value to be set * @return true if set value successfully * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public static boolean setProperty(Object bean, String name, Object value) { assertBeanAndName(bean, name); BeanHandler bh = i().getBeanHandler(bean.getClass()); return bh.setPropertyValue(bean, name, value); } // ------------------------------------------------------------------------ /** * handler map */ protected Map handlers = new ConcurrentHashMap(); /** * prepareBeanHandler * * @param type class type */ public void prepareBeanHandler(Type type) { getBeanHandler(type); } /** * prepareBeanHandler * * @param types class type array */ public void prepareBeanHandler(Type[] types) { for (Type type : types) { prepareBeanHandler(type); } } /** * prepareBeanHandler * * @param types class type collection */ public void prepareBeanHandler(Collection types) { for (Type type : types) { prepareBeanHandler(type); } } /** * Register (add) a bean handler for a class * * @param type - the class * @param handler - the handler instance */ public void register(Type type, BeanHandler handler) { handlers.put(type, handler); } /** * Unregister (remove) a bean handler for a class * * @param type - the class */ public void unregister(Type type) { handlers.remove(type); } /** * clear bean handlers */ public void clear() { handlers.clear(); } /** * getBeanHandler * @param type bean type * @return BeanHandler */ public BeanHandler getBeanHandler(Class type) { return getBeanHandler((Type)type); } /** * getBeanHandler * @param type bean type * @return BeanHandler */ @SuppressWarnings("unchecked") public BeanHandler getBeanHandler(Type type) { if (type == null) { throw new NullPointerException("type is null"); } BeanHandler handler = handlers.get(type); if (handler != null) { return handler; } if (Types.isArrayType(type)) { handler = new ArrayBeanHandler(this, type); } else if (Types.isAssignable(type, Map.class)) { handler = new MapBeanHandler(this, type); } else if (Types.isAssignable(type, List.class)) { handler = new ListBeanHandler(this, type); } else if (Types.isAssignable(type, Collection.class)) { handler = new CollectionBeanHandler(this, type); } else if (Types.isAssignable(type, Iterable.class)) { handler = new IterableBeanHandler(this, type); } else if (Types.isImmutableType(type)) { throw new IllegalArgumentException("Illegal bean type: " + type); } else { synchronized(handlers) { handler = handlers.get(type); if (handler != null) { return handler; } handler = createJavaBeanHandler(type); register(type, handler); } } return handler; } /** * create java bean handler * @param type bean type * @return BeanHandler */ protected BeanHandler createJavaBeanHandler(Type type) { return new JavaBeanHandler(this, type); } private static void setField(Map accessors, Field field) { String name = field.getName(); Type type = Fields.getFieldType(field); if (!field.isAccessible()) { field.setAccessible(true); } PropertyAccessor pa = new PropertyAccessor(); pa.getter = field; if (!Modifier.isFinal(field.getModifiers())) { pa.setter = field; } pa.type = type; accessors.put(name, pa); } private static void setGetter(Map accessors, String name, Method getter) { Type type = getter.getGenericReturnType(); if (type == null) { type = getter.getReturnType(); } PropertyAccessor pa = accessors.get(name); if (pa == null) { if (!getter.isAccessible()) { getter.setAccessible(true); } pa = new PropertyAccessor(); pa.getter = getter; pa.type = type; accessors.put(name, pa); } else if (pa.getter == null) { if (Types.isAssignable(type, pa.type)) { if (!getter.isAccessible()) { getter.setAccessible(true); } pa.getter = getter; pa.type = type; } } } private static void setSetter(Map accessors, String name, Method setter) { Type type = Methods.getParameterType(setter, 0); PropertyAccessor pa = accessors.get(name); if (pa == null) { if (!setter.isAccessible()) { setter.setAccessible(true); } pa = new PropertyAccessor(); pa.setter = setter; pa.type = type; accessors.put(name, pa); } else if (pa.setter == null) { if (Types.isAssignable(type, pa.type)) { if (!setter.isAccessible()) { setter.setAccessible(true); } setter.setAccessible(true); pa.setter = setter; pa.type = type; } } } /** * get property accessor map according to the specified class * @param clazz class * @return accessor map */ public static Map getPropertyAccessors(Class clazz) { Map pas = accessors.get(clazz); if (pas != null) { return pas; } synchronized(accessors) { pas = accessors.get(clazz); if (pas != null) { return pas; } pas = resolvePropertyAccessors(clazz); accessors.put(clazz, pas); return pas; } } public static Map resolvePropertyAccessors(Class clazz) { Map pas = new TreeMap(); Field[] fields = clazz.getFields(); for (Field f : fields) { int m = f.getModifiers(); if (f.isSynthetic() || Modifier.isStatic(m)) { continue; } setField(pas, f); } Method[] methods = clazz.getMethods(); // is for (Method m : methods) { if (Modifier.isStatic(m.getModifiers()) || m.isSynthetic() || m.isBridge()) { continue; } if (boolean.class != m.getReturnType()) { continue; } Type[] pts = m.getGenericParameterTypes(); if (pts != null && pts.length != 0) { continue; } if (!m.getName().startsWith("is")) { continue; } String n = m.getName().substring(2); if (n.isEmpty() || Character.isLowerCase(n.charAt(0))) { continue; } n = Character.toLowerCase(n.charAt(0)) + n.substring(1); setGetter(pas, n, m); } // getter for (Method m : methods) { if (Modifier.isStatic(m.getModifiers()) || m.isSynthetic() || m.isBridge()) { continue; } Type[] pts = m.getGenericParameterTypes(); if (pts != null && pts.length != 0) { continue; } if (!m.getName().startsWith("get")) { continue; } String n = m.getName().substring(3); if (n.isEmpty() || Character.isLowerCase(n.charAt(0))) { continue; } n = Character.toLowerCase(n.charAt(0)) + n.substring(1); setGetter(pas, n, m); } // setter for (Method m : methods) { if (Modifier.isStatic(m.getModifiers()) || m.isSynthetic() || m.isBridge()) { continue; } if (!Void.TYPE.equals(m.getReturnType())) { continue; } Type[] pts = m.getGenericParameterTypes(); if (pts == null || pts.length != 1) { continue; } if (!m.getName().startsWith("set")) { continue; } String n = m.getName().substring(3); if (n.isEmpty() || Character.isLowerCase(n.charAt(0))) { continue; } n = Character.toLowerCase(n.charAt(0)) + n.substring(1); setSetter(pas, n, m); } return pas; } /** *

* Return the value of the property of the specified name, * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be extracted * @param name the property to be extracted * @return the property value * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public Object getBeanValue(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.getBeanValue(bean, name); } @SuppressWarnings("unchecked") public Type getBeanType(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.getBeanType(bean, name); } /** *

* set the value of the property of the specified name. * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be set * @param name the property name * @param value the property value to be set * @return true if set value successfully * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public boolean setBeanValue(Object bean, String name, Object value) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.setBeanValue(bean, name, value); } @SuppressWarnings("unchecked") public Type getPropertyType(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.getPropertyType(bean, name); } /** *

* Return the value of the property of the specified name, * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be extracted * @param name the property to be extracted * @return the property value * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public Object getPropertyValue(Object bean, String name) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.getPropertyValue(bean, name); } /** *

* set the value of the property of the specified name. * for the specified bean, with no type conversions. *

* * @param bean Bean whose property is to be set * @param name the property name * @param value the property value to be set * @return true if set value successfully * * @exception IllegalArgumentException if bean or * name is null * throws an exception */ @SuppressWarnings("unchecked") public boolean setPropertyValue(Object bean, String name, Object value) { assertBeanAndName(bean, name); BeanHandler bh = getBeanHandler(bean.getClass()); return bh.setPropertyValue(bean, name, value); } @SuppressWarnings("unchecked") public void copyProperties(Object des, Object src, String ... props) { if (src == null || des == null || props == null || props.length == 0) { return; } BeanHandler sbh = getBeanHandler(src.getClass()); BeanHandler dbh = getBeanHandler(des.getClass()); for (String p : props) { Object v = sbh.getPropertyValue(src, p); dbh.setPropertyValue(des, p, v); } } @SuppressWarnings("unchecked") public void copyNotNullProperties(Object des, Object src, String ... props) { if (src == null || des == null || props == null || props.length == 0) { return; } BeanHandler sbh = getBeanHandler(src.getClass()); BeanHandler dbh = getBeanHandler(des.getClass()); for (String p : props) { Object v = sbh.getPropertyValue(src, p); if (v != null) { dbh.setPropertyValue(des, p, v); } } } @SuppressWarnings("unchecked") public void copyBeans(Object des, Object src, String ... props) { if (src == null || des == null || props == null || props.length == 0) { return; } BeanHandler sbh = getBeanHandler(src.getClass()); BeanHandler dbh = getBeanHandler(des.getClass()); for (String p : props) { Object v = sbh.getBeanValue(src, p); dbh.setBeanValue(des, p, v); } } @SuppressWarnings("unchecked") public void copyNotNullBeans(Object des, Object src, String ... props) { if (src == null || des == null || props == null || props.length == 0) { return; } BeanHandler sbh = getBeanHandler(src.getClass()); BeanHandler dbh = getBeanHandler(des.getClass()); for (String p : props) { Object v = sbh.getBeanValue(src, p); if (v != null) { dbh.setBeanValue(des, p, v); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy