package cn.org.rapid_framework.test.util;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import org.springframework.beans.BeanUtils;
/**
* 用于为Bean设置属性设置默认值的工具类.
* 示例应用场景:
* 1.BeanUtils.copyProperties()的测试,如我们需要验证某个属性值是否有拷贝正确.
* 这时可以为Bean设置属性值,然后copyProperties(),再验证copy完成后的结果.验证可以使用工具类:BeanAssert
*
*
* 示例使用:<br />
* UserBean bean = BeanDefaultValueUtils.setBeanProperties(new UserBean());
*
* <pre>
* <b>相关默认值:</b>
*
* 数字类型: 1
* 日期类型: 当前时间
* boolean: true
* enum类型: Enum.values()[0]
* </pre>
* @author badqiu
*
*/
public class BeanDefaultValueUtils {
public static int DEFAULT_VALUE = 1;
//TODO 增加对范型 List<String>及 setFields()
public static <T> T setBeanProperties(T obj) {
return setBeanProperties(obj, DEFAULT_VALUE);
}
public static <T> T setBeanProperties(T obj,int defaultValue) {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(obj.getClass());
for(int i = 0; i < descriptors.length; i++ ) {
String name = descriptors[i].getName();
Method writeMethod = descriptors[i].getWriteMethod();
if (writeMethod != null) {
for(Class parameterType : writeMethod.getParameterTypes()) {
Object value = null;
try {
value = getDefaultValue0(parameterType,defaultValue);
writeMethod.setAccessible(true);
writeMethod.invoke(obj, value);
}catch(Exception e) {
throw new IllegalArgumentException("cannot set property:"+name+" with default value:"+value,e);
}
}
}
}
return obj;
}
public static Object getDefaultValue(Class<?> targetType) {
return getDefaultValue(targetType,DEFAULT_VALUE);
}
private static Object getDefaultValue(Class<?> targetType,int defaultValue){
try {
return getDefaultValue0(targetType, defaultValue);
}catch(Exception e) {
throw new IllegalArgumentException("cannot generate default value for targetType:"+targetType);
}
}
private static Object getDefaultValue0(Class<?> targetType, int defaultValue)
throws IllegalAccessException, InvocationTargetException {
if(targetType.isArray()) {
Class<?> componentType = targetType.getComponentType();
Object array = java.lang.reflect.Array.newInstance(componentType, 1);
java.lang.reflect.Array.set(array, 0, getDefaultValue(componentType,defaultValue));
return array;
}
if(targetType == String.class) {
return String.valueOf(defaultValue);
}
if(targetType == char.class) {
return String.valueOf(defaultValue).charAt(0);
}
if(targetType == Byte.class || targetType == byte.class) {
return (byte)defaultValue;
}
if(targetType == Short.class || targetType == short.class) {
return (short)defaultValue;
}
if(targetType == Integer.class || targetType == int.class) {
return (int)defaultValue;
}
if(targetType == Long.class || targetType == long.class) {
return (long)defaultValue;
}
if(targetType == Float.class || targetType == float.class) {
return (float)defaultValue;
}
if(targetType == Double.class || targetType == double.class) {
return (double)defaultValue;
}
if(targetType == BigDecimal.class) {
return new BigDecimal(defaultValue);
}
if(targetType == BigInteger.class) {
return BigInteger.valueOf(defaultValue);
}
if(targetType == Boolean.class || targetType == boolean.class) {
return true;
}
if(targetType == java.util.Date.class) {
return new Date();
}
if(targetType == java.sql.Date.class) {
return new java.sql.Date(System.currentTimeMillis());
}
if(targetType == java.sql.Time.class) {
return new java.sql.Time(System.currentTimeMillis());
}
if(targetType == java.sql.Timestamp.class) {
return new java.sql.Timestamp(System.currentTimeMillis());
}
if(targetType == Calendar.class) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
return calendar;
}
if(targetType == Currency.class) {
return Currency.getInstance(Locale.getDefault());
}
if(targetType == Locale.class) {
return Locale.getDefault();
}
if(targetType.isEnum()) {
Enum[] enums = (Enum[])targetType.getEnumConstants();;
return enums != null && enums.length > 0 ? enums[0] : null;
}
if(targetType.isInterface()) {
if(targetType.isAssignableFrom(Set.class)) {
return new HashSet();
}
if(targetType.isAssignableFrom(List.class)) {
return new ArrayList();
}
if(targetType.isAssignableFrom(Collection.class)) {
return new ArrayList();
}
if(targetType.isAssignableFrom(Map.class)) {
return new HashMap();
}
if(targetType.isAssignableFrom(Queue.class)) {
return (Queue)new ArrayBlockingQueue(100);
}
if(targetType.isAssignableFrom(Iterator.class)) {
return (Iterator)new ArrayList();
}
if(targetType.isAssignableFrom(Iterable.class)) {
return (Iterable)new ArrayList();
}
return null;
}
return newInstanceByConstructors(targetType, defaultValue);
}
private static Object newInstanceByConstructors(Class<?> targetType,
int defaultValue) {
Constructor[] cs = targetType.getConstructors();
Arrays.sort(cs,new Comparator<Constructor>() {
public int compare(Constructor o1, Constructor o2) {
return o2.getParameterTypes().length - o1.getParameterTypes().length;
}
});
for(Constructor c : cs) {
Object obj = newInstance(c,defaultValue);
if(obj != null) return obj;
}
return null;
}
private static Object newInstance(Constructor c,int defaultValue) {
c.setAccessible(true);
Object[] args = new Object[c.getParameterTypes().length];
for(int i = 0; i < c.getParameterTypes().length; i++) {
Class type = c.getParameterTypes()[i];
args[i] = getDefaultValue(type);
}
try {
return c.newInstance(args);
}catch(Exception e) {
//ignore
return null;
}
}
}