/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.zt.generator.utils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.zt.common.exception.RenException;
import com.zt.generator.model.Column;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.texen.util.FileUtil;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;
import java.util.stream.Collectors;
/**
* 代码生成器 工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class GenUtils {
public static List getTemplates() {
List 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/Controller.java.vm");
templates.add("template/Excel.java.vm");
templates.add("template/index.vue.vm");
templates.add("template/add-or-update.vue.vm");
// templates.add("template/mysql.vm");
return templates;
}
public static void generatorCode(String tableName, String isGenService, String className, String isPageFlag,
String isExport, JSONArray columns, String packageName, String javaFilePath, String vueFilePath) {
boolean hasBigDecimal = false, hasDate = false;
// 列信息
List columsList = new ArrayList<>();
String filter = ",id,creator,updater,update_date,create_date,is_delete,tenant_id,company_id,dept_id,)";
String createFilter = ",creator,create_date,tenant_id,company_id,dept_id,)";
String updateFilter = ",updater,update_date,is_delete,)";
int createCount = 0, updateCount = 0;
Column pkColumn = null;
for (int i = 0; i < columns.size(); i++) {
JSONObject object = columns.getJSONObject(i);
Column columnEntity = new Column();
String columnName = object.getString("columnName");
if ("id".equals(columnName.toLowerCase())) {
continue;
}
if (createFilter.indexOf("," + columnName.toLowerCase() + ",") >= 0) {
createCount++;
continue;
}
if (updateFilter.indexOf("," + columnName.toLowerCase() + ",") >= 0) {
updateCount++;
continue;
}
columnEntity.setColumnName(columnName);
columnEntity.setDataType(object.getString("typeName"));
String comment = object.getString("remarks");
if (StringUtils.isNotEmpty(comment)) {
comment = comment.trim();
}
int index = comment.indexOf(" ");
if (index > 0) {
comment = comment.substring(0, index);
}
index = comment.indexOf("。");
if (index > 0) {
comment = comment.substring(0, index);
}
columnEntity.setComments(comment);
columnEntity.setIsSelectColumn(object.getString("isSelectColumn"));
columnEntity.setIsTableColumn(object.getString("isTableColumn"));
columnEntity.setDictType(object.getString("dictType"));
columnEntity.setOp(object.getString("op"));
// 列名转换成Java属性名
String attrName = columnToJava(columnEntity.getColumnName());
columnEntity.setAttrName(StringUtils.uncapitalize(attrName));
// 列的数据类型,转换成Java类型
String attrType = map.get(columnEntity.getDataType());
if (StringUtils.isBlank(attrType)) {
attrType = "String";
}
columnEntity.setAttrType(attrType);
if (!hasBigDecimal && attrType.equals("BigDecimal")) {
hasBigDecimal = true;
}
if (!hasDate && attrType.equals("Date")) {
hasDate = true;
}
// 是否主键
if ("Y".equalsIgnoreCase(object.getString("isKey"))) {
if (pkColumn != null) {
throw new RenException("请不要设置联合主键");
}
pkColumn = columnEntity;
}
columsList.add(columnEntity);
}
// 设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
// 封装模板数据
Map map = new HashMap<>();
map.put("tableName", tableName);// 表名@TableName("${tableName}")
map.put("comments", tableName);
if (createCount < 5) {
throw new RenException("数据库字段缺失,请按照规范");
} else if (updateCount == 3) {
map.put("entityType", "BusiEntity");
} else {
map.put("entityType", "BusiLogEntity");
}
map.put("pk", pkColumn);
map.put("package", packageName);
map.put("className", className); //实体类名字
// private ${className}Service ${classBean}Service;
map.put("classBean", StringUtils.uncapitalize(className)); //实体实例名字
// model bean的名称insert(@RequestBody ${className} ${modelName})
map.put("modelName", StringUtils.uncapitalize(className)); //模型名字
// @RequestMapping("/${moduleName}/${pathName}")
String moduleName = packageName.substring(packageName.lastIndexOf(".") + 1, packageName.length());
map.put("moduleName", moduleName); //模块名字 包名(相对路径)
String pathName = StrUtil.toSymbolCase(className, '/');// 驼峰转下划线
if (pathName.indexOf(moduleName) == 0) {
pathName = pathName.substring(moduleName.length());
if (pathName.length() > 0 && pathName.startsWith("/")) {
pathName = pathName.substring(1);
}
}
map.put("importPath", tableName.replaceAll("_", "-"));// url请求的
map.put("pathName", pathName);// url请求的
map.put("permName", pathName.replace("/", ":"));// 权限的
map.put("columns", columsList);
map.put("selectColumns", columsList.stream().filter(column -> "true".equals(column.getIsSelectColumn()))
.collect(Collectors.toList()));
map.put("version", "1.0.0");
map.put("author", "zt generator");
map.put("email", "");
map.put("isExport", isExport);
map.put("hasBigDecimal", hasBigDecimal);
map.put("hasDate", hasDate);
map.put("datetime", DateUtil.now());
map.put("date", DateUtil.format(new Date(), DatePattern.NORM_DATE_FORMAT));
for (int i = 0; i <= 10; i++) {
map.put("id" + i, IdWorker.getId());
}
VelocityContext context = new VelocityContext(map);
// 获取模板列表
List templates = getTemplates();
for (String template : templates) {
if (!"true".equals(isGenService) && (template.contains("Service") || template.contains("Controller"))) {
continue;
}
if (!"true".equals(isPageFlag)
&& (template.contains("index.vue") || template.contains("add-or-update.vue"))) {
continue;
}
if (!"true".equals(isExport) && template.contains("Excel")) {
continue;
}
// 渲染模板
String fileName = "";
String filePath = "";
if (template.contains("index.vue")) {
fileName = className + ".vue";
filePath = getFilePath(template, vueFilePath, packageName, moduleName);
} else if (template.contains("add-or-update.vue")) {
fileName = className + "-AddOrUpdate.vue";
filePath = getFilePath(template, vueFilePath, packageName, moduleName);
} else if (template.contains("Entity.java.vm")) {
fileName = className + ".java";
filePath = getFilePath(template, javaFilePath, packageName, moduleName);
} else {
fileName = className + template.split("/")[1].replaceAll(".vm", "");
filePath = getFilePath(template, javaFilePath, packageName, moduleName);
}
FileUtil.mkdir(filePath);
try {
Writer writer = new OutputStreamWriter(new FileOutputStream(filePath + "/" + fileName), "UTF-8");
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, writer);
writer.flush();
writer.close();
System.out.println("生成" + fileName + "成功,目录:" + filePath);
} catch (Exception e) {
e.printStackTrace();
throw new RenException(e.getMessage());
}
}
}
/**
* 列名转换成Java属性名
*/
public static String columnToJava(String columnName) {
return WordUtils.capitalizeFully(columnName, new char[] { '_' }).replace("_", "");
}
/**
* 表名转换成Java类名
*/
public static String tableToJava(String tableName, String tablePrefix) {
if (StringUtils.isNotBlank(tablePrefix)) {
tableName = tableName.replaceFirst(tablePrefix, "");
}
return columnToJava(tableName);
}
/**
* 获取文件名
*/
public static String getFilePath(String template, String filePath, String packageName, String moduleName) {
if (template.contains("Entity.java.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/model";
}
if (template.contains("Excel.java.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/excel";
}
if (template.contains("Dao.java.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/dao";
}
if (template.contains("Service.java.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/service";
}
if (template.contains("Controller.java.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/controller";
}
if (template.contains("Dao.xml.vm")) {
return filePath + "/src/main/resources/mapper/" + moduleName;
}
if (template.contains("index.vue.vm")) {
return filePath + "/src/views/modules/"
+ packageName.substring(packageName.lastIndexOf(".") + 1, packageName.length());
}
if (template.contains("add-or-update.vue.vm")) {
return filePath + "/src/views/modules/"
+ packageName.substring(packageName.lastIndexOf(".") + 1, packageName.length());
}
if (template.contains("mysql.vm")) {
return filePath + "/src/main/java/" + packageName.replace(".", "/") + "/mysql";
}
return null;
}
private static Map map = new HashMap() {
{
put("tinyint".toUpperCase(), "Integer");
put("smallint".toUpperCase(), "Integer");
put("mediumint".toUpperCase(), "Integer");
put("int".toUpperCase(), "Integer");
put("integer".toUpperCase(), "Integer");
put("bigint".toUpperCase(), "Long");
put("float".toUpperCase(), "Float");
put("double".toUpperCase(), "Double");
put("decimal".toUpperCase(), "BigDecimal");
put("char".toUpperCase(), "String");
put("varchar".toUpperCase(), "String");
put("tinytext".toUpperCase(), "String");
put("text".toUpperCase(), "String");
put("mediumtext".toUpperCase(), "String");
put("longtext".toUpperCase(), "String");
put("date".toUpperCase(), "Date");
put("datetime".toUpperCase(), "Date");
put("timestamp".toUpperCase(), "Date");
put("NUMBER", "Integer");
put("INT".toLowerCase(), "Integer");
put("INTEGER", "Integer");
put("BINARY_INTEGER", "Integer");
put("LONG", "String");
put("FLOAT", "Float");
put("BINARY_FLOAT", "Float");
put("DOUBLE", "Double");
put("BINARY_DOUBLE", "Double");
put("DECIMAL", "BigDecimal");
put("CHAR", "String");
put("VARCHAR", "String");
put("VARCHAR2", "String");
put("NVARCHAR", "String");
put("NVARCHAR2", "String");
put("CLOB", "String");
put("BLOB", "String");
put("DATE", "Date");
put("DATETIME", "Date");
put("TIMESTAMP", "Date");
put("TIMESTAMP(6);", "Date");
put("int8", "Long");
put("int4", "Integer");
put("int2", "Integer");
put("numeric", "BigDecimal");
put("INT16", "Short");
put("INT32", "Integer");
put("INT64", "Long");
put("BIGINT", "Long");
put("TINYINT UNSIGNED", "Integer");
put("TINYINT", "Integer");
put("BIT", "Boolean");
}
};
}