All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yanyun.go.service.ApiToGoTestService Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
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