重构旧项目实体类

本文只是抛砖引玉,不能百分百确认没有错误

我们公司使用了最开始的人自己封装的数据库操作,但是效率过低,只是用了mybatis,现在想改成mybatis-plus,之前也没有swagger 现在也想使用,都是生成的get和set方法,这改成lombok,但是数据库里面并没有注释,只是在代码中写了注释,这里介绍下我重构的思路,和自己写的样本

给大家截一个图 注解都是自定义的


image.png

生成后的效果图(onlyMp = true 表示不需要远来封装的注解)

image.png

代码里面有很多没有格式化,导致取字符串的时候对字符串操作很多
再截一个图 还存在 这种注释

image.png

没有缩进的也有

image.png

接下来开始解析文件

  1. 获取所有目标文件,这个就不用贴代码了,使用字符流读取文件(最后会给所有代码)
        List<File> files = getFiles(from);
        for (File file : files) {
//            if (!file.getName().equals("TransferFormVO.java")) {
//                continue;
//            }
            TableInfo tableInfo = createTableInfo(file);
            if (tableInfo == null || tableInfo.getClassName() == null || createExclude.contains(tableInfo.getClassName())) {
                continue;
            }
            tableInfoList.add(tableInfo);
        }

重点是 createTableInfo这个方法

  1. 获取包名,导报,排除静态,get,set方法
                //包名
                if (line.startsWith("package")) {
                    tableInfo.setPackag(line.replace("package", "").replace(";", "").trim());
                }
                //导入的类
                if (line.startsWith("import")) {
                    String anImport = line.replace("import", "").replace(";", "").trim();
                    if (!anImport.isEmpty() && anImport.contains("sysenum") && !enums.isEmpty()) {
                        anImport = anImport.replace("com.caijai.base.sysenum", enums);
                    }
                    tableInfo.getImportPackage().add(anImport);
                }
                //排除静态,get set方法
                if (line.isEmpty() || line.contains("static") || line.contains("()") || line.contains("void")) {
                    continue;
                }
  1. 获取类信息,获取旧框架的注解,获取类的注释
                //获取类的信息
                if (line.contains("public class ")) {
                    String className;
                    if (line.contains("extends")) {
                        if (line.split("extends").length > 0) {
                            tableInfo.setSupper(line.substring(line.indexOf("extends"), line.indexOf("{")).replace("extends", "").trim());
                            if (tableInfo.getSupper().equals("BaseEntity")) {
                                tableInfo.setSupper("BaseTable");
                                tableInfo.getImportPackage().add("com.caijai.base.entity.BaseTable");
                            }
                        }
                        className = line.substring(line.indexOf("class"), line.indexOf("extends")).replace("class", "").trim();
                    } else {
                        className = line.substring(line.indexOf("class"), line.indexOf("{")).replace("class", "").trim();
                    }
                    tableInfo.setClassName(className);
                    continue;
                } else if (line.startsWith("@Table")) {
                    //获取表名
                    tableInfo.setTableName(line.substring(line.indexOf("\""), line.indexOf("\")")).replace("\"", ""));
                    continue;
                }
                if (tableInfo.getClassName() == null) {
                    //获取类注释
                    if ((line.startsWith("//") || line.startsWith("*") || line.startsWith("/**")) && !line.startsWith("*/")) {
                        if (line.equals("*")) {
                            tableInfo.setRemarks(tableInfo.getRemarks() + "\n");
                            continue;
                        }
                        if (tableInfo.getRemarks() != null) {
                            tableInfo.setRemarks(tableInfo.getRemarks() + "\n" + line.replace("* ", ""));
                        } else {
                            tableInfo.setRemarks(line.replace("* ", ""));
                        }
                    }
                }
  1. 如果类的信息已存在,那么接下来读的都是字段信息
                    List<TableFiled> files = tableInfo.getFiles();
                    TableFiled filed = new TableFiled();
                    if (files.isEmpty()) {
                        files.add(filed);
                    }
                    TableFiled tableFiled = files.get(files.size() - 1);
                    //判断该字段到底有没有 如果没有就用之前的,否则就添加新的
                    if (tableFiled.getProperty() != null) {
                        files.add(filed);
                    }
                    filed = files.get(files.size() - 1);
                    //字段注释
                    if ((line.startsWith("//") || line.startsWith("*") || line.startsWith("/**")) && !line.startsWith("*/")) {
                        if (line.equals("*")) {
                            filed.setRemarks(filed.getRemarks() + "\n");
                            continue;
                        }
                        if (filed.getRemarks() != null) {
                            filed.setRemarks(filed.getRemarks() + "\n" + line.replace("* ", ""));
                        } else {
                            filed.setRemarks(line.replace("* ", "").replace("/*", "").replace("*/", ""));
                        }
                    } else if (line.startsWith("@Column")) {
                        filed.setExits(true);
                        //老框架封装的数据库 保留
                        String[] primaries = line.split("=");
                        for (int i = 0; i < primaries.length; i++) {
                            String primary = primaries[i].trim();
                            if (primary.contains("primary")) {
                                filed.setPrimary(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("readonly")) {
                                filed.setExits(false);
                                filed.setReadonly(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("byInt")) {
                                filed.setByInt(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("byDouble")) {
                                filed.setByDouble(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("sort ")) {
                                filed.setSort(primaries[i + 1].trim().replace(")", ""));
                            }
                        }
                        //获取数据库对应的字段名
                        int i = line.indexOf("\",");
                        if (i != -1) {
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        } else if ((i = line.indexOf("\")")) != -1) {
                            i = line.indexOf("\")");
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        } else if ((i = line.indexOf("\" ,")) != -1) {
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        }
                    } else if (line.startsWith("@Relation")) {
                        //获取旧框架 关联查询字段
                        String[] split = line.split("=");
                        for (int i = 0; i < split.length; i++) {
                            String s = split[i].trim();
                            if (s.contains("table")) {
                                filed.setTable(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("ref")) {
                                filed.setRef(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("value")) {
                                filed.setValue(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("show")) {
                                filed.setShow(split[i + 1].trim().replace(")", "").split(",")[0]);
                            }
                        }
                        filed.setJoinTable(line.replace("table", "表名").replace("value", "关联表字段").replace("ref", "当前表字段").replace("show", "查询的字段"));
                    } else if ((line.startsWith("private") || line.startsWith("public")) && !line.contains("class")) {
                        // 修饰符 类型名称 字段名称 备注
                        line = line.replace("  ", " ").replace(" ;", ";");
                        String[] s = line.split(" ");
                        filed.setModifier(s[0].trim());
                        filed.setClassName(s[1].trim());
                        filed.setProperty(s[2].substring(0, s[2].indexOf(";")).replace("\t", ""));
                        String[] split = line.split("//");
                        if (split.length > 1) {
                            filed.setRemarks(split[1]);
                        }
                    }

获取类的数据,接下来就开始生成文件,使用的是javapoet

  1. 如果该类有继承就把继承的类找出来,不生成相同字段
        if (tableInfo.getSupper() != null) {
            classBuilder.addAnnotation(AnnotationSpec.builder(EqualsAndHashCode.class).addMember("callSuper", "true").build());
            Optional<String> first = tableInfo.getImportPackage().stream().filter(s -> s.contains(tableInfo.getSupper())).findFirst();
            info = tableInfoList.stream().filter(s -> {
                        boolean supper = s.getClassName().equals(tableInfo.getSupper());
                        boolean equals = s.getPackag().equals(first.orElse("").replace("." + s.getClassName(), ""));
                        return equals && supper;
                    }
            ).findFirst().orElse(null);
            if (first.isPresent()) {
                String replace1 = first.get().replace("." + tableInfo.getSupper(), "");
                if (changePackage) {
                    //交换包名(我起的不一样所有要改成我自己的,如果是false就是原包名)
                    String[] split = replace1.replace("com.caijai.", "").split("\\.");
                    String s = split[0];
                    String s1 = split[1];
                    StringBuilder s3 = new StringBuilder();
                    if (split.length > 2) {
                        for (int i = 2; i < split.length; i++) {
                            s3.append(".").append(split[i]);
                        }
                    }
                    replace1 = newPackage + "." + s1 + "." + s + s3.toString();
                }
                classBuilder.superclass(ClassName.get(replace1, tableInfo.getSupper()));
            }
        }
  1. 添加类注解和备注
        if (tableInfo.getTableName() != null) {
            if (!onlyMp) {
                AnnotationSpec tableSpec = AnnotationSpec.builder(ClassName.get("com.caijai.base.anno", "Table")).addMember("name", "$S", tableInfo.getTableName()).build();
                classBuilder.addAnnotation(tableSpec);
            }
            classBuilder.addAnnotation(AnnotationSpec.builder(TableName.class).addMember("value", "$S", tableInfo.getTableName()).build());
        }
        String replace = tableInfo.getRemarks();
        if (tableInfo.getRemarks() != null) {
            replace = replace.replace("\n", "");
            classBuilder.addAnnotation(AnnotationSpec.builder(ApiModel.class).addMember("description", "$S", replace).build());
            classBuilder.addJavadoc(tableInfo.getRemarks());
        }
  1. swagger注解
//字段
            FieldSpec.Builder filedBuilder = FieldSpec.builder(className, !lowerFirstCase ? file.getProperty() : lowerFirstCase(file.getProperty()), Modifier.PRIVATE)
                    .addAnnotation(AnnotationSpec.builder(ApiModelProperty.class)
                            .addMember("value", "$S", remarks.trim()).build());
  1. 排除字段
                    if (file.isExits()) {
                    filedBuilder.addAnnotation(AnnotationSpec.builder(TableField.class).addMember("value", "$S", file.getColumn()).build());
                } else {
                    if (file.getTable() != null && !onlyMp) {
                        //老框架带入
                        AnnotationSpec.Builder relationSpec = AnnotationSpec.builder(ClassName.get("com.caijai.base.anno", "Relation"))
                                .addMember("table", file.getTable())
                                .addMember("value", file.getValue())
                                .addMember("ref", file.getRef())
                                .addMember("show", file.getShow());
                        filedBuilder.addAnnotation(relationSpec.build());
                    }
                    filedBuilder.addAnnotation(AnnotationSpec.builder(TableField.class).addMember("exist", "false").build());
                }
  1. 具体的属性字段,要判断泛型,基础数据类型,数组只考虑了字符串数组,还有枚举
            //查找是否是导入的类
            Optional<String> first = tableInfo.getImportPackage().stream().filter(s -> s.contains(finalClassNam)).findFirst();
            TypeName className;
            if (first.isPresent()) {
                String className1 = file.getClassName();
                //如果是泛型就取出真正的类型
                if (className1.contains("<")) {
                    int start = file.getClassName().indexOf("<") + 1;
                    int end = file.getClassName().indexOf(">");
                    className1 = file.getClassName().substring(start, end);
                }
                String replace1 = first.get().replace("." + className1, "");
                if (!replace1.contains("enum") && !replace1.contains("java") && changePackage) {
                    //交换包名(我起的不一样所有要改成我自己的,如果是false就是原包名)
                    String[] split = replace1.replace("com.caijai.", "").split("\\.");
                    String s = split[0];
                    String s1 = split[1];
                    StringBuilder s3 = new StringBuilder();
                    if (split.length > 2) {
                        for (int i = 2; i < split.length; i++) {
                            s3.append(".").append(split[i]);
                        }
                    }
                    replace1 = newPackage + "." + s1 + "." + s + s3.toString();
                }
                //如果是集合 加上泛型   不是就正常类型(包括导入的类型)
                if (file.getClassName().contains("List")) {
                    className = ClassName.get(replace1, finalClassNam);
                    ClassName name = ClassName.get("java.util", "List");
                    className = ParameterizedTypeName.get(name, className);
                } else {
                    className = ClassName.get(replace1, file.getClassName());
                }
            } else {
                // java自带的不需要导包的类型
                //集合
                if (file.getClassName().contains("List")) {
                    int start = file.getClassName().indexOf("<") + 1;
                    int end = file.getClassName().indexOf(">");
                    String s2 = file.getClassName().substring(start, end);
                    first = tableInfo.getImportPackage().stream().filter(a -> a.contains(s2)).findFirst();
                    String s3 = first.orElse("");
                    ClassName name = ClassName.get("java.util", "List");
                    className = ParameterizedTypeName.get(name, ClassName.get(s3, s2));
                } else {
                    //基础数据类型
                    switch (file.getClassName()) {
                        case "int":
                        case "float":
                        case "short":
                        case "double":
                        case "long":
                        case "byte":
                        case "boolean":
                        case "char":
                        case "String[]":
                            //可能出现 String数组 className就是 String[]
                            className = ClassName.get("", file.getClassName().replace("[]", ""));
                            break;
                        default:
                            try {
                                className = ClassName.get("java.lang", file.getClassName().replace("[]", ""));
                                //加载下这个类,看是不是报错 如果是就当做泛型处理
                                Class.forName("java.lang." + file.getClassName());
                            } catch (ClassNotFoundException e) {
                                className = ClassName.get(enums, file.getClassName());
                            }
                            break;
                    }
                }
            }

完整代码


import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.squareup.javapoet.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.lang.model.element.Modifier;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

class TaskApplicationTests {
    static final String from = "E:\\java_project\\ims-parent";
    //    static final String rootPath = "E:\\java_project\\ims-parent";
    static final String rootPath = "E:\\java_project\\sunad\\comm\\src\\main\\java";

    static final String baseTablePack = "com.finish.comm.entity.base";
    static final String newPackage = "com.finish.comm";
    static final String enums = "com.finish.comm.enums";
    static final List<String> baseFiled = Arrays.asList("createdBy", "ts", "dr", "id", "createdOn", "modifiedBy", "modifiedOn");
    static final List<String> exclude = Arrays.asList("HTTPURL", "U9BaseData", "BaseData", "BaseJSON", "ListenerEvent", "CorpVO");
    static final List<String> createExclude = Arrays.asList("BaseTable");
    static final boolean onlyMp = true;
    static final boolean changePackage = true;
    //属性首字母是否转小写
    static final boolean lowerFirstCase = true;
    static final List<TableInfo> tableInfoList = new ArrayList<>();

    public static void main(String[] args) throws Exception {
        List<File> files = getFiles(from);
        for (File file : files) {
//            if (!file.getName().equals("TransferFormVO.java")) {
//                continue;
//            }
            TableInfo tableInfo = createTableInfo(file);
            if (tableInfo == null || tableInfo.getClassName() == null || createExclude.contains(tableInfo.getClassName())) {
                continue;
            }
            tableInfoList.add(tableInfo);
        }
        for (TableInfo tableInfo : tableInfoList) {
            TypeSpec typeSpec = createFile(tableInfo);
            File file1 = new File(rootPath);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            String packag = tableInfo.getPackag();
            if (changePackage) {
                JavaFile.builder(packag.replace(".entity", "").replace("com.caijai", "com.finish.comm.entity"), typeSpec).build().writeTo(file1);
            } else {
                JavaFile.builder(packag, typeSpec).build().writeTo(file1);
            }
        }
    }

    private static List<File> getFiles(String path) {
        List<File> files = new ArrayList<>();
        File file = new File(path);
        if (!file.exists()) {
            return files;
        }
        if (file.isFile()) {
            files.add(file);
            return files;
        }
        File[] listFiles = file.listFiles();
        for (File listFile : listFiles) {
            if (listFile.getName().equals("utils")) {
                continue;
            }
            if (listFile.isDirectory()) {
                files.addAll(getFiles(listFile.getAbsolutePath()));
            } else {
                if (listFile.getAbsolutePath().contains("entity")) {
                    files.add(listFile);
                }
            }
        }
        return files;
    }

    private static TypeSpec createFile(TableInfo tableInfo) {
        TypeSpec.Builder classBuilder = TypeSpec.classBuilder(tableInfo.getClassName()).addModifiers(Modifier.PUBLIC);
        classBuilder.addAnnotation(Data.class);
        TableInfo info = null;
        if (tableInfo.getSupper() != null) {
            classBuilder.addAnnotation(AnnotationSpec.builder(EqualsAndHashCode.class).addMember("callSuper", "true").build());
            Optional<String> first = tableInfo.getImportPackage().stream().filter(s -> s.contains(tableInfo.getSupper())).findFirst();
            info = tableInfoList.stream().filter(s -> {
                        boolean supper = s.getClassName().equals(tableInfo.getSupper());
                        boolean equals = s.getPackag().equals(first.orElse("").replace("." + s.getClassName(), ""));
                        return equals && supper;
                    }
            ).findFirst().orElse(null);
            if (first.isPresent()) {
                String replace1 = first.get().replace("." + tableInfo.getSupper(), "");
                if (changePackage) {
                    //交换包名(我起的不一样所有要改成我自己的,如果是false就是原包名)
                    String[] split = replace1.replace("com.caijai.", "").split("\\.");
                    String s = split[0];
                    String s1 = split[1];
                    StringBuilder s3 = new StringBuilder();
                    if (split.length > 2) {
                        for (int i = 2; i < split.length; i++) {
                            s3.append(".").append(split[i]);
                        }
                    }
                    replace1 = newPackage + "." + s1 + "." + s + s3.toString();
                }
                classBuilder.superclass(ClassName.get(replace1, tableInfo.getSupper()));
            }
        }
        //添加类相关注解
        if (tableInfo.getTableName() != null) {
            if (!onlyMp) {
                AnnotationSpec tableSpec = AnnotationSpec.builder(ClassName.get("com.caijai.base.anno", "Table")).addMember("name", "$S", tableInfo.getTableName()).build();
                classBuilder.addAnnotation(tableSpec);
            }
            classBuilder.addAnnotation(AnnotationSpec.builder(TableName.class).addMember("value", "$S", tableInfo.getTableName()).build());
        }
        String replace = tableInfo.getRemarks();
        if (tableInfo.getRemarks() != null) {
            replace = replace.replace("\n", "");
            classBuilder.addAnnotation(AnnotationSpec.builder(ApiModel.class).addMember("description", "$S", replace).build());
            classBuilder.addJavadoc(tableInfo.getRemarks());
        }
        for (TableFiled file : tableInfo.getFiles()) {
            if (info != null) {
                if (info.getFiles().stream().filter(s -> s.getProperty() != null).anyMatch(s -> s.getProperty().equals(file.getProperty()))) {
                    continue;
                }
            }
            if (file.isBaseExits() || file.getProperty() == null) {
                continue;
            }
            if (file.getRemarks() == null) {
                file.setRemarks("");
            }
            String classNam = file.getClassName();
            if (classNam.contains("<")) {
                int start = file.getClassName().indexOf("<") + 1;
                int end = file.getClassName().indexOf(">");
                classNam = classNam.substring(start, end);
            }
            String finalClassNam = classNam;
            //查找是否是导入的类
            Optional<String> first = tableInfo.getImportPackage().stream().filter(s -> s.contains(finalClassNam)).findFirst();
            TypeName className;
            if (first.isPresent()) {
                String className1 = file.getClassName();
                //如果是泛型就取出真正的类型
                if (className1.contains("<")) {
                    int start = file.getClassName().indexOf("<") + 1;
                    int end = file.getClassName().indexOf(">");
                    className1 = file.getClassName().substring(start, end);
                }
                String replace1 = first.get().replace("." + className1, "");
                if (!replace1.contains("enum") && !replace1.contains("java") && changePackage) {
                    //交换包名(我起的不一样所有要改成我自己的,如果是false就是原包名)
                    String[] split = replace1.replace("com.caijai.", "").split("\\.");
                    String s = split[0];
                    String s1 = split[1];
                    StringBuilder s3 = new StringBuilder();
                    if (split.length > 2) {
                        for (int i = 2; i < split.length; i++) {
                            s3.append(".").append(split[i]);
                        }
                    }
                    replace1 = newPackage + "." + s1 + "." + s + s3.toString();
                }
                //如果是集合 加上泛型   不是就正常类型(包括导入的类型)
                if (file.getClassName().contains("List")) {
                    className = ClassName.get(replace1, finalClassNam);
                    ClassName name = ClassName.get("java.util", "List");
                    className = ParameterizedTypeName.get(name, className);
                } else {
                    className = ClassName.get(replace1, file.getClassName());
                }
            } else {
                // java自带的不需要导包的类型
                //集合
                if (file.getClassName().contains("List")) {
                    int start = file.getClassName().indexOf("<") + 1;
                    int end = file.getClassName().indexOf(">");
                    String s2 = file.getClassName().substring(start, end);
                    first = tableInfo.getImportPackage().stream().filter(a -> a.contains(s2)).findFirst();
                    String s3 = first.orElse("");
                    ClassName name = ClassName.get("java.util", "List");
                    className = ParameterizedTypeName.get(name, ClassName.get(s3, s2));
                } else {
                    //基础数据类型
                    switch (file.getClassName()) {
                        case "int":
                        case "float":
                        case "short":
                        case "double":
                        case "long":
                        case "byte":
                        case "boolean":
                        case "char":
                        case "String[]":
                            //可能出现 String数组 className就是 String[]
                            className = ClassName.get("", file.getClassName().replace("[]", ""));
                            break;
                        default:
                            try {
                                className = ClassName.get("java.lang", file.getClassName().replace("[]", ""));
                                //加载下这个类,看是不是报错 如果是就当做泛型处理
                                Class.forName("java.lang." + file.getClassName());
                            } catch (ClassNotFoundException e) {
                                className = ClassName.get(enums, file.getClassName());
                            }
                            break;
                    }
                }
            }
            //备注
            String remarks = file.getRemarks().replace("\n", "");
            if (remarks.contains("@Column")) {
                remarks = remarks.substring(0, remarks.indexOf("@Column"));
            }
            if (remarks.startsWith("*")) {
                remarks = remarks.substring(1);
            }
            //字段
            FieldSpec.Builder filedBuilder = FieldSpec.builder(className, !lowerFirstCase ? file.getProperty() : lowerFirstCase(file.getProperty()), Modifier.PRIVATE)
                    .addAnnotation(AnnotationSpec.builder(ApiModelProperty.class)
                            .addMember("value", "$S", remarks.trim()).build());
            if (tableInfo.getTableName() != null) {
                if (!onlyMp) {
                    //老框架带入
                    AnnotationSpec.Builder columnSpec = AnnotationSpec.builder(ClassName.get("com.caijai.base.anno", "Column"))
                            .addMember("name", "$S", file.getColumn());
                    //旧框架封装的数据库操作
                    if (file.isReadonly()) {
                        columnSpec.addMember("readonly", "true");
                    }
                    if (file.isByInt()) {
                        columnSpec.addMember("byInt", "true");
                    }
                    if (file.isByDouble()) {
                        columnSpec.addMember("byDouble", "true");
                    }
                    if (file.isPrimary()) {
                        columnSpec.addMember("primary", "true");
                    }
                    if (file.getSort() != null) {
                        String[] s1 = file.getSort().split("\\.");
                        Optional<String> optional = tableInfo.getImportPackage().stream().filter(s -> s.contains(s1[0])).findFirst();
                        optional.ifPresent(s -> columnSpec.addMember("sort", s + "." + s1[1]));
                    }
                    if (file.getColumn() != null) {
                        filedBuilder.addAnnotation(columnSpec.build());
                    }
                }
                if (file.isExits()) {
                    filedBuilder.addAnnotation(AnnotationSpec.builder(TableField.class).addMember("value", "$S", file.getColumn()).build());
                } else {
                    if (file.getTable() != null && !onlyMp) {
                        //老框架带入
                        AnnotationSpec.Builder relationSpec = AnnotationSpec.builder(ClassName.get("com.caijai.base.anno", "Relation"))
                                .addMember("table", file.getTable())
                                .addMember("value", file.getValue())
                                .addMember("ref", file.getRef())
                                .addMember("show", file.getShow());
                        filedBuilder.addAnnotation(relationSpec.build());
                    }
                    filedBuilder.addAnnotation(AnnotationSpec.builder(TableField.class).addMember("exist", "false").build());
                }
            }
            classBuilder.addField(filedBuilder.build());
        }
        return classBuilder.build();
    }

    public static TableInfo createTableInfo(File file) throws Exception {
        System.out.println(file.getName());
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        String line = null;
        TableInfo tableInfo = new TableInfo();
        try {
            while ((line = bufferedReader.readLine()) != null) {
                line = line.trim();
                String finalLine = line;
                if (exclude.stream().anyMatch(finalLine::contains)) {
                    return null;
                }
                //包名
                if (line.startsWith("package")) {
                    tableInfo.setPackag(line.replace("package", "").replace(";", "").trim());
                }
                //导入的类
                if (line.startsWith("import")) {
                    String anImport = line.replace("import", "").replace(";", "").trim();
                    if (!anImport.isEmpty() && anImport.contains("sysenum") && !enums.isEmpty()) {
                        anImport = anImport.replace("com.caijai.base.sysenum", enums);
                    }
                    tableInfo.getImportPackage().add(anImport);
                }
                //排除静态,get set方法
                if (line.isEmpty() || line.contains("static") || line.contains("()") || line.contains("void")) {
                    continue;
                }
                //获取类的信息
                if (line.contains("public class ")) {
                    String className;
                    if (line.contains("extends")) {
                        if (line.split("extends").length > 0) {
                            tableInfo.setSupper(line.substring(line.indexOf("extends"), line.indexOf("{")).replace("extends", "").trim());
                            if (tableInfo.getSupper().equals("BaseEntity")) {
                                tableInfo.setSupper("BaseTable");
                                tableInfo.getImportPackage().add("com.caijai.base.entity.BaseTable");
                            }
                        }
                        className = line.substring(line.indexOf("class"), line.indexOf("extends")).replace("class", "").trim();
                    } else {
                        className = line.substring(line.indexOf("class"), line.indexOf("{")).replace("class", "").trim();
                    }
                    tableInfo.setClassName(className);
                    continue;
                } else if (line.startsWith("@Table")) {
                    //获取表名
                    tableInfo.setTableName(line.substring(line.indexOf("\""), line.indexOf("\")")).replace("\"", ""));
                    continue;
                }
                if (tableInfo.getClassName() == null) {
                    //获取类注释
                    if ((line.startsWith("//") || line.startsWith("*") || line.startsWith("/**")) && !line.startsWith("*/")) {
                        if (line.equals("*")) {
                            tableInfo.setRemarks(tableInfo.getRemarks() + "\n");
                            continue;
                        }
                        if (tableInfo.getRemarks() != null) {
                            tableInfo.setRemarks(tableInfo.getRemarks() + "\n" + line.replace("* ", ""));
                        } else {
                            tableInfo.setRemarks(line.replace("* ", ""));
                        }
                    }
                } else {
                    List<TableFiled> files = tableInfo.getFiles();
                    TableFiled filed = new TableFiled();
                    if (files.isEmpty()) {
                        files.add(filed);
                    }
                    TableFiled tableFiled = files.get(files.size() - 1);
                    //判断该字段到底有没有 如果没有就用之前的,否则就添加新的
                    if (tableFiled.getProperty() != null) {
                        files.add(filed);
                    }
                    filed = files.get(files.size() - 1);
                    //字段注释
                    if ((line.startsWith("//") || line.startsWith("*") || line.startsWith("/**")) && !line.startsWith("*/")) {
                        if (line.equals("*")) {
                            filed.setRemarks(filed.getRemarks() + "\n");
                            continue;
                        }
                        if (filed.getRemarks() != null) {
                            filed.setRemarks(filed.getRemarks() + "\n" + line.replace("* ", ""));
                        } else {
                            filed.setRemarks(line.replace("* ", "").replace("/*", "").replace("*/", ""));
                        }
                    } else if (line.startsWith("@Column")) {
                        filed.setExits(true);
                        //老框架封装的数据库 保留
                        String[] primaries = line.split("=");
                        for (int i = 0; i < primaries.length; i++) {
                            String primary = primaries[i].trim();
                            if (primary.contains("primary")) {
                                filed.setPrimary(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("readonly")) {
                                filed.setExits(false);
                                filed.setReadonly(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("byInt")) {
                                filed.setByInt(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("byDouble")) {
                                filed.setByDouble(Boolean.parseBoolean(primaries[i + 1].trim().replace(")", "")));
                            } else if (primary.contains("sort ")) {
                                filed.setSort(primaries[i + 1].trim().replace(")", ""));
                            }
                        }
                        //获取数据库对应的字段名
                        int i = line.indexOf("\",");
                        if (i != -1) {
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        } else if ((i = line.indexOf("\")")) != -1) {
                            i = line.indexOf("\")");
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        } else if ((i = line.indexOf("\" ,")) != -1) {
                            filed.setColumn(line.substring(line.indexOf("\"") + 1, i).replace("\"", "").trim());
                        }
                    } else if (line.startsWith("@Relation")) {
                        //获取旧框架 关联查询字段
                        String[] split = line.split("=");
                        for (int i = 0; i < split.length; i++) {
                            String s = split[i].trim();
                            if (s.contains("table")) {
                                filed.setTable(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("ref")) {
                                filed.setRef(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("value")) {
                                filed.setValue(split[i + 1].trim().replace(")", "").split(",")[0]);
                            } else if (s.contains("show")) {
                                filed.setShow(split[i + 1].trim().replace(")", "").split(",")[0]);
                            }
                        }
                        filed.setJoinTable(line.replace("table", "表名").replace("value", "关联表字段").replace("ref", "当前表字段").replace("show", "查询的字段"));
                    } else if ((line.startsWith("private") || line.startsWith("public")) && !line.contains("class")) {
                        // 修饰符 类型名称 字段名称 备注
                        line = line.replace("  ", " ").replace(" ;", ";");
                        String[] s = line.split(" ");
                        filed.setModifier(s[0].trim());
                        filed.setClassName(s[1].trim());
                        filed.setProperty(s[2].substring(0, s[2].indexOf(";")).replace("\t", ""));
                        String[] split = line.split("//");
                        if (split.length > 1) {
                            filed.setRemarks(split[1]);
                        }
                    }
                    if (tableInfo.getSupper() != null) {
                        TableFiled finalFiled = filed;
                        //basetable是不是已存在
                        filed.setBaseExits(baseFiled.stream().anyMatch(s -> s.equalsIgnoreCase(finalFiled.getProperty()) || s.equalsIgnoreCase(finalFiled.getColumn())));
                    }
                    //去掉备注的双斜杠
                    if (filed.getRemarks() != null)
                        filed.setRemarks(filed.getRemarks().replace("//", ""));
                }
            }

        } catch (Exception e) {
            System.out.println(line);
            System.out.println(file.getName());
            throw e;
        }
        if (tableInfo.getRemarks() != null)
            tableInfo.setRemarks(tableInfo.getRemarks().replace("/**", ""));
        return tableInfo;
    }


    public static String lowerFirstCase(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
    }

    @Data
    static class TableInfo {
        private String className;
        private String supper;
        private String packag;
        private String remarks;
        private String tableName;
        private List<String> importPackage = new ArrayList<>();
        private List<TableFiled> files = new ArrayList<>();
    }

    @Data
    static class TableFiled {
        //字段名
        private String column;
        //属性名
        private String property;
        private String remarks;
        //类型名称
        private String className;
        //数据库是否存在
        private boolean exits;

        private boolean readonly;
        private String sort;
        private boolean byInt;
        private boolean byDouble;
        private boolean primary;

        private String table;
        private String value;
        private String show;
        private String ref;

        //关联的表
        private String joinTable;
        //base是否存在
        private boolean baseExits;
        private String modifier;
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352