Created
January 8, 2014 02:00
-
-
Save yongchun/8310436 to your computer and use it in GitHub Desktop.
自动化测试原型
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.snda.sysdev.util; | |
import com.snda.sysdev.template.bean.InterfaceFuncParam; | |
import org.springframework.beans.BeanUtils; | |
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; | |
import java.beans.PropertyDescriptor; | |
import java.lang.reflect.*; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.Map; | |
/** | |
* 对于一个JavaBean其属性类型可能有一下几种 <br/> | |
* 1.原生类型及其包装类/String<br/> | |
* 2.包装类的集合如List<Integer>/数组/List<String>/String[]<br/> | |
* 3.JavaBean的集合类型如List<JavaBean><br/> | |
* 4.JavaBean类型<br/> | |
* 5.Map<String,Object>类型<br/> | |
* 6.JavaBean的数组类型JavaBean[] 这些都可能递归出现 | |
* */ | |
public class ClassProperty2KeyUtil { | |
public static void getKey(Class<?> parameterType, | |
InterfaceFuncParam keyDesc, List<InterfaceFuncParam> kds) { | |
PropertyDescriptor[] pds = BeanUtils | |
.getPropertyDescriptors(parameterType); // @RequestBody 对应的参数 | |
for (PropertyDescriptor pd : pds) { | |
if ("class".equals(pd.getName())) { // TODO | |
continue; | |
} | |
String propertyName = pd.getName(); // 属性名称 | |
Method propertyWriter = pd.getWriteMethod(); // 获取属性的写方法 | |
Type[] paramTypes = null; | |
if (propertyWriter != null) { | |
paramTypes = propertyWriter.getGenericParameterTypes(); | |
} | |
if (paramTypes == null || paramTypes.length != 1) { | |
continue; | |
} | |
Integer type = getTypeCategory(paramTypes[0]); | |
InterfaceFuncParam param = new InterfaceFuncParam(propertyName, | |
Boolean.FALSE, getTypeName(paramTypes[0]), type); | |
; | |
if (TypeCategory.TC_SIMPLE.getValue() == type // 1.原生类型及其包装类(包括String及其Void) | |
|| TypeCategory.TC_SIMPLE_COLLECTION.getValue() == type) { // 2.原生类型及其包装类(包括String及其Void)的数组和集合 | |
Class<?> propertyType = null; | |
if (paramTypes[0] instanceof Class) { | |
propertyType = (Class<?>) paramTypes[0]; | |
} else { | |
propertyType = ((ParameterizedTypeImpl) paramTypes[0]) | |
.getRawType();// 对集合类的处理 | |
} | |
param = new InterfaceFuncParam(propertyName, Boolean.FALSE, | |
getTypeName(paramTypes[0]), type); | |
getPropertyKey(propertyType, param, kds, type); | |
} else if (TypeCategory.TC_COMPLEX.getValue() == type) { // 3.JavaBean的集合 | |
StringBuilder sb = new StringBuilder(); | |
ParameterizedType pt = (ParameterizedType) paramTypes[0]; | |
Type elemType = null; | |
if (Collection.class.isAssignableFrom((Class<?>) pt | |
.getRawType())) { // pt.getRawType()返回表示声明此类型的类或接口 | |
elemType = pt.getActualTypeArguments()[0]; | |
} | |
Class<?> propertyType = (Class<?>) elemType; | |
getPropertyKey(propertyType, param, kds, type); | |
getJsonStringProxy(param, sb); | |
param.setJsonString(sb.toString()); | |
} else if (TypeCategory.TC_BEAN.getValue() == type) { // 4.JavaBean | |
StringBuilder sb = new StringBuilder(); | |
Class<?> propertyType = (Class<?>) paramTypes[0]; | |
getPropertyKey(propertyType, param, kds, type); | |
getJsonStringProxy(param, sb); | |
param.setJsonString(sb.toString()); | |
} else if (TypeCategory.TC_MAP.getValue() == type) {// 5.Map类型 | |
StringBuilder sb = new StringBuilder(); | |
getPropertyKey(Map.class, param, kds, type); | |
getJsonStringProxy(param, sb); | |
param.setJsonString(sb.toString()); | |
} else if (TypeCategory.TC_BEAN_ARRAY.getValue() == type) {// 6.JavaBean类型的数组 | |
Class<?> propertyType = (Class<?>) paramTypes[0]; | |
Class<?> elemClass = propertyType.getComponentType();// 获取数组的类型 | |
StringBuilder sb = new StringBuilder(); | |
getPropertyKey(elemClass, param, kds, type); | |
getJsonStringProxy(param, sb); | |
param.setJsonString(sb.toString()); | |
} | |
addKeyDesc(keyDesc, param, kds); | |
} | |
} | |
/** | |
* 该方法是判断将target添加到kds里还是添加到source.children里 | |
* */ | |
private static void addKeyDesc(InterfaceFuncParam source, | |
InterfaceFuncParam target, List<InterfaceFuncParam> kds) { | |
StringBuilder jsonSting = null; | |
if (source == null) { | |
kds.add(target); | |
} else { | |
if (source.getChildren() == null) { | |
source.setChildren(new ArrayList<InterfaceFuncParam>()); | |
source.getChildren().add(target); | |
} else { | |
source.getChildren().add(target); | |
} | |
} | |
} | |
/** | |
* 获取属性相应的key | |
* */ | |
private static void getPropertyKey(Class<?> parameterType, | |
InterfaceFuncParam keyDesc, List<InterfaceFuncParam> kds, | |
Integer type) { | |
keyDesc.setTypeCategory(type); | |
if (TypeCategory.TC_COMPLEX.getValue() == type) { | |
getKey(parameterType, keyDesc, kds); | |
} else if (TypeCategory.TC_BEAN.getValue() == type) { | |
getKey(parameterType, keyDesc, kds); | |
} else if (TypeCategory.TC_BEAN_ARRAY.getValue() == type) { | |
getKey(parameterType, keyDesc, kds); | |
} | |
} | |
public static int getTypeCategory(Type type) { | |
if (type instanceof Class) { | |
Class<?> clazz = (Class<?>) type; | |
if (isSimpleClass(clazz)) {// 1.原生类型及其包装类(包括String及其Void) | |
return TypeCategory.TC_SIMPLE.getValue(); | |
} | |
Class<?> elemClass = clazz.getComponentType();// 获取数组的类型 | |
if ((elemClass != null) && isSimpleClass(elemClass)) {// 2.原生类型及其包装类(包括String及其Void)的数组 | |
return TypeCategory.TC_SIMPLE_COLLECTION.getValue(); | |
} | |
if ((elemClass != null) && !isSimpleClass(elemClass)) {// 6.JavaBean类型的数组 | |
return TypeCategory.TC_BEAN_ARRAY.getValue(); | |
} | |
return TypeCategory.TC_BEAN.getValue();// 4.JavaBean | |
} | |
Type elemType = null; | |
if (type instanceof GenericArrayType) { | |
elemType = ((GenericArrayType) type).getGenericComponentType(); | |
} else if (type instanceof ParameterizedType) { // 参数化类型 | |
// 如Collection<String> | |
ParameterizedType pt = (ParameterizedType) type; | |
if (Collection.class.isAssignableFrom((Class<?>) pt.getRawType())) { // pt.getRawType()返回表示声明此类型的类或接口 | |
elemType = pt.getActualTypeArguments()[0]; | |
} | |
if (Map.class.isAssignableFrom((Class<?>) pt.getRawType())) {// 5.Map类型 | |
return TypeCategory.TC_MAP.getValue(); | |
} | |
} | |
if (elemType != null) { | |
if (elemType instanceof Class && isSimpleClass((Class<?>) elemType)) {// 2.原生类型及其包装类(包括String及其Void)的集合 | |
return TypeCategory.TC_SIMPLE_COLLECTION.getValue(); | |
} | |
if (elemType instanceof WildcardType) { | |
WildcardType wt = (WildcardType) elemType; | |
// upperBounds never get zero length | |
Type[] upperBounds = wt.getUpperBounds(); | |
Type[] lowerBounds = wt.getLowerBounds(); | |
if ((upperBounds.length == 1) | |
&& (upperBounds[0] == Object.class) | |
&& (lowerBounds.length == 1) | |
&& lowerBounds[0] instanceof Class | |
&& isSimpleClass((Class<?>) lowerBounds[0])) { | |
return TypeCategory.TC_SIMPLE_COLLECTION.getValue(); | |
} | |
} | |
} | |
return TypeCategory.TC_COMPLEX.getValue(); // 3.JavaBean的集合 | |
} | |
public static boolean isSimpleClass(Class<?> clazz) { | |
return (clazz.isPrimitive() || (clazz == Boolean.class) | |
|| (clazz == Character.class) || (clazz == Byte.class) | |
|| (clazz == Short.class) || (clazz == Integer.class) | |
|| (clazz == Long.class) || (clazz == Float.class) | |
|| (clazz == Double.class) || (clazz == Void.class) || (clazz == String.class)); | |
} | |
public static String getTypeName(Type type) { | |
if (type instanceof Class) { | |
return ((Class<?>) type).getSimpleName(); | |
} | |
int i; | |
StringBuilder sb = new StringBuilder(); | |
if (type instanceof GenericArrayType) { | |
sb.append(getTypeName(((GenericArrayType) type) | |
.getGenericComponentType())); | |
sb.append("[]"); | |
} else if (type instanceof ParameterizedType) { | |
ParameterizedType pt = (ParameterizedType) type; | |
sb.append(((Class<?>) pt.getRawType()).getSimpleName()); | |
Type[] typeArguments = pt.getActualTypeArguments(); | |
if (typeArguments.length > 0) { | |
sb.append('<'); | |
for (i = 0; i < typeArguments.length; ++i) { | |
sb.append(getTypeName(typeArguments[i])); | |
sb.append(", "); | |
} | |
sb.setLength(sb.length() - 2); // delete last ", " | |
sb.append('>'); | |
} | |
} else if (type instanceof TypeVariable) { | |
TypeVariable<?> tv = (TypeVariable<?>) type; | |
sb.append(tv.getName()); | |
Type[] bounds = tv.getBounds(); | |
if ((bounds.length > 1) || (bounds[0] != Object.class)) { | |
sb.append(" extends "); | |
for (i = 0; i < bounds.length; ++i) { | |
sb.append(getTypeName(bounds[i])); | |
sb.append(" & "); | |
} | |
sb.setLength(sb.length() - 3); // delete last " & " | |
} | |
} else if (type instanceof WildcardType) { | |
sb.append('?'); | |
WildcardType wt = (WildcardType) type; | |
Type[] upperBounds = wt.getUpperBounds(); | |
if ((upperBounds.length > 1) || (upperBounds[0] != Object.class)) { | |
sb.append(" extends "); | |
for (i = 0; i < upperBounds.length; ++i) { | |
sb.append(getTypeName(upperBounds[i])); | |
sb.append(" & "); | |
} | |
sb.setLength(sb.length() - 3); // delete last " & " | |
} | |
Type[] lowerBounds = wt.getLowerBounds(); | |
if (lowerBounds.length > 0) { | |
sb.append(" super "); | |
for (i = 0; i < lowerBounds.length; ++i) { | |
sb.append(getTypeName(lowerBounds[i])); | |
sb.append(" & "); | |
} | |
sb.setLength(sb.length() - 3); // delete last " & " | |
} | |
} | |
return sb.toString(); | |
} | |
public static void getJsonStringProxy(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
if (TypeCategory.TC_SIMPLE_COLLECTION.getValue() == keyDesc | |
.getTypeCategory()) { // 数组 | |
getSimpleCollectionJsonString(keyDesc, sb); | |
} | |
if (TypeCategory.TC_BEAN_ARRAY.getValue() == keyDesc.getTypeCategory()) { | |
getBeanArrayJsonString(keyDesc, sb); | |
} | |
if (TypeCategory.TC_MAP.getValue() == keyDesc.getTypeCategory()) { // Map | |
getMapJsonString(keyDesc, sb); | |
} | |
if (TypeCategory.TC_BEAN.getValue() == keyDesc.getTypeCategory()) { // JavaBean | |
getBeanJsonString(keyDesc, sb); | |
} | |
if (TypeCategory.TC_COMPLEX.getValue() == keyDesc.getTypeCategory()) { // List<JavaBean> | |
getComplexJsonString(keyDesc, sb); | |
} | |
} | |
private static void getSimpleJsonString(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\""); | |
sb.append(":"); | |
sb.append("\"\""); | |
} | |
private static void getSimpleCollectionJsonString( | |
InterfaceFuncParam keyDesc, StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\":").append("[]"); | |
} | |
private static void getComplexJsonString(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\":").append("[{"); | |
int i = 0; | |
int size = keyDesc.getChildren().size(); | |
for (InterfaceFuncParam kd : keyDesc.getChildren()) { | |
++i; | |
if (TypeCategory.TC_SIMPLE.getValue() == kd.getTypeCategory()) { | |
getSimpleJsonString(kd, sb); | |
} else { | |
getJsonStringProxy(kd, sb); | |
} | |
if (i < size) { | |
sb.append(","); | |
} | |
} | |
sb.append("}]"); | |
} | |
private static void getBeanJsonString(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\":").append("{"); | |
int i = 0; | |
int size = keyDesc.getChildren().size(); | |
for (InterfaceFuncParam kd : keyDesc.getChildren()) { | |
++i; | |
if (TypeCategory.TC_SIMPLE.getValue() == kd.getTypeCategory()) { | |
getSimpleJsonString(kd, sb); | |
} else { | |
getJsonStringProxy(kd, sb); | |
} | |
if (i < size) { | |
sb.append(","); | |
} | |
} | |
sb.append("}"); | |
} | |
private static void getMapJsonString(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\":").append("{}"); | |
} | |
private static void getBeanArrayJsonString(InterfaceFuncParam keyDesc, | |
StringBuilder sb) { | |
sb.append("\"").append(keyDesc.getName()).append("\":").append("[{"); | |
int i = 0; | |
int size = keyDesc.getChildren().size(); | |
for (InterfaceFuncParam kd : keyDesc.getChildren()) { | |
++i; | |
if (TypeCategory.TC_SIMPLE.getValue() == kd.getTypeCategory()) { | |
getSimpleJsonString(kd, sb); | |
} else { | |
getJsonStringProxy(kd, sb); | |
} | |
if (i < size) { | |
sb.append(","); | |
} | |
} | |
sb.append("}]"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.snda.sysdev.template.bean; | |
import java.util.List; | |
public class InterfaceFuncParam { | |
private String name; | |
private Boolean required; | |
private String typeName; | |
private int typeCategory; | |
private List<InterfaceFuncParam> children; | |
private String jsonString; | |
public InterfaceFuncParam(String name, Boolean required, String typeName, | |
Integer typeCategory) { | |
this.name = name; | |
this.required = required; | |
this.typeName = typeName; | |
this.typeCategory = typeCategory; | |
} | |
public String getName() { | |
return name; | |
} | |
public Boolean getRequired() { | |
return required; | |
} | |
public String getTypeName() { | |
return typeName; | |
} | |
public int getTypeCategory() { | |
return typeCategory; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public void setRequired(Boolean required) { | |
this.required = required; | |
} | |
public void setTypeName(String typeName) { | |
this.typeName = typeName; | |
} | |
public void setTypeCategory(int typeCategory) { | |
this.typeCategory = typeCategory; | |
} | |
public List<InterfaceFuncParam> getChildren() { | |
return children; | |
} | |
public void setChildren(List<InterfaceFuncParam> children) { | |
this.children = children; | |
} | |
public String getJsonString() { | |
return jsonString; | |
} | |
public void setJsonString(String jsonString) { | |
this.jsonString = jsonString; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.snda.sysdev.util; | |
/** | |
* Created with IntelliJ IDEA. User: chengyongchun Date: 14-1-2 Time: 下午6:13 To | |
* change this template use File | Settings | File Templates. | |
*/ | |
public enum TypeCategory { | |
TC_SIMPLE(1), TC_SIMPLE_COLLECTION(2), TC_COMPLEX(3), TC_BEAN(4),TC_MAP(5),TC_BEAN_ARRAY(6); | |
private Integer value; | |
private TypeCategory(Integer value) { | |
this.value = value; | |
} | |
public Integer getValue() { | |
return this.value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment