package com.aggrepoint.winlet.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.SQLException;
/**
* Bean属性定义
*
* 创建日期:(2002-11-27)
*
* @author: Yang Jiang Ming
*/
public class BeanProperty implements PropertyTypeCode {
protected static Object[] EMPTYOBJECTARRAY = new Object[0];
/** 属性名称。如果不是通过属性指定的,则为null */
protected String m_strPropertyName;
/** 属性字段名称。如果不映射到字段,则为null */
protected String m_strFieldName;
/** 属性字段。如果不映射到字段,则为null */
protected Field m_f;
/** 属性Get方法的名称。如果不对应到Get和Set方法则为null */
protected String m_strGetName;
/** 属性Get方法。如果不对应到Get和Set方法则为null */
protected Method m_mGet;
/** 属性Set方法的名称。如果不对应到Get和Set方法则为null */
protected String m_strSetName;
/** 属性Set方法。如果不对应到Get和Set方法则为null */
protected Method m_mSet;
/** 属性类型 */
protected Class<?> m_cType;
/** 用数值来表示的属性类型 */
protected int m_iType;
/** 属性空类型 */
protected int m_iNullType;
/**
* 获取数据类型
*/
public static int getTypeCode(Class<?> c) {
int iType = 0;
String strFieldType = c.getName();
if (strFieldType.equals("short")
|| strFieldType.equals(Short.class.getName()))
iType = SHORT;
else if (strFieldType.equals("int")
|| strFieldType.equals(Integer.class.getName()))
iType = INTEGER;
else if (strFieldType.equals("long")
|| strFieldType.equals(Long.class.getName()))
iType = LONG;
else if (strFieldType.equals("float")
|| strFieldType.equals(Float.class.getName()))
iType = FLOAT;
else if (strFieldType.equals("double")
|| strFieldType.equals(Double.class.getName()))
iType = DOUBLE;
else if (strFieldType.equals("boolean")
|| strFieldType.equals(Boolean.class.getName()))
iType = BOOLEAN;
else if (strFieldType.equals("java.lang.String"))
iType = STRING;
else if (java.sql.Timestamp.class.isAssignableFrom(c))
iType = TIMESTAMP;
else if (java.sql.Date.class.isAssignableFrom(c))
iType = DATE;
else if (java.io.InputStream.class.isAssignableFrom(c))
iType = INPUTSTREAM;
else if (java.util.Collection.class.isAssignableFrom(c))
iType = COLLECTION;
return iType;
}
/**
* 获取数据类型
*/
static int getNullTypeCode(Class<?> c) {
int iType = 0;
String strFieldType = c.getName();
if (strFieldType.equals("short")
|| strFieldType.equals(Short.class.getName()))
iType = java.sql.Types.SMALLINT;
else if (strFieldType.equals("int")
|| strFieldType.equals(Integer.class.getName()))
iType = java.sql.Types.INTEGER;
else if (strFieldType.equals("long")
|| strFieldType.equals(Long.class.getName()))
iType = java.sql.Types.BIGINT;
else if (strFieldType.equals("float")
|| strFieldType.equals(Float.class.getName()))
iType = java.sql.Types.FLOAT;
else if (strFieldType.equals("double")
|| strFieldType.equals(Double.class.getName()))
iType = java.sql.Types.DOUBLE;
else if (strFieldType.equals("boolean")
|| strFieldType.equals(Boolean.class.getName()))
iType = java.sql.Types.BOOLEAN;
else if (strFieldType.equals("java.lang.String"))
iType = java.sql.Types.VARCHAR;
else if (java.sql.Timestamp.class.isAssignableFrom(c))
iType = java.sql.Types.TIMESTAMP;
else if (java.sql.Date.class.isAssignableFrom(c))
iType = java.sql.Types.DATE;
else if (java.io.InputStream.class.isAssignableFrom(c))
iType = java.sql.Types.BINARY;
return iType;
}
/**
* 从方法数组中根据方法名称找出方法
*/
static Method getMethodByName(Method[] methods, String methodName) {
for (int i = 0; i < methods.length; i++)
if (methods[i].getName().equalsIgnoreCase(methodName))
return methods[i];
return null;
}
protected BeanProperty() {
}
protected void init(Class<?> cBean, String propertyName, boolean readable,
boolean writable, Class<?> type, Class<?>... args)
throws BeanPropertyException {
m_strPropertyName = propertyName;
m_strFieldName = m_strGetName = m_strSetName = null;
m_f = null;
m_mGet = m_mSet = null;
m_cType = null;
m_iType = 0;
// {首先试将属性看作为字段
if (args == null || args.length == 0) {
try {
m_f = cBean.getField(m_strPropertyName);
m_strFieldName = m_strPropertyName;
if (type != null)
m_cType = type;
else
m_cType = m_f.getType();
} catch (NoSuchFieldException e) {
}
if (m_f != null) { // 是字段
m_iType = getTypeCode(m_cType);
m_iNullType = getNullTypeCode(m_cType);
return;
}
}
// }
Method[] methods = cBean.getMethods();
Class<?>[] params;
Class<?> cGetType = null, cSetType = null;
// {尝试get方法
if (readable) {
m_mGet = getMethodByName(methods, "get" + propertyName);
if (m_mGet == null)
m_mGet = getMethodByName(methods, propertyName);
if (m_mGet == null)
throw new BeanPropertyException("Property " + propertyName
+ " of class " + cBean.getName()
+ " should be readable.");
m_strGetName = m_mGet.getName();
// {检查Get方法所带参数,并获取Get方法的返回值类型
params = m_mGet.getParameterTypes();
if (params.length != (args == null ? 0 : args.length))
throw new BeanPropertyException("Getter method \""
+ m_strGetName + "\" of class \"" + cBean.getName()
+ "\" has wrong number of parameters.");
if (args != null)
for (int i = 0; i < params.length; i++)
if (!params[i].isAssignableFrom(args[i]))
throw new BeanPropertyException("Getter method \"("
+ m_strGetName + ")\" of class \"("
+ cBean.getName()
+ ")\" has wrong parameter types.");
cGetType = m_mGet.getReturnType();
// }
}
// }
// {尝试set方法
if (writable) {
m_mSet = getMethodByName(methods, "set" + propertyName);
if (m_mSet == null)
m_mSet = getMethodByName(methods, propertyName);
if (m_mSet == null)
throw new BeanPropertyException("Property " + propertyName
+ " of class " + propertyName + " should be writable.");
m_strSetName = m_mSet.getName();
// {Set方法的参数类型
params = m_mSet.getParameterTypes();
if (params.length != (1 + (args == null ? 0 : args.length)))
throw new BeanPropertyException("Setter method \""
+ m_strSetName + "\" of class \"" + cBean.getName()
+ "\" has wrong number of parameters.");
if (args != null)
for (int i = 0; i < args.length; i++)
if (!params[i].isAssignableFrom(args[i]))
throw new BeanPropertyException("Setter method \""
+ m_strSetName + "\" of class \""
+ cBean.getName()
+ "\" has wrong parameter types.");
cSetType = params[params.length - 1];
// }
}
// }
if (cGetType == null && cSetType == null) // 没有找到对应的属性
throw new BeanPropertyException("Property " + propertyName
+ " not exist in class " + cBean.getName() + ".");
// {检验get方法与set方法是否一致
if (cGetType != null && cSetType != null)
if (!java.io.InputStream.class.isAssignableFrom(cGetType)
&& !java.sql.Blob.class.isAssignableFrom(cSetType))
if (!cSetType.equals(cGetType)) {
throw new BeanPropertyException("Type of setter method \""
+ m_strSetName + "\" and getter method \""
+ m_strGetName + "\" of class \"" + cBean.getName()
+ "\" do not match.");
}
if (type != null)
m_cType = type;
else if (cGetType != null)
m_cType = cGetType;
else
m_cType = cSetType;
// }
m_iType = getTypeCode(m_cType);
m_iNullType = getNullTypeCode(m_cType);
}
public BeanProperty(Class<?> cBean, String propertyName, boolean readable,
boolean writable, Class<?> type, Class<?>... args)
throws BeanPropertyException {
init(cBean, propertyName, readable, writable, type, args);
}
public BeanProperty(Class<?> cBean, String propertyName, boolean readable,
boolean writable) throws BeanPropertyException {
init(cBean, propertyName, readable, writable, null);
}
/**
* 初始化
*
* @param cBean
* 对应Bean的类型
* @param fieldName
* 如果该属性是通过字段去访问的,则为字段名称,否则应设置为null 如果该参数不为空,则忽略下面两个参数
* @param getName
* 如果该属性可通过get方法去访问,则为方法名称,否则应设置为null
* @param setName
* 如果该属性可通过set方法去设置,则为方法名称,否则应设置为null
*/
public BeanProperty(Class<?> cBean, String fieldName, String getName,
String setName, Class<?>... args) throws BeanPropertyException {
if (fieldName != null && fieldName.equals(""))
fieldName = null;
if (getName != null && getName.equals(""))
getName = null;
if (setName != null && setName.equals(""))
setName = null;
m_strPropertyName = m_strFieldName = m_strGetName = m_strSetName = null;
m_f = null;
m_mGet = m_mSet = null;
if (fieldName == null && getName == null && setName == null)
throw new BeanPropertyException(
"Field name or setter method name or getter method name not specified.");
m_cType = null;
m_iType = 0;
if (fieldName != null) { // 属性字段
m_strFieldName = fieldName;
try {
m_f = cBean.getField(m_strFieldName);
} catch (NoSuchFieldException e) {
throw new BeanPropertyException("Field \"" + m_strFieldName
+ "\" not exist in class \"" + cBean.getName() + "\"");
}
m_cType = m_f.getType();
} else { // 属性方法
m_strFieldName = null;
Method[] methods = cBean.getMethods();
Class<?>[] params;
Class<?> cGetType = null, cSetType = null;
// Get方法
if (getName != null) {
m_strGetName = getName;
m_mGet = getMethodByName(methods, m_strGetName);
if (m_mGet == null)
throw new BeanPropertyException("Getter method \""
+ m_strGetName + "\" not exist in class \""
+ cBean.getName() + "\".");
// {检查Get方法所带参数,并获取Get方法的返回值类型
params = m_mGet.getParameterTypes();
if (params.length != (args == null ? 0 : args.length))
throw new BeanPropertyException("Getter method \""
+ m_strGetName + "\" of class \"" + cBean.getName()
+ "\" has wrong number of parameters.");
if (args != null)
for (int i = 0; i < params.length; i++)
if (!params[i].isAssignableFrom(args[i]))
throw new BeanPropertyException("Getter method \""
+ m_strGetName + "\" of class \""
+ cBean.getName()
+ "\" has wrong parameter types.");
cGetType = m_mGet.getReturnType();
// }
}
// Set方法
if (setName != null) {
m_strSetName = setName;
m_mSet = getMethodByName(methods, m_strSetName);
if (m_mSet == null)
throw new BeanPropertyException("Setter method \""
+ m_strSetName + "\" not exist in class \""
+ cBean.getName() + "\".");
// {Set方法的参数类型
params = m_mSet.getParameterTypes();
if (params.length != (1 + (args == null ? 0 : args.length)))
throw new BeanPropertyException("Setter method \""
+ m_strSetName + "\" of class \"" + cBean.getName()
+ "\" has wrong number of parameters.");
if (args != null)
for (int i = 0; i < args.length; i++)
if (!params[i].isAssignableFrom(args[i]))
throw new BeanPropertyException("Setter method \""
+ m_strSetName + "\" of class \""
+ cBean.getName()
+ "\" has wrong parameter types.");
cSetType = params[params.length - 1];
// }
}
if (cGetType != null && cSetType != null)
if (!java.io.InputStream.class.isAssignableFrom(cGetType)
&& !java.sql.Blob.class.isAssignableFrom(cSetType))
if (!cSetType.equals(cGetType))
throw new BeanPropertyException(
"Type of setter method \"" + m_strSetName
+ "\" and getter method \""
+ m_strGetName + "\" of class \""
+ cBean.getName() + "\" do not match.");
if (cGetType != null)
m_cType = cGetType;
else
m_cType = cSetType;
}
m_iType = getTypeCode(m_cType);
m_iNullType = getNullTypeCode(m_cType);
}
/**
* 获取属性名称
*/
public String getPropertyName() {
return m_strPropertyName;
}
/**
* 获取属性类型
*
* @return Class 属性类型
*/
public Class<?> getType() {
return m_cType;
}
/**
* 获取属性类型编号
*
* @return int 属性类型编号
*/
public int getTypeCode() {
return m_iType;
}
public int getNullTypeCode() {
return m_iNullType;
}
/**
* 获取属性对应的字段名称
*/
public String getFieldName() {
if (m_strFieldName == null)
return "";
return m_strFieldName;
}
/**
* 获取属性对应的Get方法名称
*/
public String getGetMethodName() {
if (m_strGetName == null)
return "";
return m_strGetName;
}
/**
* 获取属性对应的Set方法名称
*/
public String getSetMethodName() {
if (m_strSetName == null)
return "";
return m_strSetName;
}
/**
* 获取属性名称。 如果属性对应字段,则返回字段名称,否则返回[get 方法名称]|[set 方法名称]
*/
public String getName() {
if (m_strFieldName != null)
return m_strFieldName;
String str;
if (m_strGetName != null)
str = m_strGetName + "()|";
else
str = "|";
if (m_strSetName != null)
return str + m_strSetName;
return str;
}
/**
* 获取属性值
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws BeanPropertyException
*/
public Object get(Object obj, Object... args)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, BeanPropertyException,
NoSuchMethodException {
if (m_f != null)
return m_f.get(obj);
if (m_mGet != null)
if (args == null || args.length == 0)
return m_mGet.invoke(obj);
else
return m_mGet.invoke(obj, args);
throw new BeanPropertyException("Try to read write-only property.");
}
public static Object convert(Object val, int type, boolean[] noValue)
throws SQLException {
boolean bNoValue = false;
if (val == null) {
switch (type) {
case SHORT:
val = new Short((short) 0);
break;
case INTEGER:
val = new Integer(0);
break;
case LONG:
val = new Long(0l);
break;
case FLOAT:
val = new Float(0.0f);
break;
case DOUBLE:
val = new Double(0.0d);
break;
case BOOLEAN:
val = new Boolean(false);
break;
}
} else if (val instanceof String) {
switch (type) {
case SHORT:
if (val.equals(""))
bNoValue = true;
else
val = new Short((String) val);
break;
case INTEGER:
if (val.equals(""))
bNoValue = true;
else
val = new Integer(((String) val).replaceAll(",", ""));
break;
case LONG:
if (val.equals(""))
bNoValue = true;
else
val = new Long(((String) val).replaceAll(",", ""));
break;
case FLOAT:
if (val.equals(""))
bNoValue = true;
else
val = new Float(((String) val).replaceAll(",", ""));
break;
case DOUBLE:
if (val.equals(""))
bNoValue = true;
else
val = new Double(((String) val).replaceAll(",", ""));
break;
case BOOLEAN:
if (val.equals(""))
val = false;
else
val = new Boolean(
(new Integer((String) val)).intValue() != 0);
break;
}
} else if (type == BOOLEAN) {
if (val instanceof Short)
val = new Boolean(((Short) val).shortValue() != 0);
else if (val instanceof Integer)
val = new Boolean(((Integer) val).shortValue() != 0);
else if (val instanceof Long)
val = new Boolean(((Long) val).shortValue() != 0);
else if (val instanceof BigDecimal)
val = new Boolean(((BigDecimal) val).shortValue() != 0);
} else if (type == SHORT) {
if (val instanceof Integer)
val = new Short(((Integer) val).shortValue());
else if (val instanceof Long)
val = new Short(((Long) val).shortValue());
else if (val instanceof String)
val = new Short((short) Integer.parseInt((String) val));
else if (val instanceof BigDecimal)
val = new Short(((BigDecimal) val).shortValue());
} else if (type == INTEGER) {
if (val instanceof Long)
val = new Integer(((Long) val).intValue());
else if (val instanceof String)
val = new Integer(Integer.parseInt((String) val));
else if (val instanceof BigDecimal)
val = new Integer(((BigDecimal) val).intValue());
} else if (type == LONG) {
if (val instanceof String)
val = new Long(Long.parseLong((String) val));
else if (val instanceof BigDecimal)
val = new Long(((BigDecimal) val).longValue());
} else if (type == FLOAT) {
if (val instanceof Long)
val = new Float(((Long) val).longValue());
else if (val instanceof String)
val = new Float(Float.parseFloat((String) val));
else if (val instanceof Double)
val = new Float(((Double) val).floatValue());
else if (val instanceof BigDecimal)
val = new Float(((BigDecimal) val).floatValue());
} else if (type == DOUBLE) {
if (val instanceof Long)
val = new Double(((Long) val).longValue());
else if (val instanceof String)
val = new Double(Double.parseDouble((String) val));
else if (val instanceof Float)
val = new Double(((Float) val).floatValue());
else if (val instanceof BigDecimal)
val = new Double(((BigDecimal) val).doubleValue());
} else if (type == DATE) {
if (val instanceof java.util.Date)
val = new java.sql.Date(((java.util.Date) val).getTime());
} else if (type == TIMESTAMP) {
if (!(val instanceof java.sql.Timestamp)
&& val instanceof java.util.Date)
val = new java.sql.Timestamp(((java.util.Date) val).getTime());
} else if (type == STRING) {
val = val.toString();
}
noValue[0] = bNoValue;
return val;
}
/**
* 设置属性值
*
* @throws SQLException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws BeanPropertyException
*/
public void set(Object obj, Object val, Object... args)
throws SQLException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
BeanPropertyException, NoSuchMethodException {
boolean noValue[] = new boolean[1];
val = convert(val, getTypeCode(), noValue);
if (noValue[0])
return;
if (m_f != null) {
m_f.set(obj, val);
return;
}
if (m_mSet != null) {
if (args == null || args.length == 0)
m_mSet.invoke(obj, val);
else {
Object[] all = new Object[args.length + 1];
for (int i = 0; i < args.length; i++)
all[i] = args[i];
all[all.length - 1] = val;
m_mSet.invoke(obj, all);
}
return;
}
throw new BeanPropertyException("Try to write read-only property.");
}
/**
* 判断属性是否为数值型
*/
public boolean isNum() {
return (getTypeCode() == SHORT || getTypeCode() == INTEGER || getTypeCode() == LONG);
}
/**
* 判断属性是否为可读写
*/
public boolean isReadWrite() {
if (m_f != null)
return true;
if (m_mSet != null && m_mGet != null)
return true;
return false;
}
/**
* 判断属性是否为只读
*/
public boolean isReadOnly() {
if (m_f != null)
return false;
if (m_mSet != null)
return false;
return true;
}
/**
* 判断属性是否为只写
*/
public boolean isWriteOnly() {
if (m_f != null)
return false;
if (m_mGet != null)
return false;
return true;
}
/**
* 获取数值型的属性值
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws BeanPropertyException
*/
public long getNum(Object obj) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
BeanPropertyException, NoSuchMethodException {
switch (getTypeCode()) {
case SHORT:
if (m_f != null)
return (long) m_f.getShort(obj);
if (m_mGet != null)
return ((Short) m_mGet.invoke(obj, EMPTYOBJECTARRAY))
.shortValue();
break;
case INTEGER:
if (m_f != null)
return (long) m_f.getInt(obj);
if (m_mGet != null)
return ((Integer) m_mGet.invoke(obj, EMPTYOBJECTARRAY))
.intValue();
break;
case LONG:
if (m_f != null)
return m_f.getLong(obj);
if (m_mGet != null)
return ((Long) m_mGet.invoke(obj, EMPTYOBJECTARRAY))
.longValue();
break;
default:
throw new BeanPropertyException("Property is not numeric.");
}
throw new BeanPropertyException("Try to read write-only property.");
}
/**
* 获取数值型的属性值
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws BeanPropertyException
*/
public void setNum(Object obj, long val) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
BeanPropertyException, NoSuchMethodException {
switch (getTypeCode()) {
case SHORT:
if (m_f != null) {
m_f.setShort(obj, (short) val);
return;
}
if (m_mSet != null) {
m_mSet.invoke(obj, new Object[] { new Short((short) val) });
return;
}
break;
case INTEGER:
if (m_f != null) {
m_f.setInt(obj, (int) val);
return;
}
if (m_mSet != null) {
m_mSet.invoke(obj, new Object[] { new Integer((int) val) });
return;
}
break;
case LONG:
if (m_f != null) {
m_f.setLong(obj, val);
return;
}
if (m_mSet != null) {
m_mSet.invoke(obj, new Object[] { new Long(val) });
return;
}
break;
default:
throw new BeanPropertyException("Property is not numeric.");
}
throw new BeanPropertyException("Try to write read-only property.");
}
}