content: package com.company.project.common.utils;
  
  import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  import com.company.project.common.exception.BusinessException;
  import com.company.project.entity.ColumnEntity;
  import com.company.project.entity.TableEntity;
  import org.apache.commons.configuration.Configuration;
  import org.apache.commons.configuration.ConfigurationException;
  import org.apache.commons.configuration.PropertiesConfiguration;
  import org.apache.commons.io.IOUtils;
  import org.apache.commons.lang.StringUtils;
  import org.apache.velocity.Template;
  import org.apache.velocity.VelocityContext;
  import org.apache.velocity.app.Velocity;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.StringWriter;
  import java.util.*;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipOutputStream;
  
  /**
   * 代码生成器 工具类
   *
   * @author wenbin
   * @version V1.0
   * @date 2020年3月18日
   */
  public class GenUtils {
  
      public static List<String> getTemplates() {
          List<String> templates = new ArrayList<>();
          templates.add("template/Entity.java.vm");
          templates.add("template/Dao.java.vm");
          templates.add("template/Dao.xml.vm");
          templates.add("template/Service.java.vm");
          templates.add("template/ServiceImpl.java.vm");
          templates.add("template/Controller.java.vm");
          templates.add("template/menu.sql.vm");
          templates.add("template/list.html.vm");
  
          return templates;
      }
  
      /**
       * 生成代码
       */
      public static void generatorCode(Map<String, String> table,
                                       List<Map<String, String>> columns, ZipOutputStream zip) {
          //配置信息
          Configuration config = getConfig();
          boolean hasBigDecimal = false;
          //表信息
          TableEntity tableEntity = new TableEntity();
          tableEntity.setTableName(table.get("tableName"));
          tableEntity.setComments(table.get("tableComment"));
          //表名转换成Java类名
          String className = tableToJava(tableEntity.getTableName(), config.getStringArray("tablePrefix"));
          tableEntity.setClassName(className);
          tableEntity.setClassname(StringUtils.uncapitalize(className));
          tableEntity.setClassNameLower(className.toLowerCase());
  
          //列信息
          List<ColumnEntity> columsList = new ArrayList<>();
          List<ColumnEntity> htmlColumsList = new ArrayList<>();
          for (Map<String, String> column : columns) {
              ColumnEntity columnEntity = new ColumnEntity();
              columnEntity.setColumnName(column.get("columnName"));
              columnEntity.setDataType(column.get("dataType"));
              columnEntity.setComments(column.get("columnComment"));
              columnEntity.setExtra(column.get("extra"));
  
              //列名转换成Java属性名
              String attrName = columnToJava(columnEntity.getColumnName());
              columnEntity.setAttrName(attrName);
              columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
  
              //列的数据类型，转换成Java类型
              String attrType = config.getString(columnEntity.getDataType(), "unknowType");
              columnEntity.setAttrType(attrType);
              if (!hasBigDecimal && "BigDecimal".equals(attrType)) {
                  hasBigDecimal = true;
              }
              //是否主键
              if ("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null) {
                  tableEntity.setPk(columnEntity);
              }
  
              columsList.add(columnEntity);
              if (!Arrays.asList("deleted", "create_id", "create_by", "update_id", "update_by", "create_time", "create_date", "update_time", "update_date").contains(column.get("columnName"))) {
                  htmlColumsList.add(columnEntity);
              }
          }
          tableEntity.setColumns(columsList);
          tableEntity.setHtmlColumns(htmlColumsList);
  
          //没主键，则第一个字段为主键
          if (tableEntity.getPk() == null) {
              tableEntity.setPk(tableEntity.getColumns().get(0));
          }
  
          //设置velocity资源加载器
          Properties prop = new Properties();
          prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
          Velocity.init(prop);
          String mainPath = config.getString("mainPath");
          mainPath = StringUtils.isBlank(mainPath) ? "com.company" : mainPath;
          //封装模板数据
          Map<String, Object> map = new HashMap<>(15);
          map.put("tableName", tableEntity.getTableName());
          map.put("comments", tableEntity.getComments());
          map.put("pk", tableEntity.getPk());
          map.put("className", tableEntity.getClassName());
          map.put("classname", tableEntity.getClassname());
          map.put("pathName", tableEntity.getClassname().toLowerCase());
          map.put("columns", tableEntity.getColumns());
          map.put("htmlColumns", tableEntity.getHtmlColumns());
          map.put("classNameLower", tableEntity.getClassNameLower());
          map.put("hasBigDecimal", hasBigDecimal);
          map.put("mainPath", mainPath);
          map.put("package", config.getString("package"));
          map.put("author", config.getString("author"));
          map.put("email", config.getString("email"));
          map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
          map.put("identity", IdWorker.getId());
          map.put("addId", IdWorker.getId());
          map.put("updateId", IdWorker.getId());
          map.put("deleteId", IdWorker.getId());
          map.put("selectId", IdWorker.getId());
          map.put("identityJoinId", IdWorker.getId());
          map.put("addIdJoinId", IdWorker.getId());
          map.put("updateIdJoinId", IdWorker.getId());
          map.put("deleteIdJoinId", IdWorker.getId());
          map.put("selectIdJoinId", IdWorker.getId());
          VelocityContext context = new VelocityContext(map);
  
          //获取模板列表
          List<String> templates = getTemplates();
          for (String template : templates) {
              //渲染模板
              StringWriter sw = new StringWriter();
              Template tpl = Velocity.getTemplate(template, "UTF-8");
              tpl.merge(context, sw);
  
              try {
                  //添加到zip
                  zip.putNextEntry(new ZipEntry(Objects.requireNonNull(getFileName(template, tableEntity.getClassName(), config.getString("package")))));
                  IOUtils.write(sw.toString(), zip, "UTF-8");
                  IOUtils.closeQuietly(sw);
                  zip.closeEntry();
              } catch (IOException e) {
                  throw new BusinessException("渲染模板失败，表名：" + tableEntity.getTableName());
              }
          }
      }
  
  
      /**
       * 列名转换成Java属性名
       */
      public static String columnToJava(String field) {
          String[] fields = field.split("_");
          StringBuilder sbuilder = new StringBuilder(fields[0]);
          for (int i = 1; i < fields.length; i++) {
              char[] cs = fields[i].toCharArray();
              if (cs[0] >= 'a') {
                  cs[0] -= 32;
              }
              sbuilder.append(String.valueOf(cs));
          }
          return sbuilder.toString().substring(0, 1).toUpperCase() + sbuilder.toString().substring(1);
      }
  
  
      /**
       * 表名转换成Java类名
       */
      public static String tableToJava(String tableName, String[] tablePrefixArray) {
          tableName = tableName.toLowerCase();
          if (null != tablePrefixArray && tablePrefixArray.length > 0) {
              for (String tablePrefix : tablePrefixArray) {
                  tablePrefix = tablePrefix.toLowerCase();
                  tableName = tableName.replace(tablePrefix, "");
              }
          }
          return columnToJava(tableName);
      }
  
      /**
       * 获取配置信息
       */
      public static Configuration getConfig() {
          try {
              return new PropertiesConfiguration("generator.properties");
          } catch (ConfigurationException e) {
              throw new BusinessException("获取配置文件失败");
          }
      }
  
      /**
       * 获取文件名
       */
      public static String getFileName(String template, String className, String packageName) {
          String packagePath = "main" + File.separator + "java" + File.separator;
          if (StringUtils.isNotBlank(packageName)) {
              packagePath += packageName.replace(".", File.separator) + File.separator;
          }
  
          if (template.contains("Entity.java.vm")) {
              return packagePath + "entity" + File.separator + className + "Entity.java";
          }
  
          if (template.contains("Dao.java.vm")) {
              return packagePath + "mapper" + File.separator + className + "Mapper.java";
          }
  
          if (template.contains("Service.java.vm")) {
              return packagePath + "service" + File.separator + className + "Service.java";
          }
  
          if (template.contains("ServiceImpl.java.vm")) {
              return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
          }
  
          if (template.contains("Controller.java.vm")) {
              return packagePath + "controller" + File.separator + className + "Controller.java";
          }
  
          if (template.contains("Dao.xml.vm")) {
              return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + className + "Mapper.xml";
          }
  
          if (template.contains("menu.sql.vm")) {
              return className.toLowerCase() + "_menu.sql";
          }
  
          if (template.contains("list.html.vm")) {
              return "main" + File.separator + "resources" + File.separator + "templates" + File.separator + className.toLowerCase() + File.separator + "list" + ".html";
          }
  
          return null;
      }
  }
  