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

org.uqbar.commons.model.ScalaBeanInfo Maven / Gradle / Ivy

package org.uqbar.commons.model;

import java.awt.Image;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.uqbar.commons.utils.ReflectionUtils;


public class ScalaBeanInfo implements BeanInfo {

	private static final Log logger = LogFactory.getLog(ScalaBeanInfo.class);

	private static final String SCALA_SETTER_SUFFIX = "_$eq";

	private final BeanInfo delegate;

	private final PropertyDescriptor[] propertyDescriptors;

	public ScalaBeanInfo(Class beanClass) throws IntrospectionException {
		this(Introspector.getBeanInfo(beanClass));
	}

	public ScalaBeanInfo(BeanInfo delegate) throws IntrospectionException {
		this.delegate = delegate;
		this.propertyDescriptors = initPropertyDescriptors(delegate);
	}

	private static PropertyDescriptor[] initPropertyDescriptors(BeanInfo beanInfo) {
		Map propertyDescriptors =
				new TreeMap(new PropertyNameComparator());
		for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
			propertyDescriptors.put(pd.getName(), pd);
		}

		for (MethodDescriptor md : beanInfo.getMethodDescriptors()) {
			Method method = md.getMethod();

			if (ReflectionUtils.isObjectMethod(method)) {
				continue;
			}
			if (isScalaSetter(method)) {
				addScalaSetter(propertyDescriptors, method);
			}
			else if (isScalaGetter(method)) {
				addScalaGetter(propertyDescriptors, method);
			}
		}
		return propertyDescriptors.values()
				.toArray(new PropertyDescriptor[propertyDescriptors.size()]);
	}

	private static boolean isScalaGetter(Method method) {
		return method.getParameterTypes().length == 0 &&
				!method.getReturnType().equals(Void.TYPE) &&
				!(method.getName().startsWith("get") ||
						method.getName().startsWith("is"));
	}

	public static boolean isScalaSetter(Method method) {
		return method.getParameterTypes().length == 1 &&
				method.getReturnType().equals(Void.TYPE) &&
				method.getName().endsWith(SCALA_SETTER_SUFFIX);
	}

	private static void addScalaSetter(Map propertyDescriptors,
	                                   Method writeMethod) {
		String propertyName = writeMethod.getName().substring(0,
				writeMethod.getName().length() - SCALA_SETTER_SUFFIX.length());

		PropertyDescriptor pd = propertyDescriptors.get(propertyName);
		if (pd != null && pd.getWriteMethod() == null) {
			try {
				pd.setWriteMethod(writeMethod);
			}
			catch (IntrospectionException ex) {
				logger.debug("Could not add write method [" + writeMethod + "] for " +
						"property [" + propertyName + "]: " + ex.getMessage());
			}
		}
		else if (pd == null) {
			try {
				pd = new PropertyDescriptor(propertyName, null, writeMethod);
				propertyDescriptors.put(propertyName, pd);
			}
			catch (IntrospectionException ex) {
				logger.debug("Could not create new PropertyDescriptor for " +
						"writeMethod [" + writeMethod + "] property [" + propertyName +
						"]: " + ex.getMessage());
			}
		}
	}

	private static void addScalaGetter(Map propertyDescriptors,
	                                   Method readMethod) {
		String propertyName = readMethod.getName();

		PropertyDescriptor pd = propertyDescriptors.get(propertyName);
		if (pd != null && pd.getReadMethod() == null) {
			try {
				pd.setReadMethod(readMethod);
			}
			catch (IntrospectionException ex) {
				logger.debug("Could not add read method [" + readMethod + "] for " +
						"property [" + propertyName + "]: " + ex.getMessage());
			}
		}
		else if (pd == null) {
			try {
				pd = new PropertyDescriptor(propertyName, readMethod, null);
				propertyDescriptors.put(propertyName, pd);
			}
			catch (IntrospectionException ex) {
				logger.debug("Could not create new PropertyDescriptor for " +
						"readMethod [" + readMethod + "] property [" + propertyName +
						"]: " + ex.getMessage());
			}
		}
	}

	public PropertyDescriptor[] getPropertyDescriptors() {
		return propertyDescriptors;
	}

	public BeanInfo[] getAdditionalBeanInfo() {
		return delegate.getAdditionalBeanInfo();
	}

	public BeanDescriptor getBeanDescriptor() {
		return delegate.getBeanDescriptor();
	}

	public int getDefaultEventIndex() {
		return delegate.getDefaultEventIndex();
	}

	public int getDefaultPropertyIndex() {
		return delegate.getDefaultPropertyIndex();
	}

	public EventSetDescriptor[] getEventSetDescriptors() {
		return delegate.getEventSetDescriptors();
	}

	public Image getIcon(int iconKind) {
		return delegate.getIcon(iconKind);
	}

	public MethodDescriptor[] getMethodDescriptors() {
		return delegate.getMethodDescriptors();
	}
	
	public PropertyDescriptor getPropertyDescriptor(String property){
		String propertyName = property;
		if(property.startsWith("_")){
			propertyName = propertyName.substring(1);
		}
		for (PropertyDescriptor descriptor : this.propertyDescriptors) {
			if(descriptor.getName().equals(propertyName)){
				return descriptor; 
			}
		}
		return null;
	}
	
	public static PropertyDescriptor getPropertyDescriptor(Object bean, String name){
		return getPropertyDescriptor(bean.getClass(), name);
	}
	
	public static PropertyDescriptor getPropertyDescriptor(Class bean, String name){
		try {
			return new ScalaBeanInfo(bean).getPropertyDescriptor(name);
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static PropertyDescriptor[] getPropertyDescriptors(Class bean){
		try {
			return new ScalaBeanInfo(bean.getClass()).getPropertyDescriptors();
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Sorts property names alphanumerically to emulate the behavior of {@link
	 * java.beans.BeanInfo#getPropertyDescriptors()}.
	 */
	private static class PropertyNameComparator implements Comparator {

		public int compare(String left, String right) {
			byte[] leftBytes = left.getBytes();
			byte[] rightBytes = right.getBytes();

			for (int i = 0; i < left.length(); i++) {
				if (right.length() == i) {
					return 1;
				}
				int result = leftBytes[i] - rightBytes[i];
				if (result != 0) {
					return result;
				}
			}
			return left.length() - right.length();
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy