/*
* Copyright 2004-2010 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.slim3.util;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* This class describes bean information.
*
* @author higa
* @since 1.0.0
*
*/
public final class BeanDesc {
private Class<?> beanClass;
private CaseInsensitiveMap<PropertyDesc> propertyDescCache =
new CaseInsensitiveMap<PropertyDesc>();
/**
* Constructor.
*
* @param beanClass
* the bean class
*/
BeanDesc(Class<?> beanClass) {
this.beanClass = beanClass;
}
/**
* Creates the bean descriptor.
*
* @param beanClass
* the bean class
* @return the bean descriptor
* @throws NullPointerException
* if the beanClass parameter is null
*/
public static BeanDesc create(Class<?> beanClass) {
if (beanClass == null) {
throw new NullPointerException("The beanClass parameter is null.");
}
BeanDesc beanDesc = new BeanDesc(beanClass);
setupPropertyDesc(beanDesc);
return beanDesc;
}
private static void setupPropertyDesc(BeanDesc beanDesc) {
Set<String> illegalPropertyNames = new HashSet<String>();
Method[] methods = beanDesc.beanClass.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.isBridge()
|| m.isSynthetic()
|| m.getDeclaringClass() == Object.class) {
continue;
}
String methodName = m.getName();
if (methodName.startsWith("get")) {
if (m.getParameterTypes().length != 0
|| m.getReturnType() == void.class) {
continue;
}
String propertyName =
StringUtil.decapitalize(methodName.substring(3));
setupReadMethod(beanDesc, m, propertyName, illegalPropertyNames);
} else if (methodName.startsWith("is")) {
if (m.getParameterTypes().length != 0
|| m.getReturnType() != boolean.class) {
continue;
}
String propertyName =
StringUtil.decapitalize(methodName.substring(2));
setupReadMethod(beanDesc, m, propertyName, illegalPropertyNames);
} else if (methodName.startsWith("set")) {
if (m.getParameterTypes().length != 1
|| m.getReturnType() != void.class) {
continue;
}
String propertyName =
StringUtil.decapitalize(methodName.substring(3));
setupWriteMethod(
beanDesc,
m,
propertyName,
illegalPropertyNames);
}
}
for (Iterator<String> i = illegalPropertyNames.iterator(); i.hasNext();) {
beanDesc.propertyDescCache.remove(i.next());
}
}
private static void setupReadMethod(BeanDesc beanDesc, Method readMethod,
String propertyName, Set<String> illegalPropertyNames) {
Class<?> propertyClass = readMethod.getReturnType();
PropertyDesc propDesc = beanDesc.propertyDescCache.get(propertyName);
if (propDesc != null) {
if (!propDesc.getPropertyClass().equals(propertyClass)) {
illegalPropertyNames.add(propertyName);
} else {
propDesc.setReadMethod(readMethod);
}
} else {
propDesc =
new PropertyDesc(
propertyName,
propertyClass,
beanDesc.beanClass);
propDesc.setReadMethod(readMethod);
beanDesc.propertyDescCache.put(propertyName, propDesc);
}
}
private static void setupWriteMethod(BeanDesc beanDesc, Method writeMethod,
String propertyName, Set<String> illegalPropertyNames) {
Class<?> propertyClass = writeMethod.getParameterTypes()[0];
PropertyDesc propDesc = beanDesc.propertyDescCache.get(propertyName);
if (propDesc != null) {
if (!propDesc.getPropertyClass().equals(propertyClass)) {
illegalPropertyNames.add(propertyName);
} else {
propDesc.setWriteMethod(writeMethod);
}
} else {
propDesc =
new PropertyDesc(
propertyName,
propertyClass,
beanDesc.beanClass);
propDesc.setWriteMethod(writeMethod);
beanDesc.propertyDescCache.put(propertyName, propDesc);
}
}
/**
* Returns the bean class.
*
* @return the bean class
*/
public Class<?> getBeanClass() {
return beanClass;
}
/**
* Returns the property descriptor.
*
* @param propertyName
* the property name
* @return the property descriptor
*/
public PropertyDesc getPropertyDesc(String propertyName) {
return propertyDescCache.get(propertyName);
}
/**
* Returns the property descriptor for index.
*
* @param index
* the index
* @return the property descriptor
*/
public PropertyDesc getPropertyDesc(int index) {
return propertyDescCache.get(index);
}
/**
* Returns the number of property descriptors.
*
* @return the number of property descriptors.
*/
public int getPropertyDescSize() {
return propertyDescCache.size();
}
}