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

com.dragome.forms.bindings.reflect.BeanDescriptor Maven / Gradle / Ivy

There is a newer version: 0.96-beta4
Show newest version
package com.dragome.forms.bindings.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;

import com.dragome.forms.bindings.client.bean.AbstractPropertyDescriptor;
import com.dragome.forms.bindings.client.bean.NotCollectionPropertyException;
import com.dragome.forms.bindings.client.bean.Path;
import com.dragome.forms.bindings.client.bean.PropertyDescriptor;
import com.dragome.forms.bindings.client.bean.ReadOnlyPropertyException;
import com.dragome.forms.bindings.client.bean.TargetBeanIsNullException;
import com.dragome.forms.bindings.client.bean.UnknownPropertyException;

/**
 * Created by IntelliJ IDEA.
 * User: andrew
 * Date: Jun 1, 2010
 * Time: 11:34:01 AM
 * To change this template use File | Settings | File Templates.
 */
class BeanDescriptor
{
	private Class beanClass;
	private HashMap descriptors= new HashMap();
	private HashMap, Class> primitives= new HashMap, Class>();

	public BeanDescriptor(Class beanClass)
	{
		this.beanClass= beanClass;
		primitives.put(boolean.class, Boolean.class);
		primitives.put(char.class, Character.class);
		primitives.put(byte.class, Byte.class);
		primitives.put(short.class, Short.class);
		primitives.put(int.class, Integer.class);
		primitives.put(long.class, Long.class);
		primitives.put(float.class, Float.class);
		primitives.put(double.class, Double.class);
	}

	public PropertyDescriptor getPropertyDescriptor(Path path)
	{
		PropertyDescriptor descriptor= descriptors.get(path.getPropertyName());

		if (descriptor == null)
		{
			ensurePropertyExists(path);
			descriptor= new PropertyDescriptorImpl(path, beanClass, isMutable(path));
			descriptors.put(path.getPropertyName(), descriptor);
		}

		return descriptor;
	}

	private boolean isMutable(Path path)
	{
		// the getter exists...
		getGetter(path);

		try
		{
			// oh so hacky...
			getSetter(path);
			return true;
		}
		catch (ReadOnlyPropertyException e)
		{
			return false;
		}
	}

	public Object readProperty(Object bean, Path path) throws UnknownPropertyException
	{
		if (bean == null)
		{
			return null;
		}

		try
		{
			return getGetter(path).invoke(bean);
		}
		catch (IllegalAccessException e)
		{
			throw new UnknownPropertyException(path);
		}
		catch (InvocationTargetException e)
		{
			throw new UnknownPropertyException(path);
		}
	}

	public void writeProperty(Object bean, Path path, Object value) throws UnknownPropertyException, ReadOnlyPropertyException, TargetBeanIsNullException
	{
		if (bean == null)
		{
			throw new TargetBeanIsNullException(path, beanClass);
		}

		Method setter= getSetter(path);

		try
		{
			setter.invoke(bean, value);
		}
		catch (IllegalAccessException e)
		{
			throw new UnknownPropertyException(path);
		}
		catch (InvocationTargetException e)
		{
			throw new UnknownPropertyException(path);
		}
	}

	private void ensurePropertyExists(Path path)
	{
		// oh so hacky...
		getGetter(path);
	}

	private Method findMethod(String methodName, Class... parameterTypes) throws NoSuchMethodException
	{
		Class theClass= this.beanClass;
		while (true)
		{
			//System.out.println("hola mundo");
			int a= 1;
			try
			{
				return theClass.getMethod(methodName, parameterTypes);
			}
			catch (NoSuchMethodException e)
			{
				theClass= theClass.getSuperclass();
				if (theClass == null)
				{
					throw new NoSuchMethodException();
				}
			}
		}
	}

	private Method getGetter(Path path) throws UnknownPropertyException
	{
		try
		{
			return findMethod("get" + capitalise(path.getPropertyName()));
		}
		catch (NoSuchMethodException e)
		{
			try
			{
				// should really test it's return type is boolean...
				return findMethod("is" + capitalise(path.getPropertyName()));
			}
			catch (NoSuchMethodException e1)
			{
				throw new UnknownPropertyException(path);
			}
		}
	}

	private Method getSetter(Path path) throws ReadOnlyPropertyException
	{
		try
		{
			return beanClass.getMethod("set" + capitalise(path.getPropertyName()), getRawPropertyType(path));
		}
		catch (NoSuchMethodException e)
		{
			throw new ReadOnlyPropertyException(path);
		}
	}

	public Class getPropertyType(Path path)
	{
		Class type= getRawPropertyType(path);
		return type.isPrimitive() ? primitives.get(type) : type;
	}

	private Class getRawPropertyType(Path path)
	{
		return getGetter(path).getReturnType();
	}

	public Class getElementType(Path path)
	{
		Method method= getGetter(path);
		Class type= method.getReturnType();

		if (!Collection.class.isAssignableFrom(type))
		{
			throw new NotCollectionPropertyException(path, type);
		}

		Type returnType= method.getGenericReturnType();

		if (returnType instanceof ParameterizedType)
		{
			Type[] typeArgs= ((ParameterizedType) returnType).getActualTypeArguments();
			return typeArgs.length == 1 ? (Class) typeArgs[0] : Object.class;
		}
		else
		{
			return Object.class;
		}
	}

	private String capitalise(String property)
	{
		return property.substring(0, 1).toUpperCase() + property.substring(1);
	}

	private class PropertyDescriptorImpl extends AbstractPropertyDescriptor
	{
		public PropertyDescriptorImpl(Path path, Class beanClass, boolean mutable)
		{
			super(path.getFullPath(), path.getParentPath(), path.getPropertyName(), beanClass, mutable);
		}

		public Class getValueType()
		{
			return getPropertyType(this);
		}

		public Class getElementType() throws NotCollectionPropertyException
		{
			return BeanDescriptor.this.getElementType(this);
		}

		public boolean isCollection()
		{
			return Collection.class.isAssignableFrom(getValueType());
		}

		public Object readProperty(Object bean)
		{
			return BeanDescriptor.this.readProperty(bean, this);
		}

		public void writeProperty(Object bean, Object value) throws ReadOnlyPropertyException, TargetBeanIsNullException
		{
			BeanDescriptor.this.writeProperty(bean, this, value);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy