com.yanyun.go.service.ApiToGoTestService Maven / Gradle / Ivy
package com.yanyun.go.service;
import com.fasterxml.classmate.ResolvedType;
import com.google.common.base.Optional;
import com.yanyun.go.utils.MethodUtils;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.service.contexts.OperationContext;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 获取Api转换为Go的测试输出
*/
public class ApiToGoTestService {
/**
* 将每一个Api文档生成一个测试文件字符串
*
* @return
*/
public StringBuffer apiToStr(OperationContext context) {
StringBuffer result = new StringBuffer();
//添加头部信息
/*result.append(generatorPackageAndImport());
result.append("\n");//换行*/
//添加接口测试描述
result.append(generatorTestInfo(context));
result.append("\n");//换行
result.append(generatorTestFunc(context));
result.append("\n");//换行
result.append(generatorStructDomain(context));
return result;
}
/**
* 生成结构体
*
* @param context
* @return
*/
private String generatorStructDomain(OperationContext context) {
List parameters = context.getParameters();
Set typeSet = new HashSet<>();
Set alreadyStruct = new HashSet<>();
for (int i = 0; i < parameters.size(); i++) {
ResolvedMethodParameter parameter = parameters.get(i);
List annotations = parameter.getAnnotations();
if (annotations != null && annotations.size()>0 && annotations.get(0) instanceof RequestBody) {
//并且有注解,且是@RequestBody
//那么该参数是需要生成的参数DTO
String typeName = parameter.getParameterType().getTypeName();
createStruct(typeName, typeSet,alreadyStruct);
}
}
StringBuffer result = new StringBuffer();
typeSet.forEach(type->{
result.append(" "+type);
});
return result.toString();
}
/**
* 生成结构体的真实代码
*
* @return
*/
private StringBuffer createStruct(String typeName, Set structSet,Set alreadyStruct) {
StringBuffer result = new StringBuffer();
alreadyStruct.add(typeName);
try {
String simpleName = typeName.substring(typeName.lastIndexOf(".") + 1);
Class> aClass = Class.forName(typeName);
result.append("\n type " + simpleName + " struct { \n");
Arrays.asList(aClass.getDeclaredFields()).forEach(field -> {
String fieldName = toCamelName(field.getName());
String fieldSimpleType = field.getType().getSimpleName();
String fieldType = field.getType().getName();
String goType = MethodUtils.JavaTypeToGoType(fieldSimpleType);
if ("unknown".equalsIgnoreCase(goType)) {
//判断是否是数组
if (MethodUtils.isArrayType(fieldSimpleType)) {
if (MethodUtils.isSimpleArrayType(fieldSimpleType)) {
//如果是简单数组
String substring = fieldSimpleType.substring(0, fieldSimpleType.indexOf("["));
result.append("\n " + fieldName + " []" + MethodUtils.JavaTypeToGoType(substring) + " `json:\"" + field.getName() + "\"`");
} else {
//如果是DTO数组
result.append("\n " + fieldName + " []" + fieldSimpleType.substring(0,fieldSimpleType.indexOf("[")) + " `json:\"" + field.getName() + "\"`");
//并且DTO对象也要进行createStruct
String name = field.getType().componentType().getName();
if (name.contains("com.yanyun")){
if (!alreadyStruct.contains(name)){
createStruct(name, structSet,alreadyStruct);
}
}
}
} else if (MethodUtils.isCollectionType(fieldType)) {
//如果是集合 List/Set的简单集合
Type genericType = field.getGenericType();
if (genericType != null && genericType instanceof ParameterizedType) {
//如果有泛型,那么按照泛型进行分析
ParameterizedType pType = (ParameterizedType) genericType;
Type[] actualTypeArguments = pType.getActualTypeArguments();
if (actualTypeArguments != null && actualTypeArguments.length > 0) {
//取第一个泛型类
Type actualTypeArgument = actualTypeArguments[0];
//获取类型
String argumentType = actualTypeArgument.getTypeName();
if (argumentType.contains("java.util") && (argumentType.contains("List") || argumentType.contains("Set"))) {
//如果泛型中依旧包含集合,此处只允许二级集合
String substring = argumentType.substring(argumentType.indexOf("<") + 1);
String truthStr = substring.substring(0, substring.indexOf(">"));
String truthSimpleName = truthStr.substring(truthStr.lastIndexOf(".") + 1);
if (isSimpleType(truthSimpleName)) {
String go_Type = MethodUtils.JavaTypeToGoType(truthSimpleName);
result.append("\n " + fieldName + " [][]" + go_Type + " `json:\"" + go_Type + "\"`");
} else {
//否则不是简单类型
if (truthStr.contains("com.yanyun")){
try {
Class> a_Class = Class.forName(truthStr);
//不是简单类型则进行递归调用
if (!alreadyStruct.contains(a_Class.getName())){
createStruct(a_Class.getName(), structSet,alreadyStruct);
}
//拼装Result
result.append("\n " + fieldName + " [][]" + truthSimpleName + " `json:\"" + field.getName() + "\"`");
} catch (ClassNotFoundException e) {
//e.printStackTrace();
//出现异常的话,将Field类型写上去
result.append("\n " + fieldName + " [][]" + truthSimpleName + " `json:\"" + truthSimpleName + "\"`");
}
}
}
} else {
if (actualTypeArgument.getTypeName().contains("com.yanyun") ){
Class a_Class = (Class) actualTypeArgument;
if (isSimpleType(a_Class.getName())) {
//如果是普通类型
String go_Type = MethodUtils.JavaTypeToGoType(a_Class.getSimpleName());
result.append("\n " + fieldName + " " + go_Type + " `json:\"" + field.getName() + "\"`");
} else {
//不是普通类型
result.append("\n " + fieldName + " []" + a_Class.getSimpleName() + " `json:\"" + field.getName() + "\"`");
//泛型承载的参数
if (!alreadyStruct.contains(a_Class.getName())){
createStruct(a_Class.getName(), structSet,alreadyStruct);
}
}
}
}
}
} else {
//如果没有泛型,按照Object类型进行分析
result.append("\n " + fieldName + " []interface" + " `json:\"" + field.getName() + "\"`");
}
}else if (MethodUtils.isMapCollection(typeName)) {
//是否是Map集合类型
//获取泛型
Type genericType = field.getGenericType();
if (genericType!=null && genericType instanceof ParameterizedType){
//如果有泛型,那么按照泛型进行分析
ParameterizedType pType = (ParameterizedType)genericType;
Type[] actualTypeArguments = pType.getActualTypeArguments();
if (actualTypeArguments!=null && actualTypeArguments.length>0){
//Map一般有2种泛型
//取第一个泛型类,并进行转换
Class a_Class = (Class) actualTypeArguments[0];
String aName = MethodUtils.JavaTypeToGoType(a_Class.getSimpleName());
if ("unknown".equalsIgnoreCase(aName)){
aName = aClass.getSimpleName();
}
//第二个泛型
Class bClass = (Class) actualTypeArguments[1];
String bName = MethodUtils.JavaTypeToGoType(bClass.getSimpleName());
if ("unknown".equalsIgnoreCase(bName)){
bName = bClass.getSimpleName();
}
//参数拼接
result.append("\n" + fieldName + " map["+aName+"]"+bName+" `json:\""+field.getName()+"\"`");
}
}
}else {
//如果全没对应上
result.append("\n " + fieldName + " " + fieldName + " `json:\"" + field.getName() + "\"`");
if (fieldType.contains("com.yanyun")){
if (!alreadyStruct.contains(fieldType)){
createStruct(fieldType, structSet,alreadyStruct);
}
}
}
}else {
result.append("\n " + fieldName + " " + goType + " `json:\"" + field.getName() + "\"`");
}
});
result.append("\n } \n");
} catch (ClassNotFoundException e) {
// e.printStackTrace();
}
structSet.add(result.toString());
return result;
}
private boolean isSimpleType(String typeName) {
boolean flag = false;
if (typeName.equalsIgnoreCase("int")
|| typeName.equalsIgnoreCase("int[]")
|| typeName.equalsIgnoreCase("java.lang.Integer")
|| typeName.equalsIgnoreCase("java.lang.Integer[]")
|| typeName.equalsIgnoreCase("byte")
|| typeName.equalsIgnoreCase("java.lang.Byte")
|| typeName.equalsIgnoreCase("byte[]")
|| typeName.equalsIgnoreCase("java.lang.Byte[]")
|| typeName.equalsIgnoreCase("long")
|| typeName.equalsIgnoreCase("java.lang.Long")
|| typeName.equalsIgnoreCase("long[]")
|| typeName.equalsIgnoreCase("java.lang.Long[]")
|| typeName.equalsIgnoreCase("double")
|| typeName.equalsIgnoreCase("java.lang.Double")
|| typeName.equalsIgnoreCase("double[]")
|| typeName.equalsIgnoreCase("java.lang.Double[]")
|| typeName.equalsIgnoreCase("float")
|| typeName.equalsIgnoreCase("java.lang.Float")
|| typeName.equalsIgnoreCase("float[]")
|| typeName.equalsIgnoreCase("java.lang.Float[]")
|| typeName.equalsIgnoreCase("char")
|| typeName.equalsIgnoreCase("java.lang.Character")
|| typeName.equalsIgnoreCase("char[]")
|| typeName.equalsIgnoreCase("java.lang.Character[]")
|| typeName.equalsIgnoreCase("short")
|| typeName.equalsIgnoreCase("java.lang.Short")
|| typeName.equalsIgnoreCase("short[]")
|| typeName.equalsIgnoreCase("java.lang.Short[]")
|| typeName.equalsIgnoreCase("boolean")
|| typeName.equalsIgnoreCase("java.lang.Boolean")
|| typeName.equalsIgnoreCase("boolean[]")
|| typeName.equalsIgnoreCase("java.lang.Boolean[]")
|| typeName.equalsIgnoreCase("java.lang.String") //增加String类型
|| typeName.equalsIgnoreCase("java.lang.String[]")
) {
//如果是基本类型,那么返回true
flag = true;
}
return flag;
}
/**
* 自动生成package和import 信息
*
* @return
*/
private String generatorPackageAndImport() {
//考虑到编译时的问题需要增加: --enable-preview的共性 未使用文本块模式处理多行文本
String package_str = "package test \n";
String import_str = "(" +
//引入的包
"\"github.com/yanyundata/woodpecker/apiUtils\" \n" +
//引入日志包
"\"log\" \n" +
//引入测试包
"\"testing\" \n" +
")";
return package_str + import_str;
}
/**
* 未每个测试方法添加测试描述
*
* @param context
* @return
*/
private String generatorTestInfo(OperationContext context) {
String header = "//测试:";
Optional annotation = context.findAnnotation(ApiOperation.class);
if (annotation.isPresent()) {
//如果在方法上做了描述,那么补充测试描述
String value = annotation.get().value();
header += value;
}
//访问路径
String requestMappingPattern = context.requestMappingPattern();
//访问方式
String methodType = context.httpMethod().name();
String optionType = "\n //访问方式:" + methodType;
//得到请求的URI
String optionPath = "\n //访问路径: " + requestMappingPattern;
return header + optionType + optionPath;
}
/**
* 自动生成方法的请求体
*
* @param context
* @return
*/
private String generatorTestFunc(OperationContext context) {
String fun_str = "func TestApi";
//获得Java方法的名称
String name = context.getName();
//驼峰式命名
String camelName = toCamelName(name);
//拼接方法名称
fun_str += camelName;
fun_str += "(t *testing.T) { \n";
//拼接方法体
fun_str += "resultdata := apiap." + generatorGoMethod(context);
//判断返回值是JSON还是String
boolean flag = resultIsJSON(context);
if (flag) {
fun_str += ".ToJson()";
} else {
fun_str += ".ToString()";
}
fun_str += "\n }";
return fun_str;
}
/**
* 生成Go调用的方法
*
* @param context
* @return
*/
private String generatorGoMethod(OperationContext context) {
return MethodUtils.getMethodApi(context);
}
/**
* 将传递的字符串进行首字母大写
*
* @param originName
* @return
*/
private String toCamelName(String originName) {
if (!StringUtils.isEmpty(originName)) {
String upperCase = originName.substring(0, 1).toUpperCase();
originName = upperCase + originName.substring(1);
}
return originName;
}
/**
* 判断 返回值是否为JSON
*
* @param context
* @return
*/
private boolean resultIsJSON(OperationContext context) {
boolean flag = true;
ResolvedType returnType = context.getReturnType();
String typeName = returnType.getTypeName();
if (typeName.equalsIgnoreCase("int")
|| typeName.equalsIgnoreCase("java.lang.Integer")
|| typeName.equalsIgnoreCase("byte")
|| typeName.equalsIgnoreCase("java.lang.Byte")
|| typeName.equalsIgnoreCase("long")
|| typeName.equalsIgnoreCase("java.lang.Long")
|| typeName.equalsIgnoreCase("double")
|| typeName.equalsIgnoreCase("java.lang.Double")
|| typeName.equalsIgnoreCase("float")
|| typeName.equalsIgnoreCase("java.lang.Float")
|| typeName.equalsIgnoreCase("char")
|| typeName.equalsIgnoreCase("java.lang.Character")
|| typeName.equalsIgnoreCase("short")
|| typeName.equalsIgnoreCase("java.lang.Short")
|| typeName.equalsIgnoreCase("boolean")
|| typeName.equalsIgnoreCase("java.lang.Boolean")
|| typeName.equalsIgnoreCase("java.lang.String") //增加String类型
) {
//如果是基本类型,那么返回false
flag = false;
}
return flag;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy