Repository: caofanCPU/D8gerAutoCode Branch: Vip587 Commit: 0fc393f03039 Files: 86 Total size: 557.7 KB Directory structure: gitextract_52hz9hgr/ ├── .idea/ │ ├── $CACHE_FILE$ │ ├── .gitignore │ ├── D8gerAutoCodePluginProjectSetting.xml │ ├── codeStyles/ │ │ ├── Project.xml │ │ └── codeStyleConfig.xml │ ├── compiler.xml │ ├── dataSources.xml │ ├── dictionaries/ │ │ ├── D8GER.xml │ │ └── ht_caofan.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── inspectionProfiles/ │ │ └── Project_Default.xml │ ├── jarRepositories.xml │ ├── libraries-with-intellij-classes.xml │ ├── misc.xml │ ├── setting.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── IntelliJBestAction.adoc ├── IntelliJBestAction.html ├── LICENCE ├── README.md ├── README_CN.md ├── build.gradle ├── doc/ │ ├── ComputerMathData.md │ ├── Math.adoc │ └── WX-MarkDownTest.md ├── settings.gradle └── src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── xyz/ │ │ └── caofancpu/ │ │ └── d8ger/ │ │ ├── WhoAmI.java │ │ ├── action/ │ │ │ ├── D8gerAutoCodeAction.java │ │ │ └── SwaggerModelAutoRenderAction.java │ │ ├── activity/ │ │ │ └── D8gerActivity.java │ │ ├── core/ │ │ │ ├── AutoCodeTemplate.java │ │ │ ├── D8gerAutoCoding.java │ │ │ ├── EasterEggCodeTemplateEnum.java │ │ │ ├── KeyEnum.java │ │ │ ├── MoField.java │ │ │ ├── ProjectEnvHandler.java │ │ │ ├── SupportFieldTypeEnum.java │ │ │ └── TemplateKeyWordEnum.java │ │ ├── setting/ │ │ │ ├── D8gerApplicationState.java │ │ │ ├── D8gerProjectState.java │ │ │ ├── D8gerSetting.form │ │ │ ├── D8gerSetting.java │ │ │ └── D8gerSettingsConfigurable.java │ │ └── util/ │ │ ├── CollectionUtil.java │ │ ├── ConstantUtil.java │ │ ├── DateUtil.java │ │ ├── IdeaPlatformFileTreeUtil.java │ │ ├── JSONUtil.java │ │ ├── PropertiesUtil.java │ │ ├── StringAlignUtil.java │ │ └── VerbalExpressionUtil.java │ └── resources/ │ ├── META-INF/ │ │ └── plugin.xml │ ├── icons/ │ │ └── Icon │ └── template/ │ ├── .zshrc │ ├── ControllerTemplate.txt │ ├── DeletedServiceInterfaceTemplate.txt │ ├── EN/ │ │ ├── ControllerTemplate.txt │ │ ├── D8GER.txt │ │ ├── DeletedServiceInterfaceTemplate.txt │ │ ├── ExampleTemplate.txt │ │ ├── HandlerTemplate.txt │ │ ├── MapperTemplate.txt │ │ ├── MapperXMLTemplate.txt │ │ ├── MoTemplate.txt │ │ ├── SQLTemplate.txt │ │ └── SwaggerMoTemplate.txt │ ├── END.txt │ ├── ExampleTemplate.txt │ ├── HandlerTemplate.txt │ ├── MapperTemplate.txt │ ├── MapperXMLTemplate.txt │ ├── MoTemplate.txt │ ├── NASA.txt │ ├── PLAN.txt │ ├── Regex.txt │ ├── SQLTemplate.txt │ ├── SwaggerMoTemplate.txt │ ├── caofan.txt │ ├── d8ger-util-list.txt │ ├── javaShorts.txt │ ├── normal.command │ └── ohmyd8ger.command └── test/ ├── java/ │ └── d8ger/ │ └── D8T.java └── resources/ └── MyJSON.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .idea/$CACHE_FILE$ ================================================ Ali-Check AlibabaBooleanPropertyShouldNotStartWithIs ================================================ FILE: .idea/.gitignore ================================================ # Default ignored files /workspace.xml # Project exclude paths /. /../../ # Datasource local storage ignored files /dataSources/ /dataSources.local.xml ================================================ FILE: .idea/D8gerAutoCodePluginProjectSetting.xml ================================================ ================================================ FILE: .idea/codeStyles/Project.xml ================================================ ================================================ FILE: .idea/codeStyles/codeStyleConfig.xml ================================================ ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/dataSources.xml ================================================ mysql.8 true local com.mysql.cj.jdbc.Driver jdbc:mysql://localhost:3306 ================================================ FILE: .idea/dictionaries/D8GER.xml ================================================ xtools ================================================ FILE: .idea/dictionaries/ht_caofan.xml ================================================ caofan caofancpu dibage ocket penta uncapitalize uncapitallize ================================================ FILE: .idea/encodings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/inspectionProfiles/Project_Default.xml ================================================ ================================================ FILE: .idea/jarRepositories.xml ================================================ ================================================ FILE: .idea/libraries-with-intellij-classes.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ ================================================ FILE: .idea/setting.xml ================================================ ================================================ FILE: .idea/uiDesigner.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: IntelliJBestAction.adoc ================================================ == IntelliJ IDEA最佳实践 . Intellij IDEA for Java WEB 开发 * 快捷键 * 插件 * 快速测试 * Java工具包 . Intellij IDEA for Scala 开发(ing) . Intellij IDEA for Kotlin 开发(ing) NOTE: 如无特殊说明, 本文基于Mac OS 及Intellij IDEA 2020.1.x, + 涉及系统或版本差异时会就近补充说明, + 总体上: Mac的**#cmd#**等价于Windows的**#ctrl#**, + Intellij IDEA高版本功能是兼容低版本功能的, 只是部分插件会受到一些影响 === 快捷键 - 找到所有快捷键, `Help` --> `Keymap Reference`, 出现的PDF展示了当前你的编辑器的所有快捷键 - 确实有点多, 不着急, 知道了方法, 后续只是时间问题. 如何搜索快捷键, 参见下图 image::http://file.debuggerpowerzcy.top/power/Shortcut.png[title=如何搜索快捷键] .10个高频快捷键 |=== |功能 |关键词 |示例(默认)快捷键 |①语句自动完成 |Complete statement |cmd + shift + enter |②复写(父类)方法 |Override methods \| Generate |ctrl + O \| ctrl + enter |③智能提示\|纠错 |Show Context Actions |ctrl + shift + alt + enter |④快速复制粘贴 |Duplicate Line or Selection |cmd + D |⑤查看方法调用 |Call Hierarchy |ctrl + alt + H |⑥跳转到父类申明 |Go to Super Method |cmd + U |⑦跳转到子类实现 |Go to Declaration or Usages |cmd + B |⑧拼接下一行 |Join Lines |ctrl + shift + J |⑨优化导包 |Optimize Imports |ctrl + alt + O |⑩格式化代码 |Reformat Code |cmd + alt + L |更多彩蛋 |安装插件 Key Promoter X |对于有快捷键的按钮, 当你点击时提示告诉你快捷键 |=== === 插件 - https://plugins.jetbrains.com/plugin/9792-key-promoter-x/[Key Promoter X] * 快捷键提示, 新手必备, 而老手也可以通过它得知新版IDEA的一些特性信息 - https://plugins.jetbrains.com/plugin/10080-rainbow-brackets/[Rainbow Brackets] * 代码括号自动匹配, 彩板护眼 - https://plugins.jetbrains.com/plugin/6317-lombok/[Lombok] * 这位都听说过吧, 没听过的要么是大佬要么改行吧 * 采坑经验, 使用Lombok时, 尽量避免对象间继承, 如果非要继承, 应考虑@EqualsAndHashCode(callSuper = true : false) * 示例: [source,jave] ---- /** * balabala * * @author Mr.X */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @EqualsAndHashCode(callSuper = true) public class PormHub extends GitHub{ private Boolean well = Boolean.FALSE; } ---- - https://plugins.jetbrains.com/plugin/7391-asciidoc/[AsciiDoc] * 文档编辑神器, AsciiDoc本身目标是制作大型电子书, 超越MarkDown, 本文就是用AsciiDoc书写完成的 * **Spring**官方、**Spring-Alibaba**官方都采用AsciiDoc撰写文档, **GitHub**也支持AsciiDoc, AsciiDoc是未来的主流, MarkDown貌似要成替补了 * 个人使用体验, 对于写技术文档, 上手快, 简洁, 本文的一个小目标就是为新手提供常用的模块, 支持ctrl + c | v image::http://file.debuggerpowerzcy.top/power/AsciiDoc.png[title=AsciiDoc文档速览] - https://plugins.jetbrains.com/plugin/8579-translation/[Translation] * 作为中国程序员, 英语不会咋办? * 安装该插件, 选中任意文本, *ctrl + alt + T* 一键翻译 - https://plugins.jetbrains.com/plugin/6725-ibatis-mybatis-mini-plugin/[iBATIS/MyBatis mini-plugin] * 对于采用Mybatis且保留SQL的方式, 从Mapper接口跳转到对应SQL处, 可以借助该插件完成 * 当然现在有很多采用无SQL的方式, 参见 https://github.com/baomidou/mybatis-plus[苞米豆] - https://plugins.jetbrains.com/plugin/7179-maven-helper/[MavenHelper] * 国内Java工程多采用Maven来管理依赖, 对于一些不讲究的老项目, 依赖纠缠不清, 这个时候咋办? * 就这样, 凉拌吧! * 又或者, MavenHelper带你浴火重生, 请看下图 image::http://file.debuggerpowerzcy.top/power/MavenHelper.png[title=MavenHelper特性速览] - https://plugins.jetbrains.com/plugin/8286-sequencediagram/[SequenceDiagram] * 当我们跳槽后接坑时, 代码的链路是怎样的, 怎么没完没了呢? * 这个时候, SequenceDiagram带你一览全貌 * 方法调用时序图出来了, 慢慢瞅吧! image::http://file.debuggerpowerzcy.top/power/SequenceDiagram.png[title=SequenceDiagram特性速览] - https://plugins.jetbrains.com/plugin/13576-d8gerautocode/[D8gerAutoCode] * 作为Web开发, 当业务理解清楚后, 开发过程就可以量化如下: . 表设计 . SQL -> Mapper -> Mo -> -> handler -> *Service* -> Controller . 自测 . 联调 . PM加需求, 再改一波... * 在上诉步骤中, 我认为1、2、3步是自己可以控制的, 且步骤2中除了**Service**层代码由业务决定外, 其他基本代码基本如出一辙 * 这意味着什么? * 据我的观察, 1-3年的大部分程序员就在写这些重复代码, 有时写错或者抄错了, 到调试时定位到问题, 真的浪费不少时间... * 好在不少前辈通过创建工具, 以逆向工程方式生成``**生产环境可用的**``基础代码, 操作嘛也比较简单, 定义好SQL, 编写配置文件然后运行main方法生成 * 我的编码生涯里也有不少这样的回忆, 只是里面仍旧有不少重复操作, 甚至多人操作时会产生冲突 * 于是, 我从Mo出发, 写了D8gerAutoCode这个插件, 一切以表设计为核心, 你专注设计好Mo就可以, 其他基本代码使用快捷键一键搞定 * 如果D8gerAutoCode只有这个功能, 那其实和其他大佬插件相比没有啥可比性, 大家都用习惯了, 为何要使用新的呢? * 重点来了: D8gerAutoCode插件专注**`解决重复`**, 在平常工作中的重复工作应该被简化, 在我看来, 程序的初衷不就是如此吗? * 所以, D8gerAutoCode插件还带有字符串批处理, JSON处理, MySQL处理, 字段命名处理, 针对SwaggerAPI文档的处理, 这些功能是项目开发中都会用到的, 本着一键搞定原则而开发, 欲知详情参见后文 image::http://file.debuggerpowerzcy.top/power/D8Config.png[title=插件配置] image::http://file.debuggerpowerzcy.top/power/D8Generate.png[title=生成代码] image::http://file.debuggerpowerzcy.top/power/D8String.png[title=字符串批处理] image::http://file.debuggerpowerzcy.top/power/D8Format.png[title=格式化] image::http://file.debuggerpowerzcy.top/power/D8Regrex.png[title=正则彩蛋] === 快速测试 - 基于接口进行Http测试 - 整合Swagger-API, 代码及文档, 且支持文档界面进行调试(ing, 后续补充对应的Java实现代码) - 项目中涉及登录权限等问题, 在HTTP测试时应尽量模拟全, 为前端联调创造真实环境 - 辅助工具 * shell + python脚本 * https://httpie.org/[httpie], 可视化格式化的HTTP请求调用工具包 * https://github.com/kevinburke/sshpass[sshpass], 登录服务器自动输入指定密码, 可实现自动登录 * https://github.com/caofanCPU/D8gerConcurrent[D8gerConcurrent], 支持登陆解析、自动封装Cookie、 http://www.debuggerpowerzcy.top/home/2020/05/15/EasyHttp%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/[接口并发性能测试] [source,shell script] ---- function downLoadResponse() { echo "执行命令内容: \n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n" http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2} } function downLoadExcel() { echo "执行命令内容: \n http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}" http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2} } function show() { echo "执行命令内容: \n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n" http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2} } # 开发环境机器 function xDev() { # 借助sshpass工具, 将服务器密码保存在文件第一行, 实现自动登录; 且-t 参数支持登录后跳转到指定目录 sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt ssh Mr.X@xxx.xx.xx.${1} -t 'cd /XXX/logs/; exec $SHELL' } # 将HTPP请求的响应结果存入指定文件中, 示例: https-downLoadResponse https://www.baidu.com/ alias https-downLoadResponse='downLoadResponse' # 在控制台展示完整的HTTP请求过程, 响应打印在控制台, 示例: https-show https://www.baidu.com/ alias https-show='show' # 对于文件下载, 通过输入参数指定下载后的文件名, 示例: https-downLoadExcel https://www.baidu.com/file/123456 D8ger.zip alias https-downLoadExcel='downLoadExcel' # 对于开发测试环境多服务器, 简化为: xDev 99, 则自动登录xxx.xx.xx。99服务器 alias 'xDev=xDev' ---- image::http://file.debuggerpowerzcy.top/power/D8Login.png[登录获取COOKIE,并写入指定文件] image::http://file.debuggerpowerzcy.top/power/D8Http.png[调用HTTP接口进行测试] IMPORT: 采用这种方法, 可以告别PostMan或PostWoman及其他软件了, 你只需要**Intellij IDEA** + *iterm2*|xshell + **python**环境 === Java工具包 - Intellij IDEA代码简化模板, 这个技巧很香的, 比如常见的判断字符串不为空, 我只需要敲下``**fsnb**``, 就会得到如下代码 [source,text] ---- if (StringUtils.isNotBlank(光标在这)) { } 话不多说, 常用模板定义如下: /apim : SwaggerModel字段属性模板 oin : 对象为null ==> Objects.isNull() onn : 对象不为null ==> Objects.nonNull() o2e : 两对象相等 ==> Objects.equals(, ) one : 两对象不相等 ==> !Objects.equals(, ) foin : 判断对象为null ==> if (Objects.isNull()) {} fonn : 判断对象不为null ==> if (Objects.nonNull()) {} fo2e : 判断两对象相等 ==> if (Objects.equals(, )) {} fone : 判断两对象不相等 ==> if (!Objects.equals(, )) {} cie : 集合为空 ==> CollectionUtil.isEmpty() cne : 集合不为空 ==> CollectionUtil.isNotEmpty() sib : 字符串为空 ==> StringUtils.isBlank() snb : 字符串不为空 ==> StringUtils.isNotBlank() fcie : 判断集合为空 ==> if (CollectionUtil.isEmpty()){} fcne : 判断集合不为空 ==> if (CollectionUtil.isNotEmpty()){} fsib : 判断字符串为空 ==> if (StringUtils.isBlank()) {} fsnb : 判断字符串不为空 ==> if (StringUtils.isNotBlank()) {} ---- image::http://file.debuggerpowerzcy.top/power/D8LiveTemplate.png[代码模板] - 高频工具包, 推荐GitHub开源项目 https://github.com/caofanCPU/D8gerStarters[D8gerStarters] * 通用工具包子项目 https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-common-util[``**spring-cloud-starter-d8ger-common-util**``] . 集合流式处理工具**CollectionUtil**, 分组、求和、排序应有尽有, 基本可以告别for循环 . 树形处理工具**WrapTreeUtil**, 列表与树的多种转换骚操作也是应有尽有, 并且具有无侵入性, 开箱即用 . 数字精度运算工具**NumberUtil**, 金额进度计算, 精准百分比 . 枚举处理规范**IEnum**, 为项目打好根基, 规范枚举值用 - 中间件可插拔Starters整合工具包, 推荐GitHub开源项目 https://github.com/caofanCPU/D8gerStarters[D8gerStarters] * 通用工具包子项目 https://github.com/caofanCPU/D8gerStarters/tree/master/spring-cloud-starter-d8ger-web-util[``**spring-cloud-starter-d8ger-web-util**``] . 整合常用中间件, 例如业务线程池、邮件、Redis缓存、RestTemplate调用、消息队列、接口响应消息转换器、SwaggerAPI文档处理器 . 开关型可插拔, 默认有一套经过大型生产环境检验过的配置, 支持通过配置文件更改配置 . 保留扩展点, 通过继承等方式覆盖原有组件 === 总结 - 3个开源项目相辅相成, 目的与Spring等框架一致, 解决'最后一站'的重复问题, 以工具的使命提高编码效率, 让我们专注于业务开发 * Intelli IDEA智能生码插件, https://plugins.jetbrains.com/plugin/13576-d8gerautocode/[D8gerAutoCode] * Python脚本, 解决服务器、登录以及HTTP接口测试里的重复工作, https://github.com/caofanCPU/D8gerConcurrent[D8gerConcurrent] * Java开发者的福利, 炒鸡香的工具集, https://github.com/caofanCPU/D8gerStarters[D8gerStarters] - *捐赠|Donate*, **实践撰文分享**实属不易, 您的支持能为更多省时省事的分享提速, 如果💰不行, 那就帮上面的开源项目点量⭐吧, 谢谢! image::http://file.debuggerpowerzcy.top/power/D8WZ.png[] ================================================ FILE: IntelliJBestAction.html ================================================ IntelliJ IDEA最佳实践

IntelliJ IDEA最佳实践

  1. Intellij IDEA for Java WEB 开发

    • 快捷键

    • 插件

    • 快速测试

    • Java工具包

  2. Intellij IDEA for Scala 开发(ing)

  3. Intellij IDEA for Kotlin 开发(ing)

Note
如无特殊说明, 本文基于Mac OS 及Intellij IDEA 2020.1.x,
涉及系统或版本差异时会就近补充说明,
总体上: Mac的 cmd 等价于Windows的 ctrl ,
Intellij IDEA高版本功能是兼容低版本功能的, 只是部分插件会受到一些影响

快捷键

  • 找到所有快捷键, Help -→ Keymap Reference, 出现的PDF展示了当前你的编辑器的所有快捷键

  • 确实有点多, 不着急, 知道了方法, 后续只是时间问题. 如何搜索快捷键, 参见下图

Shortcut
Figure 1. 如何搜索快捷键
Table 1. 10个高频快捷键
功能 关键词 示例(默认)快捷键

①语句自动完成

Complete statement

cmd + shift + enter

②复写(父类)方法

Override methods | Generate

ctrl + O | ctrl + enter

③智能提示|纠错

Show Context Actions

ctrl + shift + alt + enter

④快速复制粘贴

Duplicate Line or Selection

cmd + D

⑤查看方法调用

Call Hierarchy

ctrl + alt + H

⑥跳转到父类申明

Go to Super Method

cmd + U

⑦跳转到子类实现

Go to Declaration or Usages

cmd + B

⑧拼接下一行

Join Lines

ctrl + shift + J

⑨优化导包

Optimize Imports

ctrl + alt + O

⑩格式化代码

Reformat Code

cmd + alt + L

更多彩蛋

安装插件 Key Promoter X

对于有快捷键的按钮, 当你点击时提示告诉你快捷键

插件

  • Key Promoter X

    • 快捷键提示, 新手必备, 而老手也可以通过它得知新版IDEA的一些特性信息

  • Rainbow Brackets

    • 代码括号自动匹配, 彩板护眼

  • Lombok

    • 这位都听说过吧, 没听过的要么是大佬要么改行吧

    • 采坑经验, 使用Lombok时, 尽量避免对象间继承, 如果非要继承, 应考虑@EqualsAndHashCode(callSuper = true : false)

    • 示例:

/**
 * balabala
 *
 * @author Mr.X
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class PormHub extends GitHub{
    private Boolean well = Boolean.FALSE;
}
  • AsciiDoc

    • 文档编辑神器, AsciiDoc本身目标是制作大型电子书, 超越MarkDown, 本文就是用AsciiDoc书写完成的

    • Spring官方、Spring-Alibaba官方都采用AsciiDoc撰写文档, GitHub也支持AsciiDoc, AsciiDoc是未来的主流, MarkDown貌似要成替补了

    • 个人使用体验, 对于写技术文档, 上手快, 简洁, 本文的一个小目标就是为新手提供常用的模块, 支持ctrl + c | v

AsciiDoc
Figure 2. AsciiDoc文档速览
  • Translation

    • 作为中国程序员, 英语不会咋办?

    • 安装该插件, 选中任意文本, ctrl + alt + T 一键翻译

  • iBATIS/MyBatis mini-plugin

    • 对于采用Mybatis且保留SQL的方式, 从Mapper接口跳转到对应SQL处, 可以借助该插件完成

    • 当然现在有很多采用无SQL的方式, 参见 苞米豆

  • MavenHelper

    • 国内Java工程多采用Maven来管理依赖, 对于一些不讲究的老项目, 依赖纠缠不清, 这个时候咋办?

    • 就这样, 凉拌吧!

    • 又或者, MavenHelper带你浴火重生, 请看下图

MavenHelper
Figure 3. MavenHelper特性速览
  • SequenceDiagram

    • 当我们跳槽后接坑时, 代码的链路是怎样的, 怎么没完没了呢?

    • 这个时候, SequenceDiagram带你一览全貌

    • 方法调用时序图出来了, 慢慢瞅吧!

SequenceDiagram
Figure 4. SequenceDiagram特性速览
  • D8gerAutoCode

    • 作为Web开发, 当业务理解清楚后, 开发过程就可以量化如下:

      1. 表设计

      2. SQL → Mapper → Mo → → handler → Service → Controller

      3. 自测

      4. 联调

      5. PM加需求, 再改一波…​

    • 在上诉步骤中, 我认为1、2、3步是自己可以控制的, 且步骤2中除了Service层代码由业务决定外, 其他基本代码基本如出一辙

    • 这意味着什么?

    • 据我的观察, 1-3年的大部分程序员就在写这些重复代码, 有时写错或者抄错了, 到调试时定位到问题, 真的浪费不少时间…​

    • 好在不少前辈通过创建工具, 以逆向工程方式生成生产环境可用的基础代码, 操作嘛也比较简单, 定义好SQL, 编写配置文件然后运行main方法生成

    • 我的编码生涯里也有不少这样的回忆, 只是里面仍旧有不少重复操作, 甚至多人操作时会产生冲突

    • 于是, 我从Mo出发, 写了D8gerAutoCode这个插件, 一切以表设计为核心, 你专注设计好Mo就可以, 其他基本代码使用快捷键一键搞定

    • 如果D8gerAutoCode只有这个功能, 那其实和其他大佬插件相比没有啥可比性, 大家都用习惯了, 为何要使用新的呢?

    • 重点来了: D8gerAutoCode插件专注解决重复, 在平常工作中的重复工作应该被简化, 在我看来, 程序的初衷不就是如此吗?

    • 所以, D8gerAutoCode插件还带有字符串批处理, JSON处理, MySQL处理, 字段命名处理, 针对SwaggerAPI文档的处理, 这些功能是项目开发中都会用到的, 本着一键搞定原则而开发, 欲知详情参见后文

D8Config
Figure 5. 插件配置
D8Generate
Figure 6. 生成代码
D8String
Figure 7. 字符串批处理
D8Format
Figure 8. 格式化
D8Regrex
Figure 9. 正则彩蛋

快速测试

  • 基于接口进行Http测试

  • 整合Swagger-API, 代码及文档, 且支持文档界面进行调试(ing, 后续补充对应的Java实现代码)

  • 项目中涉及登录权限等问题, 在HTTP测试时应尽量模拟全, 为前端联调创造真实环境

  • 辅助工具

function downLoadResponse() {
    echo "执行命令内容: \n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n"
    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}
}

function downLoadExcel() {
    echo "执行命令内容: \n    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}"
    http --verify=no -v --download  --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}
}

function show() {
    echo "执行命令内容: \n    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n"
    http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}
}

# 开发环境机器
function xDev() {
    # 借助sshpass工具, 将服务器密码保存在文件第一行, 实现自动登录; 且-t 参数支持登录后跳转到指定目录
    sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt  ssh Mr.X@xxx.xx.xx.${1}  -t  'cd /XXX/logs/; exec $SHELL'
}

# 将HTPP请求的响应结果存入指定文件中, 示例: https-downLoadResponse https://www.baidu.com/
alias https-downLoadResponse='downLoadResponse'
# 在控制台展示完整的HTTP请求过程, 响应打印在控制台, 示例: https-show https://www.baidu.com/
alias https-show='show'
# 对于文件下载, 通过输入参数指定下载后的文件名, 示例: https-downLoadExcel https://www.baidu.com/file/123456 D8ger.zip
alias https-downLoadExcel='downLoadExcel'
# 对于开发测试环境多服务器, 简化为: xDev 99, 则自动登录xxx.xx.xx。99服务器
alias 'xDev=xDev'
登录获取COOKIE
调用HTTP接口进行测试

IMPORT: 采用这种方法, 可以告别PostMan或PostWoman及其他软件了, 你只需要Intellij IDEA + iterm2|xshell + python环境

Java工具包

  • Intellij IDEA代码简化模板, 这个技巧很香的, 比如常见的判断字符串不为空, 我只需要敲下fsnb, 就会得到如下代码

if (StringUtils.isNotBlank(光标在这)) {

}

话不多说, 常用模板定义如下:
/apim : SwaggerModel字段属性模板

oin  : 对象为null         ==> Objects.isNull()
onn  : 对象不为null       ==> Objects.nonNull()
o2e  : 两对象相等          ==> Objects.equals(, )
one  : 两对象不相等        ==> !Objects.equals(, )
foin : 判断对象为null      ==> if (Objects.isNull()) {}
fonn : 判断对象不为null    ==> if (Objects.nonNull()) {}
fo2e : 判断两对象相等      ==> if (Objects.equals(, )) {}
fone : 判断两对象不相等    ==> if (!Objects.equals(, )) {}

cie  : 集合为空           ==> CollectionUtil.isEmpty()
cne  : 集合不为空          ==> CollectionUtil.isNotEmpty()
sib  : 字符串为空          ==> StringUtils.isBlank()
snb  : 字符串不为空        ==> StringUtils.isNotBlank()
fcie : 判断集合为空        ==> if (CollectionUtil.isEmpty()){}
fcne : 判断集合不为空      ==> if (CollectionUtil.isNotEmpty()){}
fsib : 判断字符串为空      ==> if (StringUtils.isBlank()) {}
fsnb : 判断字符串不为空    ==> if (StringUtils.isNotBlank()) {}
代码模板
  • 高频工具包, 推荐GitHub开源项目 D8gerStarters

    • 通用工具包子项目 spring-cloud-starter-d8ger-common-util

      1. 集合流式处理工具CollectionUtil, 分组、求和、排序应有尽有, 基本可以告别for循环

      2. 树形处理工具WrapTreeUtil, 列表与树的多种转换骚操作也是应有尽有, 并且具有无侵入性, 开箱即用

      3. 数字精度运算工具NumberUtil, 金额进度计算, 精准百分比

      4. 枚举处理规范IEnum, 为项目打好根基, 规范枚举值用

  • 中间件可插拔Starters整合工具包, 推荐GitHub开源项目 D8gerStarters

    • 通用工具包子项目 spring-cloud-starter-d8ger-web-util

      1. 整合常用中间件, 例如业务线程池、邮件、Redis缓存、RestTemplate调用、消息队列、接口响应消息转换器、SwaggerAPI文档处理器

      2. 开关型可插拔, 默认有一套经过大型生产环境检验过的配置, 支持通过配置文件更改配置

      3. 保留扩展点, 通过继承等方式覆盖原有组件

总结

  • 3个开源项目相辅相成, 目的与Spring等框架一致, 解决’最后一站’的重复问题, 以工具的使命提高编码效率, 让我们专注于业务开发

  • 捐赠|Donate, 实践撰文分享实属不易, 您的支持能为更多省时省事的分享提速, 如果💰不行, 那就帮上面的开源项目点量⭐吧, 谢谢!

D8WZ
================================================ FILE: LICENCE ================================================ Apache License Version 2.0, January 2019 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2019-2025 D8ger/DebuggerKing LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT http://www.apache.org/licenses/LICENSE-2.0 UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. ================================================ FILE: README.md ================================================ # D8gerAutoCode GitHub commit activity stars issues PRs Welcome open-source-organization license [![Stargazers over time](https://starchart.cc/caofanCPU/D8gerAutoCode.svg)](#) ## IDEA Code Automatically Generate Plugin • `For Java Version`
> [中文说明](./README_CN.md) ## Attention The latest version is **4.1** is approved by the official on 10th, May. If you can't fetch it, then [click here](https://github.com/caofanCPU/D8gerAutoCode/releases/tag/4.0) to download ~~.zip~~ file. Important: This version has been implemented [DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8). That is, some functions have been migrated to another plugin named [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao). After testing, installing two plugins will not affect performance. So, I hope you use happy and give me a 🌟, thx! ### Preface As JetBrains' said, I believe that you should be good use of tools will save you precious hours on your busing work. I always wonder, "If someone else has already solved the repeating work, why do I need to repeat it again?" Well, that's a valid question for my drive to find the repeat parts at daily work and develop this plugin to save my time. ### [Quick Start](http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/) ZN程序员福利 ### Convention - The general problem provides standard solutions - The personalized problem only provides example solutions ### Original design intention - Remove the fixed duplication coding for improving efficiency in development - Provide available code templates that can be used without modification - Support code directory configuration, only by self-guided package intelligent programming can be done in one-click - Support user-defined configuration, you can specify which file to be generated ### Features - ~~Camel-Underline-Uppercase-Uncapitalize-Lowercase can be converted to each other by shortcut~~ `alt` + `shift` + `cmd` + `U` - The comments of generated codes support English(Default) | Chinese Simplified(Optional) configuration - ~~JSON formatting and single line text conversion, supporting section and whole document, default shortcut~~ `alt`+`shift`+`cmd`+`J` | `S` - Generating `data table definition SQL` | `Mo` | `Mapper` | `Handler`, single table addition, deletion, modification and search with paging in one click - Under the help of SwaggerApi generating `Vo` | `Controller` with friendly document description, in addition to this, supporting `Vo` field automatic sorting - For smart coding, you just need one shortcut default as `alt`+`shift`+`cmd`+`D` - Supporting customer configuration, for example, specify the author who you are - Reserve easter eggs, you can try to edit the blank file in IDEA and type `d8ger` to get the default configuration template - ~~Reserve easter eggs, edit the blank file in IDEA and enter `nasa` to get the NASA configuration file template. This is very useful and efficient for handling multi-lines, especially SQL field naming processing.~~ - ~~Reserve easter eggs, edit the blank file in IDEA and enter `regex` to get some commonly used regular expressions. Other code Easter eggs will be added later.~~ - For automatic sorting `Vo` field , you just need one shortcut default as `alt`+`shift`+`cmd`+`O` ### Using manual(v3.0+) 1.Open the configuration box to set the generation parameters, `Preference` --> `Other Settings` --> `D8gerAutoCode` 2.Check the file to be generated and choose the generation path, rewrite `author`、`apiUrlPrefix` and `locale`, and click the button to save your configuration.
### Using manual(under v3.0) 1. Create Model Class 2. Select the class name and press the (default) shortcut `alt`+`shift`+`cmd`+`D` 3. Under the default configuration, `D8gerAutoCode` directory and `data table SQL definitions` and **Web codes** will be generated 4. So, What you need to do: - Under a multi-module project, configure the generated file output directory, for example, **`Mo.java`** should be moved into the `model` directory - Add non-null constraints to **`xx.sql`** as required - If you generated the **Controller.java** file, please note the interface returns type of **`Object`**, it should be modified to the project's uniform return type - In the above steps the `xx.java` file will report some errors, ***don't worry***, these just require you to import packages 5. Default configuration file template for easter egg: - In the ***`resource`*** root directory of the module where the `Model class` is located, create `d8ger.properties` property configuration file - Type `d8ger` and click on `Tools`-> `D8ger`-> `D8gerMore`, and you will find some surprise 6. ~~Regex template for easter egg:~~ - ~~Choose any blank file, Type `regex` and click on `Tools`-> `D8ger`-> `D8gerMore`, and you will find some surprise~~ 7. ~~NASA template for easter egg:~~ - ~~Choose any blank file, Type `nasa` and click on` Tools`-> `D8ger`-> `D8gerMore`, and you will get the NASA manual~~ - ~~Follow the manual, custom your config and write your own multi-lines need to be batch handled, then you will find some surprise~~ 8. ~~Camel-Underline-Uppercase-Uncapitalize-Lowercase circle convert by one-click~~ - ~~Choose word text in any editing file, press `alt` + `shift` + `cmd` + `U`, you`ll find the changed word~~ - ~~If not satisfied just press the shortcut again and again util you are.~~ 9. You will get the following default configuration information - It's recommended that you change the configuration items - `author` (you can't sign my name for the pits you dug!) - `apiUrlPrefix` (the interface url prefix should be configured as the project interface unified URL prefix) - generate file output directory under a multi-module project - As for `boolean` configuration items, let you choose which files need to be generated, and specify output directory is optional > By the way, these default shortcuts used in Mac OS, if you use Windows just take `cmd` into `ctrl`. ### How to install Get from Marketplace - `Preference` --> `Plugins` --> `Marketplace` --> type `D8` --> install - [IDEA official plugin library installation](https://plugins.jetbrains.com/plugin/13576-d8gerautocode) - As for `Source installation` requires you're familiar with Gradle, I will add more details about how to develop a plugin by ***Gradle*** later ### Bug & Question - Known issues > Modify the `d8ger.properties` file before generating code, the configuration file does not take effect ``` Solution 0. If you upgrade version 3.0+, you won`t see it again. 1. Because the IDEA file uses the VFS mechanism, as a plug-in to use the monitoring file I think it is not cost-effective 2. I also found a reason aboub editing .properties file, sometimes it will take one or two minutes to refresh after you finished 3. So, press `cmd` + `s` to force refreshing .properties file and you will solve it. ``` > The icon of plugin shows error like this: red square with a cross
``` Solution 1.This issue is caused by Intellij IDEA of new version feature. 2.Try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*), you'll fix it. ``` [Other issues, please come to join room](https://github.com/caofanCPU/D8gerAutoCode/issues) ### VersionRoadHistory - 4.1 - Fix 'D8gerAutoCode' error file path parsing while in WINDOWS system. For more detail, please refer [issue2](https://github.com/caofanCPU/D8gerAutoCode/issues/2) - 4.0(HIGH.START) - Important note: This time the function is migrated and upgraded, the plug-in has been divided into functions, the purpose is to be full-time and dedicated, and the general functions are sinking to serve more programmers - No.0: Each plug-in is positioned in two aspects, one is efficient coding, and the other is high-quality knowledge links to help users obtain enough useful information to improve their skills - No.1: [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao), **Published**, located JetBrains full product plug-in, General functions, covering text parsing, numerical processing, shell script processing - No.2: [D8gerAutoCode](https://github.com/caofanCPU/D8gerAutoCode), **Published**, located IntelliJ IDEA, auto coding - No.3: D8gerByteSleep, Hatching, located PyCharm - No.4: D8gerJustGo, Hatching, located GoLand - No.5: D8gerAndison, Hatching, located Android Studio - No.6: D8gerWebit, Hatching, located WebStorm - No.7: RoadMap refers [DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8) - Function migration: - BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore are migrated into plugin named [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao) - The shortcut keys and usage methods have not changed, only the code generation functions related to Java are retained - 3.4 - Addition: 'OhMyZSH' easter eggs, try to type 'ohmyzsh' in the blank file in IDEA to get some useful linux commands. I'm sure you'll save much time. - BugFix: Fix donate url(I'm waiting for your 🌟 the project on the github). - Optimization: 'BeautifulJSON', 'SimplifyOneLine' and 'BeautifulMySQL' now supports section or whole document convert. - 3.2 - BugFix: Fix 'BeautifulJSON' issue when parsing complex JSON string. - Optimization: 'CamelUnderlineConvert' now supports Timestamp-LocalDateTime convert, select the text and use origin shortcut `alt` + `shift` + `cmd` + `U` to find out. - 3.1 - BugFix: - Fix config item `locale` problem when selected as `ZN`, and before the 3.0 version`s comment was English default. - Fix SQL definition in x.sql file ✌️. - Fix batch insert records in xMapper.xml file cause `id`, `createTime`, `updateTime` all should be according to the Database. - Optimization: Config item `autoDetectSQLTimeColumn` now is more intelligent. If you checked, `createTime` and `updateTime` would be generated perfectly in there right position. - 3.0 - Addition: - Grand celebration for `D8gerAutoCode` getting his face! Now you can config the generated property parameters by setting GUI. - First, Open the configuration box to set the generation parameters, `Preference` --> `Other Settings` --> `D8gerAutoCode` - Then, Check the file to be generated and choose the generation path, rewrite `author`、`apiUrlPrefix` and `locale`, and click the button to save your configuration. - Optimization: Support project level setting parameters for non-invasive, d8ger.properties should exist invisible. - Adjustment: Remove the generated params by `d8ger.properties` file, replace of D8gerAutoCode setting GUI. - 2.5 - Addition: - Add `autoDetectSQLTimeColumn` configuration for supporting disable default generating `create_time` and `update_time` column definition in SQL. - Add `mapperBatterThenRepository` configuration for supporting custom mapper annotation in both SpringMVC and SpringBoot. - Add `selectOneByExample` in Mapper.java for supporting query one record. - Add `insertSelectiveWithId` in Mapper.java for supporting insert `non null` field and `null` field will be filled with the database default value. - Optimization: 'cause `id` is the primary key, all insert operations should exclude `id` column. - BugFix: - Generation `update_time` column definition remove the rare comma. - Troubleshooting the rare dir named `D8gerAutoCode`, now you can see it only with unspecified directory configuration. - Adjustment: Remove `ServiceInterface` and `ServiceImpl`, 'cause I think `Handler` is more suitable. - 2.4 - Addition: One-click to beauty MySQL, isn't fragrant? - Optimization: String parsing performance. - Attention: Select your MySQL text, ctrl + alt + shift + `B` will back a surprise. - 2.3 - BugFix: Json format bug. - Addition: - NASA easter eggs, try to type `nasa` in the blank file in IDEA to get the nasa-template. - NASA easter eggs, multi-lines can be batch handled with the nasa-template, special for sql columns. - Optimization: - Optimize some regex performance. - Support linebreak or comma as the delimiter. - Support windows linebreak when rendering origin code. - Attention: - When execute auto-coding, you should be careful at the linebreak, it maybe different from your project config. - Adjustment: - Icons changed for align, friendly view etc. - The manual of this plugin has been moved to my website. - 2.1 - BugFix: add Uncapitalize, and the circle is Camel-Underline-Uppercase-Uncapitalize-Lowercase. - Optimization: Optimize some regex performance. - Attention: Regex easter eggs add some very useful regex search-replace skills hidden in JetBrains's IDE products. Try to learn, and you will save much time at working. - 2.0 - BugFix: Modify method name in Controller.java. - Addition: - Remove repeat work of moving file into directories for smart coding. - Camel-Underline-Uppercase-Lowercase can be converted to each other by shortcut `alt` + `shift` + `cmd` + `U`. - Regex easter eggs, try to type `regex` in the blank file in IDEA to find it. - Optimization: Optimize source code and improve performance. - Attention: If the icon of plugin shows error(red square with a cross), try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*). - 1.24 - BugFix: Update method named `updateBatchByPrimaryKeySelective` in mapper.xml. - Addition: Set default language English and you can config it as Chinese Simplified, as before, typing `d8ger` for the latest configuration template. - Attention: You should configure your database connection like `allowMultiQueries=true` for supporting batchUpdate operation. - 1.23 - BugFix: Fix required dependencies by JetBrains's suggestion for some known compatibility issues. - Addition: Add JSON-formatter and WhiteChar-cleaner. - Attention: Can you 🌟 the project on the github? - 1.22 - BugFix: Fix README of style, description, picture problems. - Enhance: Enhance profile for generating codes by using regex to replace the circle of matching string. - Attention: Can you 🌟 the project on the github? - 1.21 - BugFix: Fix README of style, description, picture problems. - Addition: Add MoExample autoCoding for supporting simple sql. - Attention: Can you 🌟 the project on the github? - 1.20 - Completion: Auto coding for Mo/Example/Mapper/Xml/SQL/Service completed, wow! - Attention: Can you 🌟 the project on the github? ### Contribute - Please give me a 🌟 - Raise demand, write the repetitive problems you often handled at daily work in [issue](https://github.com/caofanCPU/D8gerAutoCode/issues) - Invite me to sit at the 🍦 shop

微信


支付宝


MiXin

### Thanks JetBrains
With JetBrains team's open source certificate supporting, this project will continue to develop in the spirit of open source
================================================ FILE: README_CN.md ================================================ # D8gerAutoCode GitHub commit activity stars issues PRs Welcome open-source-organization license [![Stargazers over time](https://starchart.cc/caofanCPU/D8gerAutoCode.svg)](#) ## IDEA代码自动生成插件•`Java版本`
## 说明 最新版本为**4.1**, 在 _**`05月10号`**_ 通过官方审核 如果无法获取, [戳此](https://github.com/caofanCPU/D8gerAutoCode/releases/tag/4.1) 下载~~.zip~~压缩包 如果用的不错, 给我点个🌟呗, thx! 重要: 本版本已执行[DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8). 即部分功能已迁入另一个插件[LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao). 经过测试, 安装两个插件一本不会影响性能, 还请小伙伴们支持 ### 序言 正如JetBrains所说, 我相信你在繁忙编码工作中时应该善用工具以节省宝贵的时间。 我时常在思考, "如果其他人已经解决了这些重复工作, 为什么我还需要重复解决?" 这个问题一直驱动着我, 在日常工作中探寻重复部分并开发此插件以节省时间。 ### [快速开始](http://www.debuggerpowerzcy.top/home/2020/03/14/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/) ZN程序员福利, IntelliJ IDEA最佳实践 ### 约定 - 通用问题提供规范解法 - 个性化问题只提供示例解法 ### 设计初衷 - 移除开发中的固定的重复编码过程, 提升开发效率 - 提供可用的代码模板, 基本不用修改就可使用的代码 - 支持代码目录配置, 一键自动生成代码, 仅需自行导包即可完成智能编程 - 支持用户自定义配置, 可指定需要生成的文件 ### 功能特性 - ~~驼峰-下划线-大写-首字母小写-小写, 时间戳与标准时间字符串(香!), 一键转换, 默认快捷键~~ `alt` + `shift` + `cmd` + `U` - 生成代码的注释支持英语|汉语配置 - ~~JSON格式化与单行文本转换, 默认快捷键~~ `alt`+`shift`+`cmd`+`J` | `S` - 一键生成`数据表定义SQL` | `Mo` | `Mapper` | `Handler`, 单表增删改查+分页一键搞定 - 结合SwaggerApi, 一键生成带文档定义`Vo`及`Controller`, 支持Vo字段自动排序 - 一键智能编程, 默认快捷键 `alt`+`shift`+`cmd`+`D` - 支持用户自定义配置, 指定生成哪些文件及文件author等 - 预留彩蛋, 在IDEA中编辑空白文件输入`d8ger`即可得到配置文件模板 - ~~预留彩蛋, 在IDEA中编辑空白文件输入`nasa`即可得到NASA模板, 针对多行字符串批量处理, 尤其是SQL字段命名处理~~ - ~~预留彩蛋, 在IDEA中编辑空白文件输入`regex`即可得到一些常用的有趣正则表达式, 后期会增加其他代码彩蛋~~ - SwaggerVo字段排序, 默认快捷键 `alt`+`shift`+`cmd`+`O` ### 使用手册(v3.0+) 1.打开配置框设置生成参数 `Preference` --> `Other Settings` --> `D8gerAutoCode` 2.勾选要生成的文件及生成路径, 指明 `author`、`apiUrlPrefix`、`locale`, 保存即可
### 使用手册(v3.0以下) 1. 创建Model类 2. 选中类名, 按下(默认)快捷键 `alt`+`shift`+`cmd`+`D` 3. 默认配置下, 会生成`D8gerAutoCode`目录及数据表SQL定义和Web代码, 共9个 4. 你需要做的: - 多模块工程下, 配置生成文件输出目录, 例如 **`Mo.java`** 配置`model`目录 - 根据需求对 **`xx.sql`** 增加非空约束 - 如果你生成了 **`Controller.java`** 文件, ***请注意接口返回对象类型***, 应修改为项目统一的返回类型 - 在上述步骤中, 代码文件会飘红报错, 别慌, 这需要你自行导包解决 5. 默认配置文件模板, 代码彩蛋: - 在`Model类`所在模块的 ***`resource`*** 根目录下, 创建`d8ger.properties`属性配置文件 - 输入`d8ger`并点击`Tools`-->`D8ger`-->`D8gerMore` 6. ~~正则表达式模板, 代码彩蛋:~~ - ~~任意空文本, 输入`regex`并点击`Tools`->`D8ger`->`D8gerMore`, 你会得到一点小惊喜~~ 7. ~~NASA模板(多行文本批处理), 代码彩蛋:~~ - ~~任意空文本, 输入`nasa`并点击`Tools`->`D8ger`->`D8gerMore`, 你会得到NASA操作手册~~ - ~~按照NASA手册提示, 自定义配置并输入需要处理的多行文本, 然后你会得到一点小惊喜~~ 8. ~~驼峰-下划线-大写-首字母小写-小写, 一键循环转换~~ - ~~选中任意编辑状态下文件里的单词, 按下快捷键`alt` + `shift` + `cmd` + `U`, 你会发现选中单词转换了~~ - ~~如果不是你想要的结果那就继续重复按下快捷键, 直到是你想要的为止~~ 9. 你就得到如下默认配置信息 - 推荐你更改的配置项 - `author`(你挖的坑可不许署我的名!) - `apiUrlPrefix`(接口url前缀应配置为项目接口统一Url前缀) - 多模块工程下, 生成文件输出目录 - 其他`boolean`配置项, 是让你选择需要生成哪些文件, 可选指定输出目录 >以上默认快捷键针对MacOS系统, 对于Windows用户将`cmd`看做`ctrl`即可 ### 如何安装 Get from Marketplace - `Preference` --> `Plugins` --> `Marketplace` --> type `D8` --> install - [IDEA官方插件库安装](https://plugins.jetbrains.com/plugin/13576-d8gerautocode) - 源码安装, 这需要你熟悉Gradle, 后期我会详细补充如何使用Gradle开发一个插件 ### Bug&问题 - 已知问题(最新版本3.0中已修复) >修改`d8ger.properties`文件后再生成代码, 配置文件不生效 ``` 解决方法 0.升级到3.0及以上版本, 该问题不复存在 1.由于IDEA文件采用VFS机制, 作为一个插件去采用监听文件我认为是不合算的 2.此外, 编辑.properties文件时, 内容变更有时会消耗1-2分钟才会更新生效 3.所以, 执行快捷键`cmd` + `s`强制刷新.properties文件, 即可解决 ``` > 插件图标显示异常, 图标内只出现相交的红叉
``` 1.这是Intelij IDEA新版本特性遗留的兼容性小BUG 2.升级Intelij IDEA版本, 至少为2019.3.*(2019.2.*及以下都会显示异常) ``` [其他问题, 欢迎前来查房](https://github.com/caofanCPU/D8gerAutoCode/issues) ### 版本演进历史 - 4.1 - Bug修复: 修复'D8gerAutoCode'在WINDOWS系统中文件路径解析错误的问题, 参见[issue2](https://github.com/caofanCPU/D8gerAutoCode/issues/2) - 4.0(HIGH.START) - 重要提示: 本次进行功能迁移升级, 插件已进行功能拆分, 目的是专职专责, 通用功能下沉以服务主流编程语言的程序YUAN - No.0: 每个插件定位两方面, 一是高效编码, 二是高质量的知识链接, 帮助用户获取足够有用的信息, 以提高技能 - No.1: [LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao), **已发布**, 坐标JetBrains全产品插件, 通用功能, 涵盖文本解析, 数值处理, shell脚本处理 - No.2: [D8gerAutoCode](https://github.com/caofanCPU/D8gerAutoCode), **已发布**, 坐标IntelliJ IDEA插件, 智能生码 - No.3: D8gerByteSleep, 孵化中, 坐标PyCharm插件 - No.4: D8gerJustGo, 孵化中, 坐标GoLand插件 - No.5: D8gerAndison, 孵化中, 坐标Android Studio插件 - No.6: D8gerWebit, 孵化中, 坐标WebStorm插件 - No.7: 插件RoadMap参见[DSP(D8ger Series Plan)](https://www.processon.com/view/5f96a5f35653bb06ef1870e8) - 功能迁移: - BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore均迁移至插件[LaoYouTiao](https://github.com/caofanCPU/LaoYouTiao) - 快捷键及使用方法均未改变, 仅保留与Java相关的生码功能 - 3.6 - 体验优化: 修改插件LOGO - 3.4 - 新增功能: 'OhMyZSH' 彩蛋, 空白文件中输入 'ohmyzsh' 将获得一些有用的linux命令工具及使用技巧. 这将节省你不少时间. - Bug修复: 修复donate链接(铁子, 等着你🌟该项目, thx!). - 体验优化: 'BeautifulJSON', 'SimplifyOneLine' 和 'BeautifulMySQL' 现在同时支持部分和整个文件内容转换. - 3.2 - Bug修复: 修复'BeautifulJSON'在解析复杂JSON字符串时的问题 - 体验优化: 'CamelUnderlineConvert' 支持时间戳与标准时间字符串相互转换 - 3.1 - Bug修复: - 修复配置项`locale`为中文时不生效的问题, 在之前的3.0版本只能生成英文注释. - 修复x.sql中在某些情况下因缺失`,`导致报错的问题. - 批量插入记录, 字段`id`, `createTime`, `updateTime`将被忽略强制采用数据库的默认值. - 体验优化: 配置项`autoDetectSQLTimeColumn`现在更加智能. 当你勾选改配置项时, `createTime` and `updateTime`字段将会自动填充到合适的位置. - 3.0 - 新增功能: - 很高兴宣布插件`D8gerAutoCode`终于有脸(面)了! 现在你将通过设置界面配置生码参数. - 第一步, 打开设置界面, `Preference` --> `Other Settings` --> `D8gerAutoCode` - 第二步, 勾选你要生成的文件并指明文件生成后所在目录, 填写`author`、`apiUrlPrefix` and `locale`, 保存就完事了. - 体验优化: 使用项目级别的界面配置, 对用户的代码无任何侵入性. - 功能调整: 移除`d8ger.properties`配置文件, 一键生码配置参数将通过D8gerAutoCode设置GUI完成. - 2.5 - 新增功能: - 新增配置项`autoDetectSQLTimeColumn`用以支持`create_time`和`update_time`字段的自动探测定义. - 新增配置项`mapperBatterThenRepository`用以支持`SpringMVC`和`SpringBoot`下的`mapper`注解. - 在Mapper.java文件中新增`selectOneByExample`方法用以支持根据条件查询单条记录, 慢走不送: `xList.get(0)`. - 在Mapper.java文件中新增`insertSelectiveWithId`用以支持只插入非NULL字段, NULL字段将采用数据库默认值. - 体验优化: 考虑到`id`是约定的主键字段, 所有插入操作都应该排除该字段. - Bug修复: - 在x.sql文件定义中, `update_time`在某些情况下会出现多余的`,`. - 颇费周折地抓获冗余目录`D8gerAutoCode`莫名出现的现场, 现在只有在你未指明生成目录的情况下才能遇到他, 版本不停步, 且用且珍惜. - 功能调整: 去除`ServiceInterface`和`ServiceImpl`, 因为针对自动生码的通用性而言`Handler`将更合适. - 2.4 - 新增功能: 一键美化SQL, 不香吗? - 体验优化: 优化字符串解析性能. - TheShy提示: 选中MySQL文本, 快捷键ctrl + alt + shift + `B`将奉上惊喜. - 2.3 - Bug修复: Json字符串格式化的问题. - 新增功能: - NASA彩蛋, 空白文件中输入`nasa`获取模板. - NASA彩蛋, 支持字符串批处理, 例如多行文本对齐, 提供SQL格式化及自动生成别名功能, 搞数据分析的小伙伴值得一试. - 体验优化: - 优化正则处理性能. - 支持换行符作为分割符. - 针对Windows系统, 字符串批处理结果渲染时使用Windows换行符. - TheShy提示: - 运行自动生码前, 请留意IDE项目默认换行符配置. - 功能调整: - 插件功能图标调整对齐. - 插件使用指南搬迁到我的博客. - 2.1 - Bug修复: 补充一键首字母小写转换功能, 完成字段命名闭环: 驼峰-下划线-全大写-首字母小写-全小写. - 体验优化: 优化一些正则处理的性能. - TheShy提示: 正则神器彩蛋中增加IDEA自带的高效查找与替换功能, 花点时间瞄一瞄, 之后工作快到飞起. - 2.0 - Bug修复: 修改Controller.java文件中方法名. - 新增功能: - 通过配置指定文件生成目录, 不用再手动拖入目录了, 就应该是这样的, 重复工作应该被剔除. - 驼峰-下划线-大写-小写一键转化: `alt` + `shift` + `cmd` + `U`. - 空白文件中输入`regex` 获取正则神器菜单. - 体验优化: 代码优化与性能优化. - TheShy提示: 如果插件图标出现红叉, 这是IDEA版本不兼容引起的, 将IDEA版本升级至2019.3.*(至少是2019.2.*以后). - 1.24 - Bug修复: mapper.xml文件中 `updateBatchByPrimaryKeySelective` SQL生成修复. - 新增功能: 空白文件中输入`d8ger`以获取最新模板参数配置, 该版本支持代码注释中英文, 默认英文. - TheShy提示: **对于批量更新功能, 数据库连接参数必须开启该功能: `allowMultiQueries=true`**. - 1.23 - Bug修复: 修复Intellij版本间的依赖包兼容问题. - 新增功能: 新增一键JSON美化和一键剔除空白字符. - TheShy提示: 老铁, 点亮一颗🌟可好? - 1.22 - Bug修复: 修正图片及文档格式. - 体验优化: 使用正则匹配取缔原有循环处理以提升性能 - TheShy提示: 小伙伴, 点亮一颗🌟可好? - 1.21 - Bug修复: 修正图片及文档格式. - 新增功能: 新增MoExample查询条件对象以支持简单查询. - TheShy提示: 同学, 点亮一颗🌟可好? - 1.20 - 首发上阵: 一键自动生成Mo/Example/Mapper/Xml/SQL/Service 完成, wow! - TheShy提示: 少年, 点亮一颗🌟可好? ### 参与贡献 - 帮我点亮一颗🌟 - 提需求, 在[issue](https://github.com/caofanCPU/D8gerAutoCode/issues)描述工作中经常处理的重复问题 - 请我到🍦店坐坐

微信


支付宝


MiXin

### 致谢 JetBrains
感谢JetBrains团队的开源证书支持, 本项目将秉承开源精神持续开发
================================================ FILE: build.gradle ================================================ plugins { id 'java' id 'org.jetbrains.intellij' version '0.4.21' } group 'com.xyz.caofancpu' version '4.1' sourceCompatibility = 1.8 repositories { mavenCentral() maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' } maven { url 'https://repo1.maven.org/maven2/' } } tasks.withType(JavaCompile) { options.encoding = "UTF-8" } apply plugin: 'idea' apply plugin: 'org.jetbrains.intellij' apply plugin: 'java' //task myRun(type: JavaExec) { // classpath sourceSets.main.runtimeClasspath // main = "com.xyz.caofancpu.d8ger.action.D8gerSetting" //} // 自定义task跑代码 task D8ENV { println('帝八哥正在编译插件....') // println "$System.env.IDEA_HOME" println("IDEA安装环境目录: " + System.getenv("IDEA_HOME")) println("更新IDEA后, 别忘修改变量\$IDEA_HOME") } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' annotationProcessor 'org.projectlombok:lombok:1.18.10' compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.10' compile group: 'commons-io', name: 'commons-io', version: '1.3.2' compile group: 'commons-collections', name: 'commons-collections', version: '3.2.2' compile group: 'ru.lanwen.verbalregex', name: 'java-verbal-expressions', version: '1.8' compile group: 'com.alibaba', name: 'druid', version: '0.2.9' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' } // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { // version '2019.1.4' // Adjust when toolbox update IDEA app localPath System.getenv("IDEA_HOME") plugins = ['java'] //Bundled plugin dependencies pluginName 'D8gerAutoCode' updateSinceUntilBuild false sandboxDirectory = "${project.rootDir}/.sandbox" } patchPluginXml { changeNotes """ What encounter to pain me ever belongs to see you now.

Plug-in new revision, new features and high performance.
One-click to handle multi-lines, isn't cool?
One-click to beauty MySQL, isn't fragrant?
It's very sure that you deserve to use.
""" } ================================================ FILE: doc/ComputerMathData.md ================================================ # MarkDown 数学公式语法大全 - 单行左对齐公式 $\sum_{i=0}^N\int_{a}^{b}g(t,i)\text{d}t$ - 跨行居中公式 $$ \sum_{i=0}^N\int_{a}^{b}g(t,i)\text{d}t $$ - 无边框矩阵 $$ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{matrix} $$ - 小括号边框矩阵 $$ \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} $$ - 大括号边框矩阵 $$ \begin{Bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{Bmatrix} $$ - 双竖线边框矩阵 $$ \begin{Vmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{Vmatrix} $$ - 中括号边框矩阵 $$ \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} $$ - 行列式边框矩阵 $$ \begin{vmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{vmatrix} $$ - m*n省略号矩阵 $$ \begin{bmatrix} {a_{11}}&{a_{12}}&{\cdots}&{a_{1n}} \\ {a_{21}}&{a_{22}}&{\cdots}&{a_{2n}} \\ {\vdots}&{\vdots}&{\ddots}&{\vdots} \\ {a_{m1}}&{a_{m2}}&{\cdots}&{a_{mn}} \\ \end{bmatrix} $$ - 常用集合符号函数矩阵 $$ \begin{bmatrix} {\sin x}&{\ln x}&{\max(A,B)}&{\infty}&{\cup} \\ {\cap}&{\subset}&{\subseteq}&{\supset}&{\in} \\ {\notin}&{\varnothing}&{\forall}&{\exists}&{\lnot} \\ {\nabla}&{\partial}&{a \quad b}&{a \ b}&{a_{xyz}} \\ \end{bmatrix} $$ - 常用微积分符号矩阵 $$ \begin{pmatrix} {\sum_{i=1}^n{a_i}}&{\prod \frac{1}{i^2}}&{\lim_{x\to 0}}&{\prime} \\ {\int_0^\infty{f(x)dx}}&{\mathrm{d}}&{\int ^2_3 x^2 {rm d}x}&{\iint} \\ {\iiiint}&{\oint}{\frac{x}{y}}&&{\sqrt[x]{y}} \\ \end{pmatrix} $$ - 泰勒级数 $$ e^{x} = 1 + \frac{x}{1!} + \frac{x^{2}}{2!} + \frac{x^{3}}{3!} + \cdots , \quad - \infty < x < \infty $$ - 余弦公式 $$ \cos 2\theta = \cos^2 \theta - \sin^2 \theta = 2 \cos^2 \theta $$ - 集合公式 $$ M(\beta^{\ast}(D),D) \subseteq C $$ - 求和公式 $$ \sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6} $$ - 平方根公式 $$ x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$ - 条件函数 $$ f(n) = \begin{cases} \frac{n}{2}, & \text{if $n$ is even} \\ 3n+1, & \text{if $n$ is odd} \end{cases} $$ - 偏导数公式 $$ \begin{equation} \begin{split} \frac{\partial^2 f}{\partial{x^2}} &= \frac{\partial(\Delta_x f(i,j))}{\partial x} = \frac{\partial(f(i+1,j)-f(i,j))}{\partial x} \\ &= \frac{\partial f(i+1,j)}{\partial x} - \frac{\partial f(i,j)}{\partial x} \\ &= f(i+2,j) -2f(f+1,j) + f(i,j) \end{split} \nonumber \end{equation} $$ - 统计学公式带编号 $$ \begin{equation} \sum_{i=0}^n F_i \cdot \phi (H, p_i) - \sum_{i=1}^n a_i \cdot ( \tilde{x_i}, \tilde{y_i}) + b_i \cdot ( \tilde{x_i}^2 , \tilde{y_i}^2 ) \tag{1.2.3} \end{equation} $$ $$ \begin{equation} \beta^*(D) = \mathop{argmin} \limits_{\beta} \lambda {||\beta||}^2 + \sum_{i=1}^n max(0, 1 - y_i f_{\beta}(x_i)) \tag{1.2.4} \end{equation} $$ $$ \begin{equation} \sum_{i=0}^n F_i \cdot \phi (H, p_i) - \sum_{i=1}^n a_i \cdot ( \tilde{x_i}, \tilde{y_i}) + b_i \cdot ( \tilde{x_i}^2 , \tilde{y_i}^2 ) \tag{1.2.5} \end{equation} $$ $$ \beta^*(D) = \mathop{argmin} \limits_{\beta} \lambda {||\beta||}^2 + \sum_{i=1}^n max(0, 1 - y_i f_{\beta}(x_i)) \tag{1.2.6} $$ $$z = (p_0, ..... , p_n) \tag{公式21} $$ $$ s = r cos(a+b) = r cos(a) cos(b) - r sin(a) sin(b) \tag{1.1} $$ $$ t = r sin(a+b) = r sin(a) cos(b) - r cos(a) sin(b) \tag{1.2} $$ - 极限 $$ \max \limits_{a Google 搜索**自动补全功能**的强大,相信不少朋友都能感受到,它帮助我们更快地“补全”我们所要输入的搜索关键字。那么,它怎么知道我们要输入什么内容?它又是如何工作的?在这篇文章里,我们一起来看看。 ## 使用自动补全 Google 搜索的自动补全功能可以在 Google 搜索应用的大多数位置使用,包括 [Google](https://www.google.com/) 主页、适用于 IOS 和 Android 的 Google 应用,我们只需要在 Google 搜索框上开始键入关键字,就可以看到联想词了。 ![](https://imgkr.cn-bj.ufileos.com/17ed83bf-e028-4db2-9503-5a3b4e64deee.gif) 在上图示例中,我们可以看到,输入关键字 `juej`,Google 搜索会联想到“掘金”、“掘金小册”、“绝句”等等,好处就是,我们无须输入完整的关键字即可轻松完成针对这些 topics 的搜索。 谷歌搜索的自动补全功能对于使用移动设备的用户来说特别有用,用户可以轻松在难以键入的小屏幕上完成搜索。当然,对于移动设备用户和台式机用户而言,这都节省了大量的时间。根据 Google 官方报告,自动补全功能可以减少大约 25% 的打字,累积起来,预计每天可以节省 200 多年的打字时间。是的,每天! > 注意,本文所提到的“**联想词**”与“**预测**”,是同一个意思。 ## 基于“预测”而非“建议” Google 官方将自动补全功能称之为“预测”,而不是“建议”,为什么呢?其实是有充分理由的。自动补全功能是为了**帮助用户完成他们打算进行的搜索**,而不是建议用户要执行什么搜索。 那么,Google 是如何确定这些“预测”的?其实,Google 会根据趋势搜索 [trends](https://trends.google.com/trends/?geo=US) 给到我们这些“预测”。简单来说,哪个热门、哪个搜索频率高,就更可能推给我们。当然,这也与我们当前所处的位置以及我们的搜索历史相关。 另外,这些“预测”也会随着我们键入的关键字的变更而更改。例如,当我们把键入的关键字从 `juej` 更改为 `juex` 时,与“掘金”相关的预测会“消失”,同时,与“觉醒”、“决心”相关联的词会出现。 ![](https://imgkr.cn-bj.ufileos.com/5b17dc99-606d-42c1-9f86-e09e88aaa822.gif) ## 为什么看不到某些联想词? 如果我们在输入某个关键字时看不到联想词,那么表明 Google 的算法可能检测到: - 这个关键字不是热门字词; - 搜索的字词太新了,我们可能需要等待几天或几周才能看到联想词; - 这是一个侮辱性或敏感字词,这个搜索字词违反了 Google 的相关政策。更加详细的情况,可以了解 [Google 搜索自动补全政策](https://support.google.com/websearch/answer/7368877)。 ## 为什么会看到某些不当的联想词? Google 拥有专门设计的系统,可以自动捕获不适当的预测结果而不显示出来。然而,Google 每天需要处理数十亿次搜索,这意味着 Google 每天会显示数十亿甚至上百亿条预测。再好的系统,也可能存在缺陷,不正确的预测也可能随时会出现。 我们作为 Google 搜索的用户,如果认定某条预测违反了相关的搜索自动补全政策,可以进行举报反馈,点击右下角“**举报不当的联想查询**”并勾选相关选项即可。 ![](https://imgkr.cn-bj.ufileos.com/6ca8185d-12c6-4550-bb4e-e49cfbf56db7.gif) ## 如何实现自动补全算法? 目前,Google 官方似乎并没有公开搜索自动补全的算法实现,但是业界在这方面已经有了不少研究。 一个好的自动补全器必须是快速的,并且在用户键入下一个字符后立即更新联想词列表。**自动补全器的核心是一个函数,它接受输入的前缀,并搜索以给定前缀开头的词汇或语句列表**。通常来说,只需要返回少量的数目即可。 接下来,我们先从一个简单且低效的实现开始,并在此基础上逐步构建更高效的方法。 ### 词汇表实现 一个**简单粗暴的实现方式**是:顺序查找词汇表,依次检查每个词汇,看它是否以给定的前缀开头。 但是,此方法需要将前缀与每个词汇进行匹配检查,若词汇量较少,这种方式可能勉强行得通。但是,如果词汇量规模较大,效率就太低了。 一个**更好的实现方式是**:让词汇按字典顺序排序。借助二分搜索算法,可以快速搜索有序词汇表中的前缀。由于二分搜索的每一步都会将搜索的范围减半,因此,总的搜索时间与词汇表中单词数量的对数成正比,即时间复杂度是 `O(log N)`。二分搜索的性能很好,但有没有更好的实现呢?当然有,往下看。 ### 前缀树实现 通常来说,许多词汇都以相同的前缀开头,比如 `need`、`nested` 都以 `ne` 开头,`seed`、`speed` 都以 `s` 开头。要是为每个单词分别存储公共前缀似乎很浪费。 ![](https://imgkr.cn-bj.ufileos.com/7cc3cf37-040a-420e-8ef9-d05e92c82cfd.png) 前缀树是一种利用公共前缀来加速补全速度的数据结构。前缀树在节点树中排列一组单词,单词沿着从根节点到叶子节点的路径存储,树的层次对应于前缀的字母位置。 前缀的补全是顺着前缀定义的路径来查找的。例如,在上图的前缀树中,前缀 `ne` 对应于从子节点取左边缘 `N` 和唯一边缘 `E` 的路径。然后可以通过继续遍历从 `E` 节点可以达到的所有叶节点来生成补全列表。在图中,`ne` 的补全可以是两个分支:`-ed` 和 `-sted`。如果在数中找不到由前缀定义的路径,则说明词汇表中不包含以该前缀开头的单词。 ### 有限状态自动机(DFA)实现 前缀树可以有效处理公共前缀,但是,对于其他共享词部分,仍会分别存储在每个分支中。比如,后缀 `ed`、`ing`、`tion` 在英文单词中特别常见。在上一个例子中,`e`、`d` 分别存放在了每一个分支上。 有没有一种方法可以更加节省存储空间呢?有的,那就是 DFA。
在上面的例子中,单词 `need`、`nested`、`seed` 和 `speed` 仅由 9 个节点组成,而上一张图中的前缀树包含了 17 个节点。 可以看出,最小化前缀树 DFA 可以在很大程度上减少数据结构的大小。即使词汇量很大,最小化 DFA 通常也适合在内存中存储,避免昂贵的磁盘访问是实现快速自动补全的关键。 ### 一些扩展 上面介绍了如何利用合理的数据结构实现基本的自动补全功能。这些数据结构可以通过多种方式进行扩展,从而改善用户体验。 通常,满足特定前缀的词汇可能很多,而用户界面上能够显示的却不多,我们更希望能显示最常搜索或者最有价值的词汇。这通常可以通过为词汇表中的每个单词增加一个代表单词值的**权重** `weight`,并且按照权重高低来排序自动补全列表。 - 对于排序后的词汇表来说,在词汇表每个元素上增加 `weight` 属性并不难; - 对于前缀树来说,将 `weight` 存储在叶子节点中,也是很简单的一个实现; - 对于 `DFA` 来说,则较为复杂。因为一个叶子节点可以通过多条路径到达。一种解决方案是将权重关联到路径而不是叶子节点。 目前有不少开源库都提供了这个功能,比如主流的搜索引擎框架 [Elasticsearch](https://www.elastic.co/products/elasticsearch)、[Solr](https://lucene.apache.org/solr/) 等,基于此,我们可以实现高效而强大的自动补全功能。 #### 推荐阅读 - [A: 原文链接](https://doocs.github.io/md/) - [阿里又一个 20k+ stars 开源项目诞生,恭喜 fastjson!](https://mp.weixin.qq.com/s/RNKDCK2KoyeuMeEs6GUrow) - [刷掉 90% 候选人的互联网大厂海量数据面试题(附题解 + 方法总结)](https://mp.weixin.qq.com/s/rjGqxUvrEqJNlo09GrT1Dw) - [好用!期待已久的文本块功能究竟如何在 Java 13 中发挥作用?](https://mp.weixin.qq.com/s/kalGv5T8AZGxTnLHr2wDsA) - [2019 GitHub 开源贡献排行榜新鲜出炉!微软谷歌领头,阿里跻身前 12!](https://mp.weixin.qq.com/s/_q812aGD1b9QvZ2WFI0Qgw) - [哈哈](http://file.debuggerpowerzcy.top/power/) --- 欢迎关注我的公众号“**Doocs开源社区**”,原创技术文章第一时间推送。
``` Next generation plan (backup: autoCode -> { (MAPPER + XML层) var1: insertWithIdSelective selectByExampleWithBLOBs updateByExampleWithBLOBs updateByPrimaryKeyWithBLOBs (SERVICE层) selectByPrimaryKey deleteByPrimaryKey updateByPrimaryKey var2: @ID, @SECOND_MAIN_KEY @UNIQ(group, order), @INDEX, @UNIQ_INDEX(group, order), @NOTNULL, @DEFAULT, @BLOB var3: CreateTime | UpdateTime(, bug?) 禁用配置 var4: caofanCPU-branch, private var5: digital automatic var6: bug fix, d8gerDir? }) 优先级 1.XML insertWithIdSelective 2.CreateTime | UpdateTime(, bug?) 禁用配置 3.Example支持limit 1 索引及其他标识, 交由用户自定义 大文本后期再处理 pid=`ps aux |grep newreport |grep -v grep| awk '{print }'` if [ -n "$pid" ];then kill -9 $pid sleep 5 fi rm -rf newreport-*.jar scp ``` ================================================ FILE: settings.gradle ================================================ rootProject.name = 'D8gerAutoCode' ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/WhoAmI.java ================================================ package com.xyz.caofancpu.d8ger; /** * Who You Are? */ public class WhoAmI { /** * ID */ private Long id; private Integer age; private String name; } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/action/D8gerAutoCodeAction.java ================================================ package com.xyz.caofancpu.d8ger.action; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiJavaFile; import com.xyz.caofancpu.d8ger.core.AutoCodeTemplate; import com.xyz.caofancpu.d8ger.core.D8gerAutoCoding; import com.xyz.caofancpu.d8ger.core.KeyEnum; import com.xyz.caofancpu.d8ger.core.ProjectEnvHandler; import com.xyz.caofancpu.d8ger.core.TemplateKeyWordEnum; import com.xyz.caofancpu.d8ger.util.CollectionUtil; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import com.xyz.caofancpu.d8ger.util.IdeaPlatformFileTreeUtil; import com.xyz.caofancpu.d8ger.util.PropertiesUtil; import lombok.NonNull; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; /** * ACP(AutoCodingProgramming) * * @author caofanCPU */ public class D8gerAutoCodeAction extends AnAction { @Override public synchronized void actionPerformed(@NonNull final AnActionEvent e) { D8gerAutoCoding d8gerAutoCoding = ProjectEnvHandler.checkAndInitEnv(e); if (Objects.isNull(d8gerAutoCoding)) { return; } // Create directory | file WriteCommandAction.runWriteCommandAction(d8gerAutoCoding.getCurrentProject(), () -> generateAutoCodeFile(d8gerAutoCoding)); } /** * Perform file creation, all directory | file write operations must be inside this method, * and externally use WriteCommandAction.runWriteCommandAction for wrapping * * @param d8gerAutoCoding */ public void generateAutoCodeFile(D8gerAutoCoding d8gerAutoCoding) { List fileNameList = new ArrayList<>(); // 1.Complete directory and package data d8gerAutoCoding.getFileMap().keySet().forEach(key -> { Pair packagePair = d8gerAutoCoding.getCustomConfigAutoCodeDirMap().get(key); if (Objects.isNull(packagePair)) { if (d8gerAutoCoding.getRealNeedCreateFileKeyList().contains(key) && !d8gerAutoCoding.isUseDefaultDirectory()) { // Create D8AutoCode directory PsiDirectory d8gerAutoCodeDir = IdeaPlatformFileTreeUtil.getOrCreateSubDir(d8gerAutoCoding.getD8AutoCodeDir(), ConstantUtil.GENERATE_DIR); d8gerAutoCoding.setD8AutoCodeDir(d8gerAutoCodeDir); d8gerAutoCoding.setUseDefaultDirectory(true); fileNameList.add(d8gerAutoCoding.getD8AutoCodeDir().getName()); } d8gerAutoCoding.getCustomConfigAutoCodeDirMap().put(key, Pair.of(d8gerAutoCoding.getD8AutoCodeDir(), d8gerAutoCoding.getPackageName())); } }); // 2.Replace keyword data handleCustomPackageKeyWordMap(d8gerAutoCoding); // 3.Just force file d8gerAutoCoding.getFileMap().forEach((key, pair) -> { if (skipCurrentOperation(d8gerAutoCoding, key)) { // don't create file return; } PsiDirectory targetDirectory = d8gerAutoCoding.getCustomConfigAutoCodeDirMap().get(key).getLeft(); PsiJavaFile autoCodeFile = IdeaPlatformFileTreeUtil.forceCreateJavaFile( targetDirectory, d8gerAutoCoding.getCurrentProject(), pair.getLeft(), AutoCodeTemplate.render(pair.getRight(), d8gerAutoCoding.loadEnhanceKeyWordMap(key)) ); // Find and import enum classes if (KeyEnum.needImportEnumClass(key)) { d8gerAutoCoding.getEnumTypeClassName().forEach(item -> { Optional optionalPsiClass = IdeaPlatformFileTreeUtil.findClass(d8gerAutoCoding.getCurrentProject(), item); optionalPsiClass.ifPresent(autoCodeFile::importClass); if (!skipCurrentOperation(d8gerAutoCoding, KeyEnum.FORMAT_STYLE)) { // do code formatting IdeaPlatformFileTreeUtil.format(d8gerAutoCoding.getCurrentProject(), autoCodeFile); } }); } // This step is very important which would cause fail of creating file if it was ignored targetDirectory.add(autoCodeFile); fileNameList.add(autoCodeFile.getName()); }); Notifications.Bus.notify( new Notification(ConstantUtil.NOTIFICATION_GROUP_VIEW_ID, "Look Rebuilding file here", CollectionUtil.join(fileNameList, ConstantUtil.DOUBLE_NEXT_LINE), NotificationType.INFORMATION) ); } /** * Skip current operation or not * * @param d8gerAutoCoding * @param keyEnum * @return */ private boolean skipCurrentOperation(D8gerAutoCoding d8gerAutoCoding, KeyEnum keyEnum) { return !PropertiesUtil.checkConfigTakeEffect(d8gerAutoCoding.loadPropertiesFromRootResource(), keyEnum.getKey()); } /** * Handle replacing package names by custom directory configs */ private void handleCustomPackageKeyWordMap(D8gerAutoCoding d8gerAutoCoding) { Map keyWordMatchMap = d8gerAutoCoding.getKeyWordMatchMap(); d8gerAutoCoding.getCustomConfigAutoCodeDirMap().forEach((key, pair) -> { TemplateKeyWordEnum targetPackageKey = null; switch (key) { case MO: targetPackageKey = TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY; break; case MO_MAPPER: targetPackageKey = TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY; break; case MO_EXAMPLE: targetPackageKey = TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY; break; case SWAGGER_MO: targetPackageKey = TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY; break; case MO_HANDLER: targetPackageKey = TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY; break; case MO_CONTROLLER: targetPackageKey = TemplateKeyWordEnum.CONTROLLER_PACKAGE_NAME_KEY; break; default: break; } if (Objects.nonNull(targetPackageKey)) { keyWordMatchMap.put(targetPackageKey.getName(), new StringBuilder(pair.getRight())); } }); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/action/SwaggerModelAutoRenderAction.java ================================================ package com.xyz.caofancpu.d8ger.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.xyz.caofancpu.d8ger.util.CollectionUtil; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil; import lombok.NonNull; import java.util.ArrayList; import java.util.List; /** * SwaggerModel model automatic rendering * * @author caofanCPU */ public class SwaggerModelAutoRenderAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { final Editor currentEditor = e.getRequiredData(CommonDataKeys.EDITOR); final Project currentProject = e.getRequiredData(CommonDataKeys.PROJECT); final Document currentDocument = currentEditor.getDocument(); // Perform a refresh of the current file WriteCommandAction.runWriteCommandAction(currentProject, () -> executeSwaggerRender(currentDocument)); } /** * Rewrite file * * @param currentDocument */ public void executeSwaggerRender(@NonNull Document currentDocument) { // split lines by \n | \r\n String[] codeLines = currentDocument.getText().split("(?:\\n|(?:\\r\\n))"); List wrapLineList = new ArrayList<>(codeLines.length); int apiModelPropertyCounter = 0; int apiOperationSupportCounter = 0; for (String item : codeLines) { // case 1 if (item.contains("@ApiModelProperty(")) { if (!item.contains("position")) { String replacer = (item.contains("()") ? "position = " : ", position = ") + (++apiModelPropertyCounter) + ")"; item = item.replace(")", replacer); } else { item = VerbalExpressionUtil.regexHandleSwaggerModelProperty(item, "position = " + (++apiModelPropertyCounter)); } } // case 2 if (item.contains("@ApiOperationSupport(")) { if (!item.contains("order")) { String replacer = (item.contains("()") ? "order = " : ", order = ") + (++apiOperationSupportCounter) + ")"; item = item.replace(")", replacer); } else { item = VerbalExpressionUtil.regexHandleSwaggerModelProperty(item, "order = " + (++apiOperationSupportCounter)); } } wrapLineList.add(item); } boolean isWindowsLinebreak = currentDocument.getText().contains(ConstantUtil.WINDOWS_NEXT_LINE); currentDocument.setText(CollectionUtil.join(wrapLineList, isWindowsLinebreak ? ConstantUtil.WINDOWS_NEXT_LINE : ConstantUtil.NEXT_LINE)); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/activity/D8gerActivity.java ================================================ package com.xyz.caofancpu.d8ger.activity; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import com.intellij.util.text.VersionComparatorUtil; import com.xyz.caofancpu.d8ger.setting.D8gerApplicationState; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import org.jetbrains.annotations.NotNull; import java.util.Objects; /** * Start up and update activity, show some message! * * @author D8GER */ public class D8gerActivity implements StartupActivity, DumbAware { @Override public void runActivity(@NotNull Project project) { if (ApplicationManager.getApplication().isUnitTestMode()) { return; } IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(PluginId.getId(ConstantUtil.PLUGIN_ID)); if (Objects.nonNull(plugin)) { String installedVersion = D8gerApplicationState.getOldVersion(); int compare = VersionComparatorUtil.compare(installedVersion, plugin.getVersion()); if (compare < 0) { ApplicationManager.getApplication() .invokeLater(() -> Notifications.Bus.notify( new Notification(ConstantUtil.NOTIFICATION_GROUP_VIEW_ID, ConstantUtil.RENDER_TITLE + " (Update To v" + plugin.getVersion() + ")", "If you like D8gerAutoCode, please star the project D8gerAutoCode", NotificationType.INFORMATION )) ); D8gerApplicationState.setPluginVersion(plugin.getVersion()); } } } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/AutoCodeTemplate.java ================================================ package com.xyz.caofancpu.d8ger.core; import com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil; import lombok.NonNull; import ru.lanwen.verbalregex.VerbalExpression; import java.util.Map; /** * Code template string constants * * @author caofanCPU */ public class AutoCodeTemplate { public static Boolean IS_EN_LOCALE = Boolean.TRUE; /** * MO template string */ public static StringBuilder ZN_TEMPLATE_MO = new StringBuilder("package @moPackage@;\n" + "\n" + "import lombok.AllArgsConstructor;\n" + "import lombok.Data;\n" + "import lombok.NoArgsConstructor;\n" + "import lombok.experimental.Accessors;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.Date;\n" + "\n" + "/**\n" + " * @MoName@Mo\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Data\n" + "@NoArgsConstructor\n" + "@AllArgsConstructor\n" + "@Accessors(chain = true)\n" + "public class @MoName@Mo {\n" + "\n" + "@field@\n" + "\n" + "}"); /** * Swagger VO template string */ public static StringBuilder ZN_TEMPLATE_SWAGGER_VO = new StringBuilder("package @swaggerMoPackage@;\n" + "\n" + "import io.swagger.annotations.ApiModel;\n" + "import io.swagger.annotations.ApiModelProperty;\n" + "import lombok.AllArgsConstructor;\n" + "import lombok.Data;\n" + "import lombok.NoArgsConstructor;\n" + "import lombok.experimental.Accessors;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.Date;\n" + "\n" + "/**\n" + " * @MoName@Mo对应的SwaggerApi增强Vo对象\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Data\n" + "@NoArgsConstructor\n" + "@AllArgsConstructor\n" + "@Accessors(chain = true)\n" + "@ApiModel\n" + "public class @MoName@Vo {\n" + "\n" + "@swaggerField@\n" + "\n" + "}"); /** * Sql template string */ public static StringBuilder ZN_TEMPLATE_MO_SQL = new StringBuilder("\n" + "-- ----------------------------\n" + "-- D8ger-Sql-Auto-Generated\n" + "-- Table structure for `@mo_table_name@`\n" + "-- @author @d8Author@\n" + "-- ----------------------------\n" + "-- DROP TABLE IF EXISTS `@mo_table_name@`;\n" + "CREATE TABLE `@mo_table_name@`\n" + "(\n" + "@sql_column@\n" + ")\n" + " comment '@MoName@表' charset = utf8mb4;\n"); /** * Mapper template string */ public static StringBuilder ZN_TEMPLATE_MAPPER = new StringBuilder("package @mapperPackage@;\n" + "\n" + "import @moExamplePackage@.@MoName@Example;\n" + "import @moPackage@.@MoName@Mo;\n" + "import org.apache.ibatis.annotations.Param;\n" + "import @MapperAnnotationPackage@;\n" + "\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@Mo对应的Mapper\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@MapperAnnotation@\n" + "public interface @MoName@Mapper {\n" + "\n" + " /**\n" + " * 根据条件查询列表\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * 批量更新, 根据主键更新非null字段\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n" + "\n" + " /**\n" + " * 根据条件更新非null字段\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " int updateByExampleSelective(@Param(\"record\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\"example\") @MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * 根据条件删除记录\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * 根据条件统计记录\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return 记录条数\n" + " */\n" + " int countByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * 增加单条记录, 并为入参设置ID\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * 批量增加记录, 并为入参设置ID\n" + " * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n" + "\n" + " /**\n" + " * @MoName@列表查询\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * 根据ID查询对象\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " @MoName@Mo selectByPrimaryKey(T id);\n" + "\n" + " /**\n" + " * 根据主键只更新非null字段\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * 根据ID删除记录\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " int deleteByPrimaryKey(T id);\n" + "\n" + " /**\n" + " * 根据条件查询单个对象\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * 增加单条非空字段记录, 并为入参设置ID\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + "}"); /** * MoExample template string */ public static StringBuilder ZN_TEMPLATE_MO_EXAMPLE = new StringBuilder("package @moExamplePackage@;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.ArrayList;\n" + "import java.util.Date;\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@Mo对应的Example单表操作对象\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "public class @MoName@Example {\n" + "\n" + " protected String orderByClause;\n" + "\n" + " protected Integer limit;\n" + "\n" + " protected boolean distinct;\n" + "\n" + " protected List conditionCriteria;\n" + "\n" + " public @MoName@Example() {\n" + " conditionCriteria = new ArrayList<>();\n" + " }\n" + "\n" + " public @MoName@Example andOrderByClause(String orderByClause) {\n" + " this.orderByClause = orderByClause;\n" + " return this;\n" + " }\n" + "\n" + " public String getOrderByClause() {\n" + " return orderByClause;\n" + " }\n" + "\n" + " public @MoName@Example andLimit(Integer limit) {\n" + " if (limit != null && limit > 0) {\n" + " this.limit = limit;\n" + " }\n" + " return this;\n" + " }\n" + "\n" + " public Integer getLimit() {\n" + " return limit;\n" + " }\n" + "\n" + " public @MoName@Example andDistinct(boolean distinct) {\n" + " this.distinct = distinct;\n" + " return this;\n" + " }\n" + "\n" + " public boolean isDistinct() {\n" + " return distinct;\n" + " }\n" + "\n" + " public List getConditionCriteria() {\n" + " return conditionCriteria;\n" + " }\n" + "\n" + " public void or(Criteria criteria) {\n" + " conditionCriteria.add(criteria);\n" + " }\n" + "\n" + " public Criteria or() {\n" + " Criteria criteria = createCriteriaInternal();\n" + " conditionCriteria.add(criteria);\n" + " return criteria;\n" + " }\n" + "\n" + " public Criteria createCriteria() {\n" + " Criteria criteria = createCriteriaInternal();\n" + " if (conditionCriteria.size() == 0) {\n" + " conditionCriteria.add(criteria);\n" + " }\n" + " return criteria;\n" + " }\n" + "\n" + " protected Criteria createCriteriaInternal() {\n" + " return new Criteria();\n" + " }\n" + "\n" + " public void clear() {\n" + " conditionCriteria.clear();\n" + " orderByClause = null;\n" + " distinct = false;\n" + " }\n" + "\n" + " protected abstract static class GeneratedCriteria {\n" + " protected List criteria;\n" + "\n" + " protected GeneratedCriteria() {\n" + " super();\n" + " criteria = new ArrayList<>();\n" + " }\n" + "\n" + " public boolean isValid() {\n" + " return criteria.size() > 0;\n" + " }\n" + "\n" + " public List getAllCriteria() {\n" + " return criteria;\n" + " }\n" + "\n" + " public List getCriteria() {\n" + " return criteria;\n" + " }\n" + "\n" + " protected void addCriterion(String condition) {\n" + " if (condition == null) {\n" + " throw new RuntimeException(\"Value for condition cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition));\n" + " }\n" + "\n" + " protected void addCriterion(String condition, Object value, String property) {\n" + " if (value == null) {\n" + " throw new RuntimeException(\"Value for \" + property + \" cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition, value));\n" + " }\n" + "\n" + " protected void addCriterion(String condition, Object value1, Object value2, String property) {\n" + " if (value1 == null || value2 == null) {\n" + " throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition, value1, value2));\n" + " }\n" + "\n" + "@ExampleDefinitionMethod@\n" + " }\n" + "\n" + " public static class Criteria extends GeneratedCriteria {\n" + " protected Criteria() {\n" + " super();\n" + " }\n" + " }\n" + "\n" + " public static class Criterion {\n" + " private String condition;\n" + "\n" + " private Object value;\n" + "\n" + " private Object secondValue;\n" + "\n" + " private boolean noValue;\n" + "\n" + " private boolean singleValue;\n" + "\n" + " private boolean betweenValue;\n" + "\n" + " private boolean listValue;\n" + "\n" + " private String typeHandler;\n" + "\n" + " public String getCondition() {\n" + " return condition;\n" + " }\n" + "\n" + " public Object getValue() {\n" + " return value;\n" + " }\n" + "\n" + " public Object getSecondValue() {\n" + " return secondValue;\n" + " }\n" + "\n" + " public boolean isNoValue() {\n" + " return noValue;\n" + " }\n" + "\n" + " public boolean isSingleValue() {\n" + " return singleValue;\n" + " }\n" + "\n" + " public boolean isBetweenValue() {\n" + " return betweenValue;\n" + " }\n" + "\n" + " public boolean isListValue() {\n" + " return listValue;\n" + " }\n" + "\n" + " public String getTypeHandler() {\n" + " return typeHandler;\n" + " }\n" + "\n" + " protected Criterion(String condition) {\n" + " super();\n" + " this.condition = condition;\n" + " this.typeHandler = null;\n" + " this.noValue = true;\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, String typeHandler) {\n" + " super();\n" + " this.condition = condition;\n" + " this.value = value;\n" + " this.typeHandler = typeHandler;\n" + " if (value instanceof List) {\n" + " this.listValue = true;\n" + " } else {\n" + " this.singleValue = true;\n" + " }\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value) {\n" + " this(condition, value, null);\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\n" + " super();\n" + " this.condition = condition;\n" + " this.value = value;\n" + " this.secondValue = secondValue;\n" + " this.typeHandler = typeHandler;\n" + " this.betweenValue = true;\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, Object secondValue) {\n" + " this(condition, value, secondValue, null);\n" + " }\n" + " }\n" + "}"); /** * Mapper.xml template string */ public static StringBuilder ZN_TEMPLATE_MAPPER_XML = new StringBuilder("\n" + "\n" + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@BatchUpdateNonNullFieldByID@\n" + " \n" + " WHERE `id` = #{item.id}\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@UpdateNonNullFieldByExample@\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + " DELETE FROM `@mo_table_name@`\n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@` (\n" + "@BaseColumnList@\n" + " )\n" + " values (\n" + "@InsertField@\n" + " )\n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@` (\n" + "@BaseColumnList@\n" + " )\n" + " VALUES\n" + " \n" + "@BatchInsertField@\n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@UpdateNonNullFieldByID@\n" + " \n" + " WHERE `id` = #{id}\n" + " \n" + "\n" + " \n" + " \n" + " DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@`\n" + " \n" + "@NonNullColumnList@\n" + " \n" + " \n" + "@NonNullInsertField@\n" + " \n" + " \n" + ""); /** * Service implement template string */ public static StringBuilder ZN_TEMPLATE_HANDLER = new StringBuilder("package @handlerPackage@;\n" + "\n" + "import @mapperPackage@.@MoName@Mapper;\n" + "import @moPackage@.@MoName@Mo;\n" + "import com.github.pagehelper.PageHelper;\n" + "import org.springframework.stereotype.Service;\n" + "import lombok.extern.slf4j.Slf4j;\n" + "\n" + "import javax.annotation.Resource;\n" + "import java.util.List;\n" + "import java.util.Objects;\n" + "\n" + "/**\n" + " * @MoName@Mo对应的Handler\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Service\n" + "@Slf4j\n" + "public class @MoName@Handler {\n" + "\n" + " @Resource\n" + " private @MoName@Mapper @uncapitallizeMoName@Mapper;\n" + "\n" + " /**\n" + " * 插入单条记录\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\n" + " return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * 批量插入\n" + " * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n" + " return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " /**\n" + " * 查询列表, 如果携带分页参数则返回分页后的列表\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @param pageParams 可选分页参数\n" + " * @return\n" + " */\n" + " public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\n" + " if (Objects.nonNull(pageParams) && pageParams.length > 0) {\n" + " int pageNum = pageParams[0];\n" + " int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\n" + " PageHelper.startPage(pageNum, pageSize);\n" + " }\n" + " return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * 根据id更新非null字段\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\n" + " return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * 批量根据id更新非null字段\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n" + " return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " /**\n" + " * 根据id物理删除\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " public int delete(T id) {\n" + " return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\n" + " }\n" + "\n" + " /**\n" + " * 根据id查询单条记录\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " public @MoName@Mo selectByPrimaryKey(T id) {\n" + " return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\n" + " }\n" + "\n" + "}"); /** * Controller template string */ public static StringBuilder ZN_TEMPLATE_CONTROLLER = new StringBuilder("package @controllerPackage@;\n" + "\n" + "import @handlerPackage@.@MoName@Handler;\n" + "import @moPackage@.@MoName@Mo;\n" + "import @swaggerMoPackage@.@MoName@Vo;\n" + "import com.alibaba.fastjson.JSONObject;\n" + "import com.github.pagehelper.PageInfo;\n" + "import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\n" + "import com.github.xiaoymin.knife4j.annotations.ApiSort;\n" + "import io.swagger.annotations.Api;\n" + "import io.swagger.annotations.ApiOperation;\n" + "import lombok.extern.slf4j.Slf4j;\n" + "import org.springframework.web.bind.annotation.PostMapping;\n" + "import org.springframework.web.bind.annotation.RequestBody;\n" + "import org.springframework.web.bind.annotation.RestController;\n" + "\n" + "import javax.annotation.Resource;\n" + "import javax.validation.Valid;\n" + "import javax.validation.constraints.NotEmpty;\n" + "import java.util.ArrayList;\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@Mo控制器\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@RestController\n" + "@Api(tags = {\"@MoName@Mo模块接口\"})\n" + "@ApiSort(0)\n" + "@Slf4j\n" + "public class @MoName@Controller {\n" + "\n" + " @Resource\n" + " private @MoName@Handler @uncapitallizeMoName@Handler;\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\")\n" + " @ApiOperationSupport(order = 1)\n" + " @ApiOperation(value = \"@MoName@Mo新增记录\")\n" + " public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // 转换数据\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\n" + " return @uncapitallizeMoName@Mo.getId();\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\")\n" + " @ApiOperationSupport(order = 2)\n" + " @ApiOperation(value = \"@MoName@Mo批量新增\")\n" + " public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n" + " List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n" + " for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\n" + " @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\n" + " }\n" + " return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\")\n" + " @ApiOperationSupport(order = 3)\n" + " @ApiOperation(value = \"@MoName@Mo列表查询\")\n" + " public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // 转换数据\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\")\n" + " @ApiOperationSupport(order = 4)\n" + " @ApiOperation(value = \"@MoName@Mo分页查询\")\n" + " public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // 转换数据\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\n" + " return PageInfo.of(result@MoName@MoList);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\")\n" + " @ApiOperationSupport(order = 5)\n" + " @ApiOperation(value = \"@MoName@Mo修改记录\")\n" + " public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // 转换数据\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\")\n" + " @ApiOperationSupport(order = 5)\n" + " @ApiOperation(value = \"@MoName@Mo批量修改记录\")\n" + " public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n" + " // 转换数据\n" + " List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n" + " @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\n" + " return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\")\n" + " @ApiOperationSupport(order = 6)\n" + " @ApiOperation(value = \"@MoName@Mo删除记录\")\n" + " public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\n" + " }\n" + "\n" + "\n" + "}\n"); /** * Mo template string */ public static StringBuilder TEMPLATE_MO = new StringBuilder("package @moPackage@;\n" + "\n" + "import lombok.AllArgsConstructor;\n" + "import lombok.Data;\n" + "import lombok.NoArgsConstructor;\n" + "import lombok.experimental.Accessors;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.Date;\n" + "\n" + "/**\n" + " * @MoName@Mo\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Data\n" + "@NoArgsConstructor\n" + "@AllArgsConstructor\n" + "@Accessors(chain = true)\n" + "public class @MoName@Mo {\n" + "\n" + "@field@\n" + "\n" + "}"); /** * Swagger enhance VO template string */ public static StringBuilder TEMPLATE_SWAGGER_VO = new StringBuilder("package @swaggerMoPackage@;\n" + "\n" + "import io.swagger.annotations.ApiModel;\n" + "import io.swagger.annotations.ApiModelProperty;\n" + "import lombok.AllArgsConstructor;\n" + "import lombok.Data;\n" + "import lombok.NoArgsConstructor;\n" + "import lombok.experimental.Accessors;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.Date;\n" + "\n" + "/**\n" + " * @MoName@Mo with SwaggerApi Enhance Vo\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Data\n" + "@NoArgsConstructor\n" + "@AllArgsConstructor\n" + "@Accessors(chain = true)\n" + "@ApiModel\n" + "public class @MoName@Vo {\n" + "\n" + "@swaggerField@\n" + "\n" + "}"); /** * Sql template string */ public static StringBuilder TEMPLATE_MO_SQL = new StringBuilder("\n" + "-- ----------------------------\n" + "-- D8ger-Sql-Auto-Generated\n" + "-- Table structure for `@mo_table_name@`\n" + "-- @author @d8Author@\n" + "-- ----------------------------\n" + "-- DROP TABLE IF EXISTS `@mo_table_name@`;\n" + "CREATE TABLE `@mo_table_name@`\n" + "(\n" + "@sql_column@\n" + ")\n" + " comment '@MoName@' charset = utf8mb4;\n"); /** * Mapper template string */ public static StringBuilder TEMPLATE_MAPPER = new StringBuilder("package @mapperPackage@;\n" + "\n" + "import @moExamplePackage@.@MoName@Example;\n" + "import @moPackage@.@MoName@Mo;\n" + "import org.apache.ibatis.annotations.Param;\n" + "import @MapperAnnotationPackage@;\n" + "\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@Mo Database Mapper\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@MapperAnnotation@\n" + "public interface @MoName@Mapper {\n" + "\n" + " /**\n" + " * Query list by criteria, supporting all conditions for querying a single table\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * Batch update non-null fields by ID for multi-records\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n" + "\n" + " /**\n" + " * Update non-null fields by ID for a single record\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " int updateByExampleSelective(@Param(\"record\") @MoName@Mo @uncapitallizeMoName@Mo, @Param(\"example\") @MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * Delete a single record by condition\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " int deleteByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * Statistical records by query conditions\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return Number of records\n" + " */\n" + " int countByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * Add a single record, and set the ID for the input Mo parameter\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * Batch add records, and set the ID for the input MoList parameters\n" + " * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList);\n" + "\n" + " /**\n" + " * @MoName@ query list\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * Query just one record by ID\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " @MoName@Mo selectByPrimaryKey(T id);\n" + "\n" + " /**\n" + " * Update non-null fields by ID for a single record\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + " /**\n" + " * Delete a record by ID\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " int deleteByPrimaryKey(T id);\n" + "\n" + " /**\n" + " * Query just one record by criteria, supporting all conditions for querying a single table\n" + " *\n" + " * @param @uncapitallizeMoName@Example\n" + " * @return\n" + " */\n" + " @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example);\n" + "\n" + " /**\n" + " * Add a single record with nonNull field, and set the ID for the input Mo parameter\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo);\n" + "\n" + "}"); /** * Example template string */ public static StringBuilder TEMPLATE_MO_EXAMPLE = new StringBuilder("package @moExamplePackage@;\n" + "\n" + "import java.math.BigDecimal;\n" + "import java.time.LocalDateTime;\n" + "import java.util.ArrayList;\n" + "import java.util.Date;\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@Mo with multi-conditions object, Example\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "public class @MoName@Example {\n" + "\n" + " protected String orderByClause;\n" + "\n" + " protected Integer limit;\n" + "\n" + " protected boolean distinct;\n" + "\n" + " protected List conditionCriteria;\n" + "\n" + " public @MoName@Example() {\n" + " conditionCriteria = new ArrayList<>();\n" + " }\n" + "\n" + " public @MoName@Example andOrderByClause(String orderByClause) {\n" + " this.orderByClause = orderByClause;\n" + " return this;\n" + " }\n" + "\n" + " public String getOrderByClause() {\n" + " return orderByClause;\n" + " }\n" + "\n" + " public @MoName@Example andLimit(Integer limit) {\n" + " if (limit != null && limit > 0) {\n" + " this.limit = limit;\n" + " }\n" + " return this;\n" + " }\n" + "\n" + " public Integer getLimit() {\n" + " return limit;\n" + " }\n" + "\n" + " public @MoName@Example andDistinct(boolean distinct) {\n" + " this.distinct = distinct;\n" + " return this;\n" + " }\n" + "\n" + " public boolean isDistinct() {\n" + " return distinct;\n" + " }\n" + "\n" + " public List getConditionCriteria() {\n" + " return conditionCriteria;\n" + " }\n" + "\n" + " public void or(Criteria criteria) {\n" + " conditionCriteria.add(criteria);\n" + " }\n" + "\n" + " public Criteria or() {\n" + " Criteria criteria = createCriteriaInternal();\n" + " conditionCriteria.add(criteria);\n" + " return criteria;\n" + " }\n" + "\n" + " public Criteria createCriteria() {\n" + " Criteria criteria = createCriteriaInternal();\n" + " if (conditionCriteria.size() == 0) {\n" + " conditionCriteria.add(criteria);\n" + " }\n" + " return criteria;\n" + " }\n" + "\n" + " protected Criteria createCriteriaInternal() {\n" + " return new Criteria();\n" + " }\n" + "\n" + " public void clear() {\n" + " conditionCriteria.clear();\n" + " orderByClause = null;\n" + " distinct = false;\n" + " }\n" + "\n" + " protected abstract static class GeneratedCriteria {\n" + " protected List criteria;\n" + "\n" + " protected GeneratedCriteria() {\n" + " super();\n" + " criteria = new ArrayList<>();\n" + " }\n" + "\n" + " public boolean isValid() {\n" + " return criteria.size() > 0;\n" + " }\n" + "\n" + " public List getAllCriteria() {\n" + " return criteria;\n" + " }\n" + "\n" + " public List getCriteria() {\n" + " return criteria;\n" + " }\n" + "\n" + " protected void addCriterion(String condition) {\n" + " if (condition == null) {\n" + " throw new RuntimeException(\"Value for condition cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition));\n" + " }\n" + "\n" + " protected void addCriterion(String condition, Object value, String property) {\n" + " if (value == null) {\n" + " throw new RuntimeException(\"Value for \" + property + \" cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition, value));\n" + " }\n" + "\n" + " protected void addCriterion(String condition, Object value1, Object value2, String property) {\n" + " if (value1 == null || value2 == null) {\n" + " throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");\n" + " }\n" + " criteria.add(new Criterion(condition, value1, value2));\n" + " }\n" + "\n" + "@ExampleDefinitionMethod@\n" + " }\n" + "\n" + " public static class Criteria extends GeneratedCriteria {\n" + " protected Criteria() {\n" + " super();\n" + " }\n" + " }\n" + "\n" + " public static class Criterion {\n" + " private String condition;\n" + "\n" + " private Object value;\n" + "\n" + " private Object secondValue;\n" + "\n" + " private boolean noValue;\n" + "\n" + " private boolean singleValue;\n" + "\n" + " private boolean betweenValue;\n" + "\n" + " private boolean listValue;\n" + "\n" + " private String typeHandler;\n" + "\n" + " public String getCondition() {\n" + " return condition;\n" + " }\n" + "\n" + " public Object getValue() {\n" + " return value;\n" + " }\n" + "\n" + " public Object getSecondValue() {\n" + " return secondValue;\n" + " }\n" + "\n" + " public boolean isNoValue() {\n" + " return noValue;\n" + " }\n" + "\n" + " public boolean isSingleValue() {\n" + " return singleValue;\n" + " }\n" + "\n" + " public boolean isBetweenValue() {\n" + " return betweenValue;\n" + " }\n" + "\n" + " public boolean isListValue() {\n" + " return listValue;\n" + " }\n" + "\n" + " public String getTypeHandler() {\n" + " return typeHandler;\n" + " }\n" + "\n" + " protected Criterion(String condition) {\n" + " super();\n" + " this.condition = condition;\n" + " this.typeHandler = null;\n" + " this.noValue = true;\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, String typeHandler) {\n" + " super();\n" + " this.condition = condition;\n" + " this.value = value;\n" + " this.typeHandler = typeHandler;\n" + " if (value instanceof List) {\n" + " this.listValue = true;\n" + " } else {\n" + " this.singleValue = true;\n" + " }\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value) {\n" + " this(condition, value, null);\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {\n" + " super();\n" + " this.condition = condition;\n" + " this.value = value;\n" + " this.secondValue = secondValue;\n" + " this.typeHandler = typeHandler;\n" + " this.betweenValue = true;\n" + " }\n" + "\n" + " protected Criterion(String condition, Object value, Object secondValue) {\n" + " this(condition, value, secondValue, null);\n" + " }\n" + " }\n" + "}"); /** * Sql xml template string */ public static StringBuilder TEMPLATE_MAPPER_XML = new StringBuilder("\n" + "\n" + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value}\n" + " \n" + " \n" + " AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}\n" + " \n" + " \n" + " AND ${criterion.condition}\n" + " \n" + " #{listItem}\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@BatchUpdateNonNullFieldByID@\n" + " \n" + " WHERE `id` = #{item.id}\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@UpdateNonNullFieldByExample@\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + " DELETE FROM `@mo_table_name@`\n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@` (\n" + "@BaseColumnList@\n" + " )\n" + " values (\n" + "@InsertField@\n" + " )\n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@` (\n" + "@BaseColumnList@\n" + " )\n" + " VALUES\n" + " \n" + "@BatchInsertField@\n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " UPDATE `@mo_table_name@`\n" + " \n" + "@UpdateNonNullFieldByID@\n" + " \n" + " WHERE `id` = #{id}\n" + " \n" + "\n" + " \n" + " \n" + " DELETE FROM `@mo_table_name@` WHERE `id` = #{id}\n" + " \n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " INSERT INTO `@mo_table_name@`\n" + " \n" + "@NonNullColumnList@\n" + " \n" + " \n" + "@NonNullInsertField@\n" + " \n" + " \n" + ""); /** * Service implement template string */ public static StringBuilder TEMPLATE_HANDLER = new StringBuilder("package @handlerPackage@;\n" + "\n" + "import @mapperPackage@.@MoName@Mapper;\n" + "import @moPackage@.@MoName@Mo;\n" + "import com.github.pagehelper.PageHelper;\n" + "import org.springframework.stereotype.Service;\n" + "import lombok.extern.slf4j.Slf4j;\n" + "\n" + "import javax.annotation.Resource;\n" + "import java.util.List;\n" + "import java.util.Objects;\n" + "\n" + "/**\n" + " * @MoName@Handler\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@Service\n" + "@Slf4j\n" + "public class @MoName@Handler {\n" + "\n" + " @Resource\n" + " private @MoName@Mapper @uncapitallizeMoName@Mapper;\n" + "\n" + " /**\n" + " * Insert a record\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " public int add(@MoName@Mo @uncapitallizeMoName@Mo) {\n" + " return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * Batch insert records\n" + " * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n" + " return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " /**\n" + " * Query list, if the paging parameter is carried, return the list after paging\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @param pageParams Optional paging parameters\n" + " * @return\n" + " */\n" + " public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) {\n" + " if (Objects.nonNull(pageParams) && pageParams.length > 0) {\n" + " int pageNum = pageParams[0];\n" + " int pageSize = pageParams.length > 1 ? pageParams[1] : 10;\n" + " PageHelper.startPage(pageNum, pageSize);\n" + " }\n" + " return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * Update non-null fields by ID for a single record\n" + " *\n" + " * @param @uncapitallizeMoName@Mo\n" + " * @return\n" + " */\n" + " public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) {\n" + " return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " /**\n" + " * Batch Update non-nulls field by ID for multi-records\n" + " *\n" + " * @param @uncapitallizeMoName@MoList\n" + " * @return\n" + " */\n" + " public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) {\n" + " return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " /**\n" + " * Delete a record by ID\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " public int delete(T id) {\n" + " return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id);\n" + " }\n" + "\n" + " /**\n" + " * Select a record by ID\n" + " *\n" + " * @param id\n" + " * @return\n" + " */\n" + " public @MoName@Mo selectByPrimaryKey(T id) {\n" + " return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id);\n" + " }\n" + "\n" + "}"); /** * Controller template string */ public static StringBuilder TEMPLATE_CONTROLLER = new StringBuilder("package @controllerPackage@;\n" + "\n" + "import @handlerPackage@.@MoName@Handler;\n" + "import @moPackage@.@MoName@Mo;\n" + "import @swaggerMoPackage@.@MoName@Vo;\n" + "import com.alibaba.fastjson.JSONObject;\n" + "import com.github.pagehelper.PageInfo;\n" + "import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\n" + "import com.github.xiaoymin.knife4j.annotations.ApiSort;\n" + "import io.swagger.annotations.Api;\n" + "import io.swagger.annotations.ApiOperation;\n" + "import lombok.extern.slf4j.Slf4j;\n" + "import org.springframework.web.bind.annotation.PostMapping;\n" + "import org.springframework.web.bind.annotation.RequestBody;\n" + "import org.springframework.web.bind.annotation.RestController;\n" + "\n" + "import javax.annotation.Resource;\n" + "import javax.validation.Valid;\n" + "import javax.validation.constraints.NotEmpty;\n" + "import java.util.ArrayList;\n" + "import java.util.List;\n" + "\n" + "/**\n" + " * @MoName@MoController\n" + " *\n" + " * @author @d8Author@\n" + " */\n" + "@RestController\n" + "@Api(tags = {\"@MoName@Mo-ModuleAPI\"})\n" + "@ApiSort(0)\n" + "@Slf4j\n" + "public class @MoName@Controller {\n" + "\n" + " @Resource\n" + " private @MoName@Handler @uncapitallizeMoName@Handler;\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/add\")\n" + " @ApiOperationSupport(order = 1)\n" + " @ApiOperation(value = \"@MoName@Mo-AddRecord\")\n" + " public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // convert Vo to Mo\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo);\n" + " return @uncapitallizeMoName@Mo.getId();\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd\")\n" + " @ApiOperationSupport(order = 2)\n" + " @ApiOperation(value = \"@MoName@Mo-BatchAddRecords\")\n" + " public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n" + " List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n" + " for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) {\n" + " @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class));\n" + " }\n" + " return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList\")\n" + " @ApiOperationSupport(order = 3)\n" + " @ApiOperation(value = \"@MoName@Mo-QueryList\")\n" + " public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // convert Vo to Mo\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage\")\n" + " @ApiOperationSupport(order = 4)\n" + " @ApiOperation(value = \"@MoName@Mo-QueryListWithPaging\")\n" + " public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // convert Vo to Mo\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize());\n" + " return PageInfo.of(result@MoName@MoList);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/update\")\n" + " @ApiOperationSupport(order = 5)\n" + " @ApiOperation(value = \"@MoName@Mo-UpdateRecord\")\n" + " public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " // convert Vo to Mo\n" + " @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class);\n" + " return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate\")\n" + " @ApiOperationSupport(order = 5)\n" + " @ApiOperation(value = \"@MoName@Mo-BatchUpdateRecords\")\n" + " public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) {\n" + " // convert Vo to Mo\n" + " List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size());\n" + " @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class)));\n" + " return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List);\n" + " }\n" + "\n" + " @PostMapping(value = \"@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete\")\n" + " @ApiOperationSupport(order = 6)\n" + " @ApiOperation(value = \"@MoName@Mo-DeleteRecord\")\n" + " public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) {\n" + " return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId());\n" + " }\n" + "\n" + "\n" + "}\n"); /** * Config template string */ public static String TEMPLATE_D8GER = "# The default author called 'D8ger', but it's highly recommended to modify\n" + "author=D8ger\n" + "\n" + "#### Basic generate, support two item configs such as:\n" + "#### autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\n" + "#### ATTENTION: if you config directory path, you should make sure it exists first\n" + "#### WARNING: if you config error, the auto code file will put into the origin directory named 'D8AutoCode'\n" + "#### THEN plugin will create Mo.java file\n" + "#### AND put the file into 'com.xyz.caofancpu.d8ger.test.Mo' directory\n" + "#### UNDER current project source directory which include '/src/main/java'\n" + "autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo\n" + "autoCreateMapper=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper\n" + "autoCreateExample=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper/Example\n" + "autoCreateXML=true, /src/main/resources/mybatis\n" + "autoCreateDefinitionSQL=true, /doc\n" + "\n" + "#### Enhance generate, also support two item configs, please refer Basic generate\n" + "autoCreateSwaggerMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Vo\n" + "autoCreateHandler=true, /src/main/java/com/xyz/caofancpu/d8ger/test/handler\n" + "autoCreateController=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Controller\n" + "\n" + "#### Other normal binary config\n" + "autoFormatStyle=true\n" + "\n" + "#### Api path prefix\n" + "# apiUrlPrefix=/D8ger\n" + "\n" + "#### auto generating create_time and update_time SQL column definition\n" + "autoDetectSQLTimeColumn=true\n" + "\n" + "#### if true then moMapper with annotation @Mapper, otherwise, with annotation @Repository\n" + "mapperBatterThenRepository=true\n" + "\n" + "#### Language just for EN(English) and ZN(Chinese Simplified)\n" + "# locale=ZN\n"; public static String TEMPLATE_REGEX = "0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions\n" + "Usage, static pattern can improve performance in regex searching:\n" + " public static final Pattern XXX_REGEX = Pattern.compile(\"...Regex string...\");\n" + "\n" + "1.Whitespace Regex\n" + "((?:\\s)+)\n" + "\n" + "2.One or more newlines Regex\n" + "(?:\\\\n|(?:\\\\r\\\\n))+\n" + "\n" + "3.Phone validate Regex\n" + "^1[0-9]{10}$\n" + "\n" + "4.Email validate Regex\n" + "^([a-z0-9A-Z]+[-|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\.)+[a-zA-Z]{2,}$\n" + "\n" + "5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species\n" + "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_]+$)(?![a-z0-9]+$)(?![a-z\\\\W_]+$)(?![0-9\\\\W_]+$)[a-zA-Z0-9\\\\W_]{8,30}$\n" + "\n" + "6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital]\n" + "(?:position)(?:\\\\s)*(?:\\\\=)(?:\\\\s)*(?:\\\\d)*\n" + "\n" + "7.No '_' and begin with [A-Z] in word Regex\n" + "^(?!_)(?:[A-Z])[a-zA-Z0-9\\\\W]+$\n" + "\n" + "8.No upper case in word Regex\n" + "^(?![A-Z])[a-z0-9\\\\W_]+$\n" + "\n" + "9.No lower case in word Regex\n" + "^(?![a-z])[A-Z0-9\\\\W_]+$\n" + "\n" + "10.'www' Url detect Regex\n" + "^(?:http)(?:s)?(?:\\:\\/\\/)(?:www\\.)?(?:[^\\ ]*)$\n" + "\n" + "11.IDEA Skills\n" + "- 11.1 For multi-lines, how to add some same fix characters?\n" + " ResearchRegex@ (?:\\n|(?:\\r\\n))+\n" + " ReplaceString@ ,\\r\\n\n" + "\n" + "- 11.2 For multi-lines, especially for SQL batch replacing, such as:\n" + " - zcy_cf, --> WE'RE(zcy_cf) AS zcy_cf,\n" + " - cf_zcy --> WE'RE(cf_zcy) AS cf_zcy\n" + " - note: WE'RE is just a function\n" + " I.Clear the character ','\n" + " ResearchRegex@ (?:,)+\n" + " ReplaceString@ [EMPTY]\n" + " II.Batch replace\n" + " ResearchRegex@ ((?:\\w+)+)\n" + " ReplaceString@ WE'RE($0) AS $0,\n" + " III.Clear the rare character ',' at the last line\n" + "\n" + "- 11.3 For multi-lines, especially for SQL batch reduce-replacing, such as:\n" + " - WE'RE(zcy_cf) AS zcy_cf, --> zcy_cf,\n" + " - WE'RE(cf_zcy) AS cf_zcy --> cf_zcy\n" + " - note: WE'RE is just a function\n" + " I.Handle prefix\n" + " ResearchRegex@ (?:WE'RE\\()+\n" + " ReplaceString@ [EMPTY]\n" + " II.Handle suffix\n" + " ResearchRegex@ (?:\\))(?:[^\\,]*)\n" + " ReplaceString@ [EMPTY]\n" + " III.Watch out whether need to clear the rare character ',' at the last line\n" + "\n" + "12. Cron Expression\n" + "每隔5秒执行一次: */5 * * * * ?\n" + "每隔5分钟执行一次: 0 */5 * * * ?\n" + "每天23点执行一次: 0 0 23 * * ?\n" + "每天凌晨2点执行一次: 0 0 2 * * ?\n" + "每月2号凌晨4点执行一次: 0 0 2 4 * ?\n" + "每月最后一天23点执行一次: 0 0 23 L * ?\n" + "每周星期天凌晨2点实行一次: 0 0 2 ? * L\n" + "在26分、29分、33分执行一次: 0 26,29,33 * * * ?\n" + "每天的0点、22点、23点都执行一次: 0 0 0 0,22,23 * * ?\n" + "\n"; public static String TEMPLATE_OH_MY_ZSH = "export ZSH=\"$HOME/.oh-my-zsh\"\n" + "export HOMEBREW_NO_AUTO_UPDATE=true\n" + "\n" + "ZSH_THEME=\"powerlevel9k/powerlevel9k\"\n" + "POWERLEVEL9K_MODE=\"nerdfont-complete\"\n" + "POWERLEVEL9K_PROMPT_ON_NEWLINE=true\n" + "POWERLEVEL9K_RPROMPT_ON_NEWLINE=false\n" + "POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon user dir_writable dir vcs)\n" + "POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time root_indicator background_jobs time disk_usage ram)\n" + "#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\"%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )\"\n" + "#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\"\"\n" + "#POWERLEVEL9K_USER_ICON=\"\\uF415\" # \uF415\n" + "POWERLEVEL9K_ROOT_ICON=\"\\uF09C\"\n" + "#POWERLEVEL9K_SUDO_ICON=$'\\uF09C' # \uF09C\n" + "POWERLEVEL9K_TIME_FORMAT=\"%D{%H:%M}\"\n" + "#POWERLEVEL9K_VCS_GIT_ICON='\\uF408 '\n" + "#POWERLEVEL9K_VCS_GIT_GITHUB_ICON='\\uF408 '\n" + "\n" + "ZSH_DISABLE_COMPFIX=true\n" + "#ENABLE_CORRECTION=\"true\"\n" + "DISABLE_CORRECTION=true\n" + "COMPLETION_WAITING_DOTS=true\n" + "\n" + "# 左侧栏目显示的要素(指定的关键字参考官网)\n" + "#POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon context dir vcs)\n" + "# 右侧栏目显示的要素\n" + "#POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs time virtualenv)\n" + "#新起一行显示命令 (推荐!极其方便)\n" + "#POWERLEVEL9K_PROMPT_ON_NEWLINE=true\n" + "#右侧状态栏与命令在同一行\n" + "#POWERLEVEL9K_RPROMPT_ON_NEWLINE=false\n" + "#缩短目录层级\n" + "#POWERLEVEL9K_SHORTEN_DIR_LENGTH=1\n" + "#缩短目录策略:隐藏上层目录中间的字\n" + "#POWERLEVEL9K_SHORTEN_STRATEGY=\"truncate_middle\"\n" + "#添加连接上下连接箭头更方便查看\n" + "#POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX=\"↱\"\n" + "#POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX=\"↳ \"\n" + "# 新的命令与上面的命令隔开一行\n" + "#POWERLEVEL9K_PROMPT_ADD_NEWLINE=true\n" + "# Git仓库状态的色彩指定\n" + "#POWERLEVEL9K_VCS_CLEAN_FOREGROUND='blue'\n" + "#POWERLEVEL9K_VCS_CLEAN_BACKGROUND='black'\n" + "#POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND='yellow'\n" + "#POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='black'\n" + "#POWERLEVEL9K_VCS_MODIFIED_FOREGROUND='red'\n" + "#POWERLEVEL9K_VCS_MODIFIED_BACKGROUND='black'\n" + "\n" + "\n" + "DISABLE_AUTO_UPDATE=\"true\"\n" + "# autojump : 'j'历史目录\n" + "# cp : 'cpv'带进度条的复制\n" + "# zsh_reload : 'src'快速重载.zshrc\n" + "# 快速编辑.zshrc: alias 'vrc=vim ~/.zshrc'\n" + "# 快速展示.zshrc: alias 'crc=cat ~/.zshrc'\n" + "# extract : 'x'解压任何文件\n" + "plugins=(git autojump cp zsh_reload extract zsh-syntax-highlighting)\n" + "\n" + "export LC_ALL=en_US.UTF-8 \n" + "export LANG=en_US.UTF-8\n" + "\n" + "# Maven家目录\n" + "export M2_HOME=/usr/local/maven-3.6.1/apache-maven-3.6.1\n" + "alias mcf=\"/usr/local/maven-3.6.1/caofanCPU-apache-maven-3.6.1/bin/mvn\"\n" + "\n" + "# 查看java安装位置命令 /usr/libexec/java_home -V\n" + "export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home\n" + "export JRE_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre\n" + "export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH\n" + "export PATH=$M2_HOME/bin:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH\n" + "\n" + "# Python项目打包工具包\n" + "export TWINE_HOME=/Users/D8GER/Library/Python/3.7\n" + "export PATH=$PATH:$TWINE_HOME/bin\n" + "\n" + "export PATH=$PATH:$HOME/bin\n" + "export PATH=\"$PATH:/usr/local/python3/bin\"\n" + "\n" + "# thefuck插件\n" + "eval \"$(thefuck --alias)\"\n" + "\n" + "# 服务器\n" + "alias caofanCPU='sshpass -f PWD_DIR ssh xxxx@xx.xx.xx.xx'\n" + "alias caofanJumpAli='sshpass -f PWD_DIR ssh xx@xx.xx.xx.xx'\n" + "\n" + "function execute() {\n" + " http --session=~/Desktop/ssoLogin/session-${1}.json --verify=no -v ${2} POST ${@:3}\n" + "}\n" + "\n" + "function downLoadResponse() {\n" + " echo \"执行命令内容: \\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\\n\"\n" + " http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n" + "}\n" + "\n" + "function downLoadExcel() {\n" + " echo \"执行命令内容: \\n http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\"\n" + " http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}\n" + "}\n" + "\n" + "function downloadD8ger() {\n" + " echo \"执行命令内容: 并发下载文件\"\n" + " for i in {1..30}\n" + " do \n" + " http --verify=no -v --download GET ${1} -o D8.zip\n" + " done\n" + "}\n" + "\n" + "function show() {\n" + " echo \"执行命令内容: \\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\\n\"\n" + " http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n" + "}\n" + "\n" + "function searchPortOccupy(){\n" + " lsof -i :${1}\n" + "}\n" + "\n" + "function searchPID(){\n" + " ps aux | grep ${1} | grep -v grep | awk '{print $2}'\n" + "}\n" + "\n" + "function killPID(){\n" + " pid=`ps aux | grep ${1} | grep -v grep | awk '{print $2}'`\n" + " if [ -n \"$pid\" ]; then\n" + " kill -9 $pid\n" + " sleep 1\n" + " fi\n" + "}\n" + "\n" + "\n" + "# 环境\n" + "function xDev() {\n" + " sshpass -f ENV_PIR.txt ssh xx@xx.xx.xx.${1} -t 'cd /work/www/d8ger.com/logs/; exec $SHELL'\n" + "}\n" + "\n" + "# 环境普通模式\n" + "function xDevNormal(){\n" + " sshpass -f ENV_PIR.txt ssh xx@xx.xx.xx.${1}\n" + "}\n" + "\n" + "# 不同环境\n" + "function backgroundENV() {\n" + " env=${1}\n" + " if [ -z \"$env\" ]; then\n" + " echo \"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\"\n" + " return\n" + " fi\n" + " domain=''\n" + " if [ \"$env\" = '1' ]; then\n" + " domain='https://1.d8ger.com'\n" + " elif [ \"$env\" = '2' ]; then\n" + " domain='https://2.d8ger.com'\n" + " elif [ \"$env\" = '3' ]; then\n" + " domain='https://3.d8ger.com'\n" + " elif [ \"$env\" = '4' ]; then\n" + " domain='https://4.d8ger.com'\n" + " elif [ \"$env\" = '5' ]; then\n" + " domain='https://5.d8ger.com'\n" + " elif [ \"$env\" = '6' ]; then\n" + " domain='https://6.d8ger.com'\n" + " elif [ \"$env\" = '7' ]; then\n" + " domain='https://7.d8ger.com'\n" + " elif [ \"$env\" = '8' ]; then\n" + " domain='https://8.d8ger.com'\n" + " elif [ \"$env\" = '9' ]; then\n" + " domain='https://9.d8ger.com'\n" + " elif [ \"$env\" = '10' ]; then\n" + " domain='https://ok.d8ger.com'\n" + " fi\n" + " # 判断\n" + " if [ -z \"$domain\" ]; then\n" + " echo \"请选择可用环境: 1,2,3,4,5,6,7,8,9,10\"\n" + " return\n" + " fi\n" + " echo \"德玛西亚, http -v --verify=no POST ${domain}/ok/xx\"\n" + " echo \"查询任务是否启动及是否完成: grep \\\"德玛西亚\\\" all.log | grep \\\"end\\\"\"\n" + " http -v --verify=no POST ${domain}/ok/xx\n" + "}\n" + "\n" + "function justDoIT(){\n" + " SID=${1}\n" + " if [ -z \"$SID\" ]; then\n" + " echo \"非法的SID, 请检查\"\n" + " return\n" + " fi \n" + " url=\"https://1.d8ger.com/xx/yy/zz\"\n" + " # 登录\n" + " login-cookie -f ~/Desktop/ssoLogin/sso-on-admin.json -a 6 \n" + " # 执行\n" + " echo \"执行:\\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\\n\"\n" + " # http多个参数不能放在一个字符串中, 用多个变量来区分解决\n" + " http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\n" + "}\n" + "\n" + "function cph(){\n" + " echo \",------. ,---. ,----. ,------.,------.\"\n" + " echo \"| .-. \\\\ | o |' .-./ | .---'| .--. '\"\n" + " echo \"| | \\\\ :.' '.| | .---.| \\`--, | '--'.'\"\n" + " echo \"| '--' /| o |' '--' || \\`---.| |\\\\ \\\\\"\n" + " echo \"\\`-------' \\`---' \\`------' \\`------'\\`--' '--'\"\n" + " echo \"##### SCP命令 #####\"\n" + " echo \"# -r 支持复制目录及其子文件\"\n" + " echo \"- 本地文件传到远程服务器\"\n" + " echo \"scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh caofan@172.16.10.59:~/\"\n" + " echo \"- 从远程服务器拉取文件\"\n" + " echo \"scp caofan@172.16.10.59:~/HAHA.tmp /Users/D8GER/Desktop/ssoLogin/ZZ.xls\"\n" + " echo \"- 无痕登录\"\n" + " echo \"xD8scp || d8scp\"\n" + " echo \"sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh caofan@172.16.10.59:~/\"\n" + " echo \"sshpass -f /Users/D8GER/Desktop/CAOFAN/sshpass/caofan-ssh-dev.txt scp /Users/D8GER/Desktop/ssoLogin/LEARN-SH.sh caofan@172.16.10.59:~/\"\n" + " echo \"##### cpv #####, zsh的一个插件cp, 文件复制时展示进度条\"\n" + " echo \"##### sudo cp #####, 普通复制\"\n" + "}\n" + "\n" + "function fkgrep(){\n" + " echo \",------.,--. ,--. ,----. ,------. ,------.,------.\"\n" + " echo \"| .---'| .' /' .-./ | .--. '| .---'| .--. '\"\n" + " echo \"| \\`--, | . ' | | .---.| '--'.'| \\`--, | '--' |\"\n" + " echo \"| |\\` | |\\\\ \\' '--' || |\\\\ \\\\ | \\`---.| | --'\"\n" + " echo \"\\`--' \\`--' '--' \\`------' \\`--' '--'\\`------'\\`--'\"\n" + " echo \"\"\n" + " echo \"grep -n '[a-zA-Z0-9]D8' X.txt\"\n" + " echo \"grep -n '[^a-zA-Z0-9]D9' X.txt\"\n" + " echo \"grep -n '^[a-z]' X.txt\"\n" + " echo \"grep -n '^[^a-z]' X.txt\"\n" + " echo \"grep -n '^$' X.txt\"\n" + " echo \"grep -n '\\.$' X.txt\"\n" + " echo \"grep -n 'g.*d' X.txt\"\n" + " echo \"grep -n 'go*d' X.txt\"\n" + " echo \"grep -n 'o\\{2,3\\}' X.txt\"\n" + " echo \"grep -En 'God|The' X.txt grep -n 'god\\|The' X.txt\"\n" + " echo \"grep -En 'o+' X.txt grep -n 'o\\+' X.txt\"\n" + " echo \"grep -n '\\.' X.txt grep -En '\\.' X.txt\"\n" + " echo \"grep -En '(oo)+' X.txt grep -n '\\(oo\\)\\+' X.txt\"\n" + " echo \"Search Today's log: ll -ah | grep \\\"[a-z_A-Z]\\+\\.log\\\"\"\n" + "}\n" + "\n" + "function arthasHelp(){\n" + " echo \" ,---. ,------. ,--------.,--. ,--. ,---. ,---.\"\n" + " echo \" / O \\\\ | .--. ''--. .--'| '--' | / O \\\\ ' .-'\"\n" + " echo \"| .-. || '--'.' | | | .--. || .-. |\\`. \\`-.\"\n" + " echo \"| | | || |\\\\ \\\\ | | | | | || | | |.-' |\"\n" + " echo \"\\`--' \\`--'\\`--' '--' \\`--' \\`--' \\`--'\\`--' \\`--'\\`-----'\"\n" + " # `和\\ 为特殊字符, 必须使用\\转义\n" + " echo \"\\n# 观察方法返回值\"\n" + " echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\" -x 2\"\n" + " echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\"\"\n" + " echo \"# 观察方法入参, 对象层次限制2级\"\n" + " echo \"watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \\\"{params,returnObj}\\\" -x 2 -b\"\n" + " echo \"# 持续记录3次接口调用\"\n" + " echo \"tt -t -n 3 com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage\"\n" + " echo \"# 展示记录接口调用的列表\"\n" + " echo \"tt -l\"\n" + " echo \"# 展示某个具体调用过程\"\n" + " echo \"tt -i 1002\"\n" + " echo \"# 重复某个具体调用, 重复3次, 重复间隔2秒\"\n" + " echo \"tt -i 1002 -p --replay-times 3 --replay-interval 2000\"\n" + " echo \"# 日志器\"\n" + " echo \"logger\"\n" + " echo \"# 类加载器列表\"\n" + " echo \"classloader -t\"\n" + " echo \"history\"\n" + " echo \"help\"\n" + " echo \"keymap\"\n" + " echo \"dashboard\"\n" + " echo \"# 清屏\"\n" + " echo \"cls\"\n" + " echo \"# 线程\"\n" + " echo \"thread\"\n" + " echo \"thread --state WAITING\"\n" + " echo \"thread --state TIMED_WAITING\"\n" + " echo \"thread --state RUNNABLE\"\n" + " echo \"\\n# 退出、关闭等命令, 禁止ctrl + C\"\n" + " echo \"# 退出某个命令\"\n" + " echo \"Q\"\n" + " echo \"# 退出当前arthas-client\"\n" + " echo \"quit\"\n" + " echo \"# 关闭arthas-server\"\n" + " echo \"shutdown\"\n" + "}\n" + "\n" + "alias searchPID='searchPID'\n" + "alias killPID='killPID'\n" + "alias searchPortOccupy='searchPortOccupy'\n" + "alias https-downLoadResponse='downLoadResponse'\n" + "alias https-show='show'\n" + "alias https-downLoadExcel='downLoadExcel'\n" + "alias https-downloadD8ger='downloadD8ger'\n" + "\n" + "alias 'xDev=xDev'\n" + "alias 'xDevNormal=xDevNormal'\n" + "alias 'backgroundENV=backgroundENV'\n" + "\n" + "alias 'showssh=ps -ef | grep ssh'\n" + "alias 'tsm=justDoIT'\n" + "# 开隧道\n" + "alias 'iphone4j=nohup sshpass -f TUNNEL_DIR ssh xx@xx.xx.xx.xx -L 11186:xx.xx.xx.xx:1186 -N &'\n" + "\n" + "alias 'ip=ifconfig | grep xxx'\n" + "\n" + "alias 'cph=cph'\n" + "alias 'fkgrep=fkgrep'\n" + "alias 'arthasHelp=arthasHelp'\n" + "# 快速编辑.zshrc\n" + "alias 'vrc=vim ~/.zshrc'\n" + "# 快速展示.zshrc\n" + "alias 'crc=cat ~/.zshrc'\n" + "\n" + "# source ~/.bash_profile\n" + "if [ -f ~/.bash_profile ]; then\n" + " . ~/.bash_profile;\n" + "fi\n" + "\n" + "\n" + "source $ZSH/oh-my-zsh.sh\n"; public static String TEMPLATE_NASA = "=========================================NASA=========================================\n" + "Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\n" + " which these context included will be ignored;\n" + " 2.Multi-lines to be handled must include ','\n" + " as the split keyword\n" + " 3.config example:\n" + " - @@ , add 'D8(' before the start of each line\n" + " - @@ , add ')' after the end of each line\n" + " - @@ , you can config CENTER, RIGHT too\n" + " - @@ , if config SQL then it will append 'AS' alias name\n" + " - @@ , special for SQL column alias camel name\n" + " 4.As example below, one handled what you will find like this:\n" + " first_name, --> D8(first_name) AS firstName,\n" + " current_age, --> D8(current_age) AS currentAge,\n" + " blog_url, --> D8(blog_url) AS blogUrl,\n" + " graduated_school, --> D8(graduated_school) AS graduatedSchool,\n" + " total_assets --> D8(total_assets) AS totalAssets\n" + "=========================================NASA=========================================\n" + "The next line is very import below, do not modify anything or you'll get nothing\n" + "@D8ger-ALIGN@\n" + "\n" + "\n" + "first_name,\n" + "current_age,\n" + "blog_url,\n" + "graduated_school,\n" + "total_assets\n"; public static String TEMPLATE_END = "=========================================END=========================================\n" + "Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text,\n" + " which these context included will be ignored;\n" + " 2.Considering compatibility separator, Multi-lines to be handled\n" + " must include ',' or line break or ',' as the split keyword.\n" + " 3.config example:\n" + " - @@ , LEFT(default) and you can config CENTER, RIGHT too\n" + " - @@ , 1(default) as 'AES' and 2 as 'PinYin'\n" + " - @@ , 1 as encrypt, 2 as decrypt\n" + " and 0(default) is encrypt + decrypt for complete\n" + " 4.As example below, one handled what you will find like this:\n" + " When algorithmType=1 && operateType = 0\n" + " MyName -->(first AES encryption) d8gerX==\n" + " -->(then AES decryption) MyName\n" + " When algorithmType=2 && operateType = 0\n" + " 帝八哥 -->(first Fetch Chinese PinYin) dibage\n" + " -->(then PinYin encryption) d8gerY==\n" + " -->(last PinYin decryption) dibage\n" + " Other case, just refer the two above.\n" + "=========================================END=========================================\n" + "The next line is very import below, do not modify anything or you'll get nothing\n" + "@D8ger-END@\n" + "\n" + "\n" + "AName"; /** * Template rendering * * @param template * @param bindingMap * @return */ public static StringBuilder render(@NonNull StringBuilder template, Map bindingMap) { StringBuilder result = template; for (Map.Entry entry : bindingMap.entrySet()) { VerbalExpression regex = VerbalExpressionUtil.buildRegex(entry.getKey()); result = VerbalExpressionUtil.executePatternRex(regex, result, entry.getValue()); } return result; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/D8gerAutoCoding.java ================================================ package com.xyz.caofancpu.d8ger.core; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiField; import com.intellij.psi.PsiJavaFile; import com.xyz.caofancpu.d8ger.util.CollectionUtil; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import com.xyz.caofancpu.d8ger.util.IdeaPlatformFileTreeUtil; import com.xyz.caofancpu.d8ger.util.PropertiesUtil; import com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil; import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.experimental.Accessors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; /** * Automatically generate code core classes * * @author caofanCPU */ @Data @NoArgsConstructor @Accessors(chain = true) public class D8gerAutoCoding { /** * Project where the current file is located */ private Project currentProject; /** * Module where the current file is located */ private Module currentModule; /** * Resource root directory file */ private VirtualFile rootResource; /** * Automatic code generation directory */ private PsiDirectory d8AutoCodeDir; /** * Flag of using D8AutoCode directory or not */ private boolean useDefaultDirectory; /** * Original model file object */ private PsiJavaFile originMoJavaFile; /** * Original model class object, take only the first one by default */ private PsiClass originMoPsiClass; /** * Original model class name */ private String originMoName; /** * Field list of the original model class object */ private List moFieldList; /** * FileMap, value: Pair */ private Map> fileMap = new HashMap<>(32, 0.75f); /** * Template keyword match replacement Map */ private Map keyWordMatchMap = new HashMap<>(32, 0.75f); /** * Storage custom config directories that auto code files put into */ private Map> customConfigAutoCodeDirMap = new HashMap<>(16, 0.75f); /** * Real need create file, just for marking */ private List realNeedCreateFileKeyList = new ArrayList<>(); /** * Construction methods exposed to the outside world, * pay attention to the method execution order * * @param currentProject * @param currentModule * @param rootResource * @param moJavaFile * @return */ public static D8gerAutoCoding build(@NonNull Project currentProject, @NonNull Module currentModule, @NonNull VirtualFile rootResource, @NonNull PsiJavaFile moJavaFile) { return new D8gerAutoCoding() // Set the project .setCurrentProject(currentProject) // Set the module .setCurrentModule(currentModule) // config resource root directory file .setRootResource(rootResource) // config directory which current Java file is located .setD8AutoCodeDir(moJavaFile.getContainingDirectory()) // Set model type of PsiJavaFile .setOriginMoJavaFile(moJavaFile) // Set model class type of PsiClass .configOriginPsiClass() // Set field list .initMoFieldList() // Config custom directory Map .initCustomConfigAutoCodeDirMap() // Config keyword Map .initKeyWordMap() // Config file Map .initFileMap(); } /** * File name Map * * @return */ private D8gerAutoCoding initFileMap() { fileMap.put(KeyEnum.MO, Pair.of(this.getMoName().concat(ConstantUtil.MO_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO : AutoCodeTemplate.ZN_TEMPLATE_MO)); fileMap.put(KeyEnum.SWAGGER_MO, Pair.of(this.getMoName().concat(ConstantUtil.SWAGGER_MO_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_SWAGGER_VO : AutoCodeTemplate.ZN_TEMPLATE_SWAGGER_VO)); fileMap.put(KeyEnum.MO_EXAMPLE, Pair.of(this.getMoName().concat(ConstantUtil.MO_EXAMPLE_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO_EXAMPLE : AutoCodeTemplate.ZN_TEMPLATE_MO_EXAMPLE)); fileMap.put(KeyEnum.MO_MAPPER, Pair.of(this.getMoName().concat(ConstantUtil.MO_MAPPER_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MAPPER : AutoCodeTemplate.ZN_TEMPLATE_MAPPER)); fileMap.put(KeyEnum.MO_HANDLER, Pair.of(this.getMoName().concat(ConstantUtil.MO_HANDLER_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_HANDLER : AutoCodeTemplate.ZN_TEMPLATE_HANDLER)); fileMap.put(KeyEnum.MO_CONTROLLER, Pair.of(this.getMoName().concat(ConstantUtil.MO_CONTROLLER_NAME_SUFFIX).concat(ConstantUtil.JAVA_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_CONTROLLER : AutoCodeTemplate.ZN_TEMPLATE_CONTROLLER)); fileMap.put(KeyEnum.MO_MAPPER_XML, Pair.of(this.getMoName().concat(ConstantUtil.MO_MAPPER_NAME_SUFFIX).concat(ConstantUtil.XML_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MAPPER_XML : AutoCodeTemplate.ZN_TEMPLATE_MAPPER_XML)); fileMap.put(KeyEnum.MO_SQL, Pair.of(this.getMoName().concat(ConstantUtil.SQL_FILE_SUFFIX), AutoCodeTemplate.IS_EN_LOCALE ? AutoCodeTemplate.TEMPLATE_MO_SQL : AutoCodeTemplate.ZN_TEMPLATE_MO_SQL)); return this; } private List getAllFileKeyList() { List keyEnumList = new ArrayList<>(); keyEnumList.add(KeyEnum.MO); keyEnumList.add(KeyEnum.SWAGGER_MO); keyEnumList.add(KeyEnum.MO_EXAMPLE); keyEnumList.add(KeyEnum.MO_MAPPER); keyEnumList.add(KeyEnum.MO_HANDLER); keyEnumList.add(KeyEnum.MO_CONTROLLER); keyEnumList.add(KeyEnum.MO_MAPPER_XML); keyEnumList.add(KeyEnum.MO_SQL); return keyEnumList; } /** * Init custom config directories that auto code files put into * * @return */ private D8gerAutoCoding initCustomConfigAutoCodeDirMap() { Properties properties = loadPropertiesFromRootResource(); List keyEnumList = getAllFileKeyList(); keyEnumList.forEach(keyEnum -> { if (PropertiesUtil.checkConfigTakeEffect(properties, keyEnum.getKey())) { realNeedCreateFileKeyList.add(keyEnum); } String directoryPath = PropertiesUtil.detectConfigDirectoryPath(properties, keyEnum.getKey()); if (StringUtils.isNotBlank(directoryPath)) { PsiDirectory targetDir = IdeaPlatformFileTreeUtil.getOrCreateSubDirByPath(currentProject, directoryPath); if (Objects.nonNull(targetDir)) { String targetPackage = VerbalExpressionUtil.convertPathToPackage(directoryPath); customConfigAutoCodeDirMap.put(keyEnum, Pair.of(targetDir, targetPackage)); } } }); return this; } /** * Load custom config properties * * @return */ public Properties loadPropertiesFromRootResource() { return PropertiesUtil.loadPropertiesFromRootResource(this.currentProject); } /** * Template keywords Map * * @return */ private D8gerAutoCoding initKeyWordMap() { keyWordMatchMap.put(TemplateKeyWordEnum.MO_NAME_KEY.getName(), new StringBuilder(this.getMoName())); keyWordMatchMap.put(TemplateKeyWordEnum.PACKAGE_NAME_KEY.getName(), new StringBuilder(this.getPackageName())); keyWordMatchMap.put(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY.getName(), new StringBuilder(StringUtils.uncapitalize(this.getMoName()))); Properties properties = loadPropertiesFromRootResource(); keyWordMatchMap.put(TemplateKeyWordEnum.AUTHOR_KEY.getName(), StringUtils.isNotBlank(properties.getProperty(ConstantUtil.CONFIG_AUTHOR_KEY)) ? new StringBuilder(properties.getProperty(ConstantUtil.CONFIG_AUTHOR_KEY)) : new StringBuilder(ConstantUtil.DEFAULT_AUTHOR)); String apiUrlPrefix; if (StringUtils.isBlank(properties.getProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY))) { apiUrlPrefix = ConstantUtil.DEFAULT_API_URL_PREFIX; } else { apiUrlPrefix = VerbalExpressionUtil.correctUrl(properties.getProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY)); } // handle mapper's annotation boolean isMapper = PropertiesUtil.checkConfigTakeEffect(properties, KeyEnum.MO_MAPPER_ANNOTATION.getKey()); Pair mapperPair = isMapper ? ConstantUtil.BOOT_MAPPER : ConstantUtil.MVC_MAPPER; keyWordMatchMap.put(TemplateKeyWordEnum.MAPPER_ANNOTATION_PACKAGE_KEY.getName(), new StringBuilder(mapperPair.getLeft())); keyWordMatchMap.put(TemplateKeyWordEnum.MAPPER_ANNOTATION_KEY.getName(), new StringBuilder(mapperPair.getRight())); keyWordMatchMap.put(TemplateKeyWordEnum.API_URL_PREFIX_KEY.getName(), new StringBuilder(apiUrlPrefix)); keyWordMatchMap.put(TemplateKeyWordEnum.MO_FIELD_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toString), ConstantUtil.DOUBLE_NEXT_LINE))); keyWordMatchMap.put(TemplateKeyWordEnum.SWAGGER_MO_FIELD_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toSwaggerString), ConstantUtil.DOUBLE_NEXT_LINE)).append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE).append(wrapSwaggerPage())); keyWordMatchMap.put(TemplateKeyWordEnum.MO_EXAMPLE_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toMoExampleDefinitionMethodString), ConstantUtil.EMPTY))); keyWordMatchMap.put(TemplateKeyWordEnum.SQL_MO_TABLE_KEY.getName(), new StringBuilder(VerbalExpressionUtil.sqlUnderLineName(this.getMoName()))); keyWordMatchMap.put(TemplateKeyWordEnum.SQL_MO_COLUMN_KEY.getName(), new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, MoField::toSqlColumnDefinitionString), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE))); keyWordMatchMap.put(TemplateKeyWordEnum.XML_BASE_COLUMN_LIST_KEY.getName(), this.getXMLBaseColumnList()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_SELECT_BASE_COLUMN_LIST_KEY.getName(), this.getXMLSelectBaseColumnList()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY.getName(), this.getXMLBatchUpdateNonNullFieldByID()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_COLUMN_LIST_KEY.getName(), this.getXMLInsertSelectiveColumnList()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_FIELD_LIST_KEY.getName(), this.getXMLInsertSelectiveFieldList()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY.getName(), this.getXMLUpdateNonNullFieldByExample()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_INSERT_COLUMN_LIST_KEY.getName(), this.getXMLInsertField()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_BATCH_INSERT_COLUMN_LIST_KEY.getName(), this.getXMLBatchInsertField()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_ID_KEY.getName(), this.getXMLUpdateNonNullFieldByID()); keyWordMatchMap.put(TemplateKeyWordEnum.XML_MO_LIST_QUERY_KEY.getName(), this.getXMLMoListQuery()); return this; } /** * Enhance swagger model with paging request field * * @return */ public String wrapSwaggerPage() { return ConstantUtil.TAB + "@ApiModelProperty(value = \"" + "pageNum" + "\", required = false, example = \"1\", position = " + (moFieldList.size() + 1) + ")" + ConstantUtil.NEXT_LINE + ConstantUtil.TAB + ConstantUtil.DEFAULT_ACCESS_MODIFIER + ConstantUtil.SPACE + SupportFieldTypeEnum.INTEGER.getShortName() + ConstantUtil.SPACE + ConstantUtil.PAGE_NUM_NAME + ConstantUtil.ENGLISH_SEMICOLON + ConstantUtil.NEXT_LINE + ConstantUtil.NEXT_LINE + ConstantUtil.TAB + "@ApiModelProperty(value = \"" + "pageSize" + "\", required = false, example = \"10\", position = " + (moFieldList.size() + 2) + ")" + ConstantUtil.NEXT_LINE + ConstantUtil.TAB + ConstantUtil.DEFAULT_ACCESS_MODIFIER + ConstantUtil.SPACE + SupportFieldTypeEnum.INTEGER.getShortName() + ConstantUtil.SPACE + ConstantUtil.PAGE_SIZE_NAME + ConstantUtil.ENGLISH_SEMICOLON; } /** * To improve performance, only the internal key is selected for each file to reduce the number of string replacements * * @param key * @return */ public Map loadEnhanceKeyWordMap(KeyEnum key) { Map resultMap = new HashMap<>(32, 0.65f); if (KeyEnum.FORMAT_STYLE == key) { return resultMap; } List keyWordEnumList = new ArrayList<>(TemplateKeyWordEnum.values().length); switch (key) { case MO: keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_FIELD_KEY); break; case SWAGGER_MO: keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_FIELD_KEY); break; case MO_EXAMPLE: keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_KEY); break; case MO_MAPPER_XML: keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_SELECT_BASE_COLUMN_LIST_KEY); keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_TABLE_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_UPDATE_NONNULL_FIELD_BY_ID_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_BASE_COLUMN_LIST_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_BATCH_INSERT_COLUMN_LIST_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_MO_LIST_QUERY_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_COLUMN_LIST_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_COLUMN_LIST_KEY); keyWordEnumList.add(TemplateKeyWordEnum.XML_INSERT_SELECTIVE_FIELD_LIST_KEY); break; case MO_SQL: keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_TABLE_KEY); keyWordEnumList.add(TemplateKeyWordEnum.SQL_MO_COLUMN_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); break; case MO_MAPPER: keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_ANNOTATION_PACKAGE_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_ANNOTATION_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_EXAMPLE_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY); break; case MO_HANDLER: keyWordEnumList.add(TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MAPPER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY); break; case MO_CONTROLLER: keyWordEnumList.add(TemplateKeyWordEnum.CONTROLLER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.HANDLER_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.SWAGGER_MO_PACKAGE_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.AUTHOR_KEY); keyWordEnumList.add(TemplateKeyWordEnum.UNCAPITALLIZE_MO_NAME_KEY); keyWordEnumList.add(TemplateKeyWordEnum.API_URL_PREFIX_KEY); break; } Map keyWordMatchMap = getKeyWordMatchMap(); keyWordEnumList.forEach(templateKey -> resultMap.put(templateKey.getName(), keyWordMatchMap.get(templateKey.getName()))); return resultMap; } /** * Encapsulating model field object * * @return */ private D8gerAutoCoding initMoFieldList() { PsiField[] selfOwnedFields = this.originMoPsiClass.getFields(); // extract original field list this.setMoFieldList(CollectionUtil.transToList(Arrays.asList(selfOwnedFields), MoField::new)); // enhance by configuration Properties properties = loadPropertiesFromRootResource(); // Language configuration if (ConstantUtil.OPTIONAL_CONFIG_LANGUAGE.equals(properties.getProperty(ConstantUtil.CONFIG_LANGUAGE_KEY))) { // Annotation Chinese Culture AutoCodeTemplate.IS_EN_LOCALE = Boolean.FALSE; } else { AutoCodeTemplate.IS_EN_LOCALE = Boolean.TRUE; } if (Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID)))) { this.produceIdField(); } // whether auto generate create_time and update_time column definition by custom config boolean sqlDetectTimeColumn = PropertiesUtil.checkConfigTakeEffect(properties, KeyEnum.SQL_DETECT_TIME_COLUMN.getKey()); if (sqlDetectTimeColumn && Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_CREATE_TIME)))) { this.produceCreateTimeField(); } if (sqlDetectTimeColumn && Objects.isNull(CollectionUtil.findFirst(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_UPDATE_TIME)))) { this.produceUpdateTimeField(); } // Set field order moFieldList.forEach(item -> item.setIndex(moFieldList.indexOf(item))); return this; } /** * Get enum field type * * @return */ public List getEnumTypeClassName() { return CollectionUtil.filterAndTransList(moFieldList, item -> SupportFieldTypeEnum.ENUM.getOriginName().equals(item.getFieldOriginTypeName()), MoField::getFieldTypeShortName); } /** * Model name * * @return */ public String getMoName() { String originMoName = Objects.nonNull(this.getOriginMoName()) ? this.getOriginMoName() : VerbalExpressionUtil.cropMoSuffix(originMoJavaFile.getClasses()[0].getName()); this.setOriginMoName(originMoName); return originMoName; } /** * package name * * @return */ public String getPackageName() { return originMoJavaFile.getPackageName() + ConstantUtil.ENGLISH_FULL_STOP + ConstantUtil.GENERATE_DIR; } /** * SQL-BaseColumnList, exclude primary key column `id` | `createTime` | `updateTime` * example: * `name`, * `hello_d8ger` * * @return */ private StringBuilder getXMLBaseColumnList() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME), item -> ConstantUtil.TRIPLE_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`" ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE)); } /** * SQL-SelectBaseColumnList(with alias name) * example: * `id` AS id, * `name` AS name, * `hello_d8ger` AS helloD8ger * * @return */ private StringBuilder getXMLSelectBaseColumnList() { return new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, item -> ConstantUtil.TRIPLE_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "` AS " + item.getName() ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE)); } /** * SQL-BatchUpdateNonNullFieldByID * * @return */ private StringBuilder getXMLBatchUpdateNonNullFieldByID() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID), item -> ConstantUtil.QUATERNARY_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.PENTA_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`" + ConstantUtil.SPACE + "=" + ConstantUtil.SPACE + "#{item." + item.getName() + "}," + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "" ), ConstantUtil.NEXT_LINE)); } /** * SQL-NonNullColumnList * * @return */ private StringBuilder getXMLInsertSelectiveColumnList() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID), item -> ConstantUtil.TRIPLE_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`," + ConstantUtil.NEXT_LINE + ConstantUtil.TRIPLE_TAB + "" ), ConstantUtil.NEXT_LINE)); } /** * SQL-NonNullInsertField * * @return */ private StringBuilder getXMLInsertSelectiveFieldList() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID), item -> ConstantUtil.TRIPLE_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "#{" + item.getName() + "}," + ConstantUtil.NEXT_LINE + ConstantUtil.TRIPLE_TAB + "" ), ConstantUtil.NEXT_LINE)); } /** * SQL-UpdateNonNullFieldByExample, exclude primary key column `id` * * @return */ private StringBuilder getXMLUpdateNonNullFieldByExample() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID), item -> ConstantUtil.TRIPLE_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`" + ConstantUtil.SPACE + "=" + ConstantUtil.SPACE + "#{record." + item.getName() + "}," + ConstantUtil.NEXT_LINE + ConstantUtil.TRIPLE_TAB + "" ), ConstantUtil.NEXT_LINE)); } /** * SQL-Insert, exclude primary key column `id` | `createTime` | `updateTime` * * @return */ private StringBuilder getXMLInsertField() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME), item -> ConstantUtil.TRIPLE_TAB + "#{" + item.getName() + "}" ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE)); } /** * SQL-BatchInsertField, exclude primary key column `id` | `createTime` | `updateTime` * * @return */ private StringBuilder getXMLBatchInsertField() { return new StringBuilder(ConstantUtil.TRIPLE_TAB).append("(").append(ConstantUtil.NEXT_LINE) .append(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID) || item.getName().equals(ConstantUtil.SQL_CREATE_TIME) || item.getName().equals(ConstantUtil.SQL_UPDATE_TIME), item -> ConstantUtil.QUATERNARY_TAB + "#{item." + item.getName() + "}" ), ConstantUtil.ENGLISH_COMMA + ConstantUtil.NEXT_LINE)) .append(ConstantUtil.NEXT_LINE).append(ConstantUtil.TRIPLE_TAB).append(")"); } /** * SQL-UpdateNonNullFieldByID * * @return */ private StringBuilder getXMLUpdateNonNullFieldByID() { return new StringBuilder(CollectionUtil.join(CollectionUtil.removeAndTransList(moFieldList, item -> item.getName().equals(ConstantUtil.SQL_ID), item -> ConstantUtil.TRIPLE_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "`" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`" + ConstantUtil.SPACE + "=" + ConstantUtil.SPACE + "#{" + item.getName() + "}," + ConstantUtil.NEXT_LINE + ConstantUtil.TRIPLE_TAB + "" ), ConstantUtil.NEXT_LINE)); } /** * SQL-QueryModelList * * @return */ private StringBuilder getXMLMoListQuery() { return new StringBuilder(CollectionUtil.join(CollectionUtil.transToList(moFieldList, item -> { String tmp; if (SupportFieldTypeEnum.STRING.getShortName().equals(item.getFieldTypeShortName())) { tmp = "LIKE " + "CONCAT(#{" + item.getName() + "}, '%')"; } else { tmp = "=" + ConstantUtil.SPACE + "#{" + item.getName() + "}"; } return ConstantUtil.TRIPLE_TAB + "" + ConstantUtil.NEXT_LINE + ConstantUtil.QUATERNARY_TAB + "AND `" + VerbalExpressionUtil.sqlUnderLineName(item.getName()) + "`" + ConstantUtil.SPACE + tmp + ConstantUtil.NEXT_LINE + ConstantUtil.TRIPLE_TAB + ""; } ), ConstantUtil.NEXT_LINE)); } /** * Config origin Model class * * @return */ public D8gerAutoCoding configOriginPsiClass() { return this.setOriginMoPsiClass(originMoJavaFile.getClasses()[0]); } /** * For an optional, auto add 'id' field */ private void produceIdField() { String comment = StringUtils.upperCase(ConstantUtil.SQL_ID); SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LONG; MoField idField = new MoField() .setComment(comment) .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER) .setFieldOriginTypeName(idFieldType.getOriginName()) .setFieldTypeShortName(idFieldType.getShortName()) .setFieldSqlTypeName(idFieldType.getSqlName()) .setName(ConstantUtil.SQL_ID); this.moFieldList.add(0, idField); } /** * For an optional, auto add 'createTime' field */ private void produceCreateTimeField() { String comment = AutoCodeTemplate.IS_EN_LOCALE ? ConstantUtil.SQL_CREATE_TIME : ConstantUtil.ZN_SQL_CREATE_TIME; SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LOCAL_DATE_TIME; MoField idField = new MoField() .setComment(comment) .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER) .setFieldOriginTypeName(idFieldType.getOriginName()) .setFieldTypeShortName(idFieldType.getShortName()) .setFieldSqlTypeName(idFieldType.getSqlName()) .setName(ConstantUtil.SQL_CREATE_TIME); this.moFieldList.add(idField); } /** * For an optional, auto add 'updateTime' field */ private void produceUpdateTimeField() { String comment = AutoCodeTemplate.IS_EN_LOCALE ? ConstantUtil.SQL_UPDATE_TIME : ConstantUtil.ZN_SQL_UPDATE_TIME; SupportFieldTypeEnum idFieldType = SupportFieldTypeEnum.LOCAL_DATE_TIME; MoField idField = new MoField() .setComment(comment) .setAccessModifier(ConstantUtil.DEFAULT_ACCESS_MODIFIER) .setFieldOriginTypeName(idFieldType.getOriginName()) .setFieldTypeShortName(idFieldType.getShortName()) .setFieldSqlTypeName(idFieldType.getSqlName()) .setName(ConstantUtil.SQL_UPDATE_TIME); this.moFieldList.add(idField); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/EasterEggCodeTemplateEnum.java ================================================ package com.xyz.caofancpu.d8ger.core; /** * EasterEgg code template keyword enumeration * * @author caofanCPU */ public enum EasterEggCodeTemplateEnum { D8GER_CONFIG_FILE_KEY("D8GER", AutoCodeTemplate.TEMPLATE_D8GER), REGEX_CONFIG_FILE_KEY("REGEX", AutoCodeTemplate.TEMPLATE_REGEX), OH_MY_ZSH_CONFIG_FILE_KEY("OHMYZSH", AutoCodeTemplate.TEMPLATE_OH_MY_ZSH), END_CONFIG_FILE_KEY("END", AutoCodeTemplate.TEMPLATE_END), NASA_CONFIG_FILE_KEY("NASA", AutoCodeTemplate.TEMPLATE_NASA), ; private String codeKey; private String templateCode; EasterEggCodeTemplateEnum(String codeKey, String templateCode) { this.codeKey = codeKey; this.templateCode = templateCode; } public String getCodeKey() { return codeKey; } public String getTemplateCode() { return templateCode; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/KeyEnum.java ================================================ package com.xyz.caofancpu.d8ger.core; /** * Generate file enum * * @author caofanCPU */ public enum KeyEnum { MO("autoCreateMo"), SWAGGER_MO("autoCreateSwaggerMo"), MO_MAPPER("autoCreateMapper"), MO_EXAMPLE("autoCreateExample"), MO_MAPPER_XML("autoCreateXML"), MO_HANDLER("autoCreateHandler"), MO_CONTROLLER("autoCreateController"), MO_SQL("autoCreateDefinitionSQL"), FORMAT_STYLE("autoFormatStyle"), SQL_DETECT_TIME_COLUMN("autoDetectSQLTimeColumn"), MO_MAPPER_ANNOTATION("mapperBetterThenRepository"), ; private String key; KeyEnum(String key) { this.key = key; } /** * Judge create file or not * * @param key * @return */ @Deprecated public static boolean ignoreCreateFile(KeyEnum key) { return MO_CONTROLLER == key; } /** * Judge import enumeration classes or not in Java files * * @param key * @return */ public static boolean needImportEnumClass(KeyEnum key) { return MO == key || SWAGGER_MO == key || MO_EXAMPLE == key; } public String getKey() { return key; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/MoField.java ================================================ package com.xyz.caofancpu.d8ger.core; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiIdentifier; import com.intellij.psi.PsiModifierList; import com.intellij.psi.PsiTypeElement; import com.intellij.psi.impl.source.tree.PsiCommentImpl; import com.intellij.psi.javadoc.PsiDocComment; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import com.xyz.caofancpu.d8ger.util.VerbalExpressionUtil; import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.experimental.Accessors; import org.apache.commons.lang3.StringUtils; import java.util.Objects; /** * Model encapsulated object * * @author caofanCPU */ @Data @NoArgsConstructor @Accessors(chain = true) public class MoField { /** * Field comment(name) */ private String comment; /** * Access modifier, private is used by default */ private String accessModifier; /** * Field primitive type name */ private String fieldOriginTypeName; /** * Field type abbreviation */ private String fieldTypeShortName; /** * Field SQL Type Name */ private String fieldSqlTypeName; /** * Field Name */ private String name; /** * Field order */ private int index; public MoField(@NonNull PsiField field) { PsiElement[] children = field.getChildren(); for (PsiElement child : children) { if (child instanceof PsiCommentImpl || child instanceof PsiDocComment) { this.comment = VerbalExpressionUtil.extractComment(child.getText()).trim(); continue; } if (child instanceof PsiModifierList) { this.accessModifier = child.getText(); continue; } if (child instanceof PsiTypeElement) { if (Objects.nonNull(child.getText()) && StringUtils.containsIgnoreCase(child.getText(), ConstantUtil.ENUM_SUFFIX)) { // Enums or enums with names that are enumerated this.fieldOriginTypeName = SupportFieldTypeEnum.ENUM.getOriginName(); this.fieldTypeShortName = child.getText(); this.fieldSqlTypeName = SupportFieldTypeEnum.ENUM.getSqlName(); } else { SupportFieldTypeEnum fieldTypeEnum = SupportFieldTypeEnum.positionByShortName(child.getText()); this.fieldOriginTypeName = fieldTypeEnum.getOriginName(); this.fieldTypeShortName = fieldTypeEnum.getShortName(); this.fieldSqlTypeName = fieldTypeEnum.getSqlName(); } continue; } if (child instanceof PsiIdentifier) { this.name = child.getText(); } } if (Objects.isNull(this.comment)) { this.comment = ConstantUtil.EMPTY; } if (Objects.isNull(this.accessModifier)) { this.accessModifier = ConstantUtil.DEFAULT_ACCESS_MODIFIER; } } /** * SQL columns field type display * * @return */ public String wrapSqlDefaultValueView() { if (Objects.isNull(fieldSqlTypeName)) { return ConstantUtil.EMPTY; } if (fieldSqlTypeName.contains("int")) { return "default 0 null"; } if (fieldSqlTypeName.contains("double")) { return "default 0.00 null"; } if (fieldSqlTypeName.contains("datetime")) { return name.equals(ConstantUtil.SQL_UPDATE_TIME) ? "default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP" : "default CURRENT_TIMESTAMP null"; } return "default '' null"; } @Override public String toString() { return ConstantUtil.TAB + "/**\n" + ConstantUtil.TAB + ConstantUtil.SPACE + "*" + ConstantUtil.SPACE + comment + "\n" + ConstantUtil.TAB + ConstantUtil.SPACE + "*/" + "\n" + ConstantUtil.TAB + accessModifier + ConstantUtil.SPACE + fieldTypeShortName + ConstantUtil.SPACE + name + ConstantUtil.ENGLISH_SEMICOLON; } /** * Swagger fields * * @return */ public String toSwaggerString() { return ConstantUtil.TAB + "@ApiModelProperty(value = \"" + comment + "\", required = false, example = \"\", position = " + (index + 1) + ")" + ConstantUtil.NEXT_LINE + ConstantUtil.TAB + accessModifier + ConstantUtil.SPACE + fieldTypeShortName + ConstantUtil.SPACE + name + ConstantUtil.ENGLISH_SEMICOLON; } /** * SQL columns definition field * * @return */ public String toSqlColumnDefinitionString() { if (name.equals(ConstantUtil.SQL_ID)) { return ConstantUtil.TAB + ConstantUtil.SQL_ID + ConstantUtil.SPACE + fieldSqlTypeName + ConstantUtil.SPACE + "unsigned auto_increment" + ConstantUtil.SPACE + "comment" + ConstantUtil.SPACE + "'" + comment + "'" + ConstantUtil.SPACE + "primary key"; } return ConstantUtil.TAB + VerbalExpressionUtil.sqlUnderLineName(name) + ConstantUtil.SPACE + fieldSqlTypeName + ConstantUtil.SPACE + wrapSqlDefaultValueView() + ConstantUtil.SPACE + "comment" + ConstantUtil.SPACE + "'" + comment + "'"; } /** * SQL operating methods by using example object * * @return */ public String toMoExampleDefinitionMethodString() { String capitalizeName = StringUtils.capitalize(name); String sqlColumnName = VerbalExpressionUtil.sqlUnderLineName(name); String javaTypeShortName = fieldTypeShortName; String fieldTypeInListShortName = SupportFieldTypeEnum.BASIC_INT.getShortName().equals(fieldOriginTypeName) ? SupportFieldTypeEnum.INTEGER.getShortName() : StringUtils.capitalize(javaTypeShortName); StringBuilder builder = new StringBuilder(); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Is Null").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("IsNull() {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("is null\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("IS Not Null").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("IsNotNull() {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("is not null\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Equal").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("EqualTo(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("=\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Not Equal").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("NotEqualTo(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("<>\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Greater Than").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("GreaterThan(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append(">\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Greater Than Or Equal To").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("GreaterThanOrEqualTo(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append(">=\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Less Than").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("LessThan(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("<\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Less Than Or Equal To").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("LessThanOrEqualTo(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("<=\", value, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("In").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("In(List<").append(fieldTypeInListShortName).append(">").append(ConstantUtil.SPACE).append("values) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("in\", values, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Not In").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("NotIn(List<").append(fieldTypeInListShortName).append(">").append(ConstantUtil.SPACE).append("values) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("not in\", values, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Between").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("Between(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value1,").append(ConstantUtil.SPACE).append(javaTypeShortName).append(ConstantUtil.SPACE).append("value2) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("between\", value1, value2, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Not Between").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("NotBetween(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value1,").append(ConstantUtil.SPACE).append(javaTypeShortName).append(ConstantUtil.SPACE).append("value2) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("not between\", value1, value2, \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); if (SupportFieldTypeEnum.STRING.getShortName().equals(fieldTypeShortName)) { // 字符串字段, 添加前缀模糊查询 builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Like").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("Like(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("like\", value + \"%\", \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); builder.append(ConstantUtil.DOUBLE_TAB).append("/**").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append(name).append(ConstantUtil.SPACE).append("Not Like").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*").append(ConstantUtil.SPACE).append("@return").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append(ConstantUtil.SPACE).append("*/").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("public Criteria and").append(capitalizeName).append("NotLike(").append(javaTypeShortName).append(ConstantUtil.SPACE).append("value) {").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("addCriterion(\"").append(sqlColumnName).append(ConstantUtil.SPACE).append("not like\", value + \"%\", \"").append(name).append("\");").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.TRIPLE_TAB).append("return (Criteria) this;").append(ConstantUtil.NEXT_LINE) .append(ConstantUtil.DOUBLE_TAB).append("}").append(ConstantUtil.NEXT_LINE).append(ConstantUtil.NEXT_LINE); } return builder.toString(); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/ProjectEnvHandler.java ================================================ package com.xyz.caofancpu.d8ger.core; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import java.util.Objects; /** * Initialize the project environment parameters * * @author caofanCPU */ public class ProjectEnvHandler { public static D8gerAutoCoding checkAndInitEnv(AnActionEvent e) { PsiFile currentPsiFile = e.getData(CommonDataKeys.PSI_FILE); if (Objects.isNull(currentPsiFile) || !(currentPsiFile instanceof PsiJavaFile)) { Messages.showErrorDialog("No .java file chosen", "Initialize Environment Error"); return null; } PsiJavaFile currentJavaFile = (PsiJavaFile) currentPsiFile; if (currentJavaFile.getClasses().length == 0) { Messages.showErrorDialog("No class defined in current chosen .java file", "Initialize Environment Error"); return null; } Project currentProject = e.getData(PlatformDataKeys.PROJECT); if (Objects.isNull(currentProject)) { Messages.showErrorDialog("Not included in a project for current chosen .java file", "Initialize Environment Error"); return null; } Module currentModule = FileIndexFacade.getInstance(currentProject).getModuleForFile(currentPsiFile.getVirtualFile()); if (Objects.isNull(currentModule)) { Messages.showErrorDialog("Not included in a module for current chosen .java file", "Initialize Environment Error"); return null; } VirtualFile rootResource = ModuleRootManager.getInstance(currentModule).getSourceRoots(JavaModuleSourceRootTypes.RESOURCES).get(0); if (!rootResource.isDirectory()) { Messages.showErrorDialog("No resource directory for the project where the current .java file is located", "Initialize Environment Error"); } // Initialize the core class return D8gerAutoCoding.build(currentProject, currentModule, rootResource, currentJavaFile); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/SupportFieldTypeEnum.java ================================================ package com.xyz.caofancpu.d8ger.core; import com.xyz.caofancpu.d8ger.util.CollectionUtil; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.function.Function; /** * Support field types for Model * * @author caofanCPU */ public enum SupportFieldTypeEnum { INTEGER("java.lang.Integer", "Integer", "int(11)"), BASIC_INT("int", "int", "int(11)"), LONG("java.lang.Long", "Long", "bigint(20)"), BASIC_LONG("long", "long", "bigint(20)"), STRING("java.lang.String", "String", "varchar(32)"), BOOLEAN("java.lang.Boolean", "Boolean", "tinyint(1)"), DATE("java.util.Date", "Date", "datetime"), LOCAL_DATE_TIME("java.time.LocalDateTime", "LocalDateTime", "datetime"), BIG_DECIMAL("java.math.BigDecimal", "BigDecimal", "double(8, 2)"), DOUBLE("java.lang.Double", "Double", "double(8, 2)"), FLOAT("java.lang.Float", "Float", "double(8, 2)"), SHORT("java.lang.Short", "Short", "int(4)"), BASIC_DOUBLE("double", "double", "double(8, 2)"), BASIC_FLOAT("float", "float", "double(8, 2)"), BASIC_SHORT("short", "short", "int(4)"), BASIC_BOOLEAN("boolean", "boolean", "tinyint(1)"), ENUM("java.lang.Enum", null, "int(4)"), NONE(null, null, null); private String originName; private String shortName; private String sqlName; SupportFieldTypeEnum(String originName, String shortName, String sqlName) { this.originName = originName; this.shortName = shortName; this.sqlName = sqlName; } public static SupportFieldTypeEnum positionByShortName(String shortName) { List noneNullEnumList = CollectionUtil.removeAndTransList(Arrays.asList(SupportFieldTypeEnum.values()), item -> item == SupportFieldTypeEnum.NONE || item == SupportFieldTypeEnum.ENUM, Function.identity() ); SupportFieldTypeEnum result = CollectionUtil.findFirst(noneNullEnumList, item -> item.getShortName().equals(shortName)); if (Objects.nonNull(result)) { return result; } return SupportFieldTypeEnum.NONE; } public String getOriginName() { return originName; } public String getShortName() { return shortName; } public SupportFieldTypeEnum setShortName(String shortName) { this.shortName = shortName; return this; } public String getSqlName() { return sqlName; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/core/TemplateKeyWordEnum.java ================================================ package com.xyz.caofancpu.d8ger.core; /** * Template keyword enum * * @author caofanCPU */ public enum TemplateKeyWordEnum { MO_NAME_KEY("@MoName@"), PACKAGE_NAME_KEY("@package@"), UNCAPITALLIZE_MO_NAME_KEY("@uncapitallizeMoName@"), AUTHOR_KEY("@d8Author@"), MO_FIELD_KEY("@field@"), SWAGGER_MO_FIELD_KEY("@swaggerField@"), SQL_MO_TABLE_KEY("@mo_table_name@"), MO_EXAMPLE_KEY("@ExampleDefinitionMethod@"), SQL_MO_COLUMN_KEY("@sql_column@"), XML_BASE_COLUMN_LIST_KEY("@BaseColumnList@"), XML_SELECT_BASE_COLUMN_LIST_KEY("@SelectBaseColumnList@"), XML_BATCH_UPDATE_NONNULL_FIELD_BY_ID_KEY("@BatchUpdateNonNullFieldByID@"), XML_UPDATE_NONNULL_FIELD_BY_ID_KEY("@UpdateNonNullFieldByID@"), XML_UPDATE_NONNULL_FIELD_BY_EXAMPLE_KEY("@UpdateNonNullFieldByExample@"), XML_INSERT_COLUMN_LIST_KEY("@InsertField@"), XML_BATCH_INSERT_COLUMN_LIST_KEY("@BatchInsertField@"), XML_INSERT_SELECTIVE_COLUMN_LIST_KEY("@NonNullColumnList@"), XML_INSERT_SELECTIVE_FIELD_LIST_KEY("@NonNullInsertField@"), XML_MO_LIST_QUERY_KEY("@MoListQuery@"), API_URL_PREFIX_KEY("@apiUrlPrefix@"), MO_PACKAGE_NAME_KEY("@moPackage@"), MAPPER_PACKAGE_NAME_KEY("@mapperPackage@"), MAPPER_ANNOTATION_KEY("@MapperAnnotation@"), MAPPER_ANNOTATION_PACKAGE_KEY("@MapperAnnotationPackage@"), MO_EXAMPLE_PACKAGE_NAME_KEY("@moExamplePackage@"), SWAGGER_MO_PACKAGE_NAME_KEY("@swaggerMoPackage@"), HANDLER_PACKAGE_NAME_KEY("@handlerPackage@"), CONTROLLER_PACKAGE_NAME_KEY("@controllerPackage@"), ; private String name; TemplateKeyWordEnum(String name) { this.name = name; } public String getName() { return name; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerApplicationState.java ================================================ package com.xyz.caofancpu.d8ger.setting; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.util.xmlb.XmlSerializerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * D8gerSetting State Service * * @author D8GER */ @State( name = "com.xyz.caofancpu.d8ger.setting.D8gerApplicationState", storages = {@Storage("D8gerAutoCodePluginGlobalSetting.xml")} ) public class D8gerApplicationState implements PersistentStateComponent { public String version = "1.0"; public static D8gerApplicationState getInstance() { return ServiceManager.getService(D8gerApplicationState.class); } public static String getOldVersion() { return getInstance().version; } public static void setPluginVersion(String version) { getInstance().setVersion(version); } public void setVersion(String version) { this.version = version; } @Nullable @Override public D8gerApplicationState getState() { return this; } @Override public void loadState(@NotNull D8gerApplicationState d8gerState) { XmlSerializerUtil.copyBean(d8gerState, this); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerProjectState.java ================================================ package com.xyz.caofancpu.d8ger.setting; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.project.Project; import com.intellij.util.xmlb.XmlSerializerUtil; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * D8gerSetting State Service * * @author D8GER */ @State( name = "com.xyz.caofancpu.d8ger.setting.D8gerProjectState", storages = {@Storage("D8gerAutoCodePluginProjectSetting.xml")} ) public class D8gerProjectState implements PersistentStateComponent { public boolean moCheck = true; public boolean mapperCheck = true; public boolean mapperExampleCheck = true; public boolean mapperXmlCheck = true; public boolean sqlCheck = true; public boolean voCheck = false; public boolean handlerCheck = false; public boolean controllerCheck = false; public boolean formatStyleCheck = true; public boolean detectSQLTimeColumnCheck = true; public boolean mapperBetterThenRepositoryCheck = true; public String moPath = ConstantUtil.EMPTY; public String mapperPath = ConstantUtil.EMPTY; public String mapperExamplePath = ConstantUtil.EMPTY; public String mapperXmlPath = ConstantUtil.EMPTY; public String sqlPath = ConstantUtil.EMPTY; public String voPath = ConstantUtil.EMPTY; public String handlerPath = ConstantUtil.EMPTY; public String controllerPath = ConstantUtil.EMPTY; public String defaultAuthor = ConstantUtil.DEFAULT_AUTHOR; public String defaultUrlPrefix = ConstantUtil.DEFAULT_API_URL_PREFIX; public String defaultLocale = ConstantUtil.OPTIONAL_CONFIG_LANGUAGE; public static D8gerProjectState getInstance(Project currentProject) { return ServiceManager.getService(currentProject, D8gerProjectState.class); } @Nullable @Override public D8gerProjectState getState() { return this; } @Override public void loadState(@NotNull D8gerProjectState d8GerProjectState) { XmlSerializerUtil.copyBean(d8GerProjectState, this); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSetting.form ================================================
================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSetting.java ================================================ package com.xyz.caofancpu.d8ger.setting; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.ui.TextBrowseFolderListener; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ui.JBUI; import com.xyz.caofancpu.d8ger.util.ConstantUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Objects; /** * Setting Form * * @author D8GER */ public class D8gerSetting { /** * Current project, this determines the root directory */ private Project currentProject; /** * File choose descriptor */ private FileChooserDescriptor cacheFolderDescriptor; /** * Root panel */ private JPanel rootPanel; /** * L1 */ private JCheckBox moCheck; /** * L2 */ private JCheckBox mapperCheck; /** * L3 */ private JCheckBox mapperExampleCheck; /** * L4 */ private JCheckBox mapperXmlCheck; /** * L5 */ private JCheckBox sqlCheck; /** * L6 */ private JCheckBox voCheck; /** * L7 */ private JCheckBox handlerCheck; /** * L8 */ private JCheckBox controllerCheck; /** * L9 */ private JCheckBox formatStyleCheck; /** * L10 */ private JCheckBox detectSQLTimeColumnCheck; /** * L11 */ private JCheckBox mapperBetterThenRepositoryCheck; /** * L12 */ private JLabel author; /** * L13 */ private JLabel apiUrlPrefix; /** * L14 */ private JLabel locale; /** * R1 */ private TextFieldWithBrowseButton moPath; /** * R2 */ private TextFieldWithBrowseButton mapperPath; /** * R3 */ private TextFieldWithBrowseButton mapperExamplePath; /** * R4 */ private TextFieldWithBrowseButton mapperXmlPath; /** * R5 */ private TextFieldWithBrowseButton sqlPath; /** * R6 */ private TextFieldWithBrowseButton voPath; /** * R7 */ private TextFieldWithBrowseButton handlerPath; /** * R8 */ private TextFieldWithBrowseButton controllerPath; /** * R12 */ private JTextField defaultAuthor; /** * R13 */ private JTextField defaultUrlPrefix; /** * R14 */ private JComboBox defaultLocale; /** * Donate link button */ private JButton donateButton; public D8gerSetting(Project project) { this.currentProject = project; initDonate(); initTbbListener(); } private void initTbbListener() { moPath.addBrowseFolderListener(getFolderChooseListener()); mapperPath.addBrowseFolderListener(getFolderChooseListener()); mapperExamplePath.addBrowseFolderListener(getFolderChooseListener()); mapperXmlPath.addBrowseFolderListener(getFolderChooseListener()); sqlPath.addBrowseFolderListener(getFolderChooseListener()); voPath.addBrowseFolderListener(getFolderChooseListener()); handlerPath.addBrowseFolderListener(getFolderChooseListener()); controllerPath.addBrowseFolderListener(getFolderChooseListener()); } private TextBrowseFolderListener getFolderChooseListener() { if (Objects.isNull(cacheFolderDescriptor)) { cacheFolderDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); cacheFolderDescriptor.setTitle(ConstantUtil.FILE_CHOOSE_TITLE); cacheFolderDescriptor.setDescription(ConstantUtil.FILE_CHOOSE_DESCRIPTION); cacheFolderDescriptor.setShowFileSystemRoots(false); cacheFolderDescriptor.withTreeRootVisible(true); cacheFolderDescriptor.setHideIgnored(true); VirtualFile projectDir = ProjectUtil.guessProjectDir(this.currentProject); if (Objects.nonNull(projectDir)) { cacheFolderDescriptor.setRoots(projectDir); cacheFolderDescriptor.setForcedToUseIdeaFileChooser(true); } } return new TextBrowseFolderListener(cacheFolderDescriptor); } private void initDonate() { donateButton.setBorder(null); donateButton.setMargin(JBUI.emptyInsets()); donateButton.setContentAreaFilled(false); donateButton.addActionListener(e -> BrowserUtil.browse(ConstantUtil.DONATE_CLICK_URL)); donateButton.putClientProperty(ConstantUtil.DONATE_BACKGROUND_KEY, rootPanel.getBackground()); } public JPanel getPanel() { return rootPanel; } public JComponent getPreferredFocusedComponent() { return defaultAuthor; } public boolean getMoCheck() { return moCheck.isSelected(); } public void setMoCheck(boolean newStatus) { moCheck.setSelected(newStatus); } public boolean getMapperCheck() { return mapperCheck.isSelected(); } public void setMapperCheck(boolean newStatus) { mapperCheck.setSelected(newStatus); } public boolean getMapperExampleCheck() { return mapperExampleCheck.isSelected(); } public void setMapperExampleCheck(boolean newStatus) { mapperExampleCheck.setSelected(newStatus); } public boolean getMapperXmlCheck() { return mapperXmlCheck.isSelected(); } public void setMapperXmlCheck(boolean newStatus) { mapperXmlCheck.setSelected(newStatus); } public boolean getSqlCheck() { return sqlCheck.isSelected(); } public void setSqlCheck(boolean newStatus) { sqlCheck.setSelected(newStatus); } public boolean getVoCheck() { return voCheck.isSelected(); } public void setVoCheck(boolean newStatus) { voCheck.setSelected(newStatus); } public boolean getHandlerCheck() { return handlerCheck.isSelected(); } public void setHandlerCheck(boolean newStatus) { handlerCheck.setSelected(newStatus); } public boolean getControllerCheck() { return controllerCheck.isSelected(); } public void setControllerCheck(boolean newStatus) { controllerCheck.setSelected(newStatus); } public boolean getFormatStyleCheck() { return formatStyleCheck.isSelected(); } public void setFormatStyleCheck(boolean newStatus) { formatStyleCheck.setSelected(newStatus); } public boolean getDetectSQLTimeColumnCheck() { return detectSQLTimeColumnCheck.isSelected(); } public void setDetectSQLTimeColumnCheck(boolean newStatus) { detectSQLTimeColumnCheck.setSelected(newStatus); } public boolean getMapperBetterThenRepositoryCheck() { return mapperBetterThenRepositoryCheck.isSelected(); } public void setMapperBetterThenRepositoryCheck(boolean newStatus) { mapperBetterThenRepositoryCheck.setSelected(newStatus); } @NotNull public String getMoPath() { return moPath.getText(); } public void setMoPath(@NotNull String newText) { moPath.setText(newText); } @NotNull public String getMapperPath() { return mapperPath.getText(); } public void setMapperPath(@NotNull String newText) { mapperPath.setText(newText); } @NotNull public String getMapperExamplePath() { return mapperExamplePath.getText(); } public void setMapperExamplePath(@NotNull String newText) { mapperExamplePath.setText(newText); } @NotNull public String getMapperXmlPath() { return mapperXmlPath.getText(); } public void setMapperXmlPath(@NotNull String newText) { mapperXmlPath.setText(newText); } @NotNull public String getSqlPath() { return sqlPath.getText(); } public void setSqlPath(@NotNull String newText) { sqlPath.setText(newText); } @NotNull public String getVoPath() { return voPath.getText(); } public void setVoPath(@NotNull String newText) { voPath.setText(newText); } @NotNull public String getHandlerPath() { return handlerPath.getText(); } public void setHandlerPath(@NotNull String newText) { handlerPath.setText(newText); } @NotNull public String getControllerPath() { return controllerPath.getText(); } public void setControllerPath(@NotNull String newText) { controllerPath.setText(newText); } @NotNull public String getDefaultAuthor() { return defaultAuthor.getText(); } public void setDefaultAuthor(@NotNull String newText) { defaultAuthor.setText(newText); } @NotNull public String getDefaultUrlPrefix() { return defaultUrlPrefix.getText(); } public void setDefaultUrlPrefix(@NotNull String newText) { defaultUrlPrefix.setText(newText); } @NotNull public String getDefaultLocale() { return defaultLocale.getModel().getSelectedItem().toString(); } public void setDefaultLocale(@NotNull String newText) { defaultLocale.getModel().setSelectedItem(newText); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/setting/D8gerSettingsConfigurable.java ================================================ package com.xyz.caofancpu.d8ger.setting; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Objects; /** * D8ger Setting Configurable * * @author D8GER */ public class D8gerSettingsConfigurable implements Configurable { private static final Logger LOG = Logger.getInstance(D8gerSettingsConfigurable.class); private Project currentProject; /** * User custom config result */ private D8gerSetting d8gerSetting; /** * Must have this construct, and should only inject Project param * * @param currentProject */ public D8gerSettingsConfigurable(Project currentProject) { this.currentProject = currentProject; } // A default constructor with no arguments is required because this implementation // is registered as an applicationConfigurable EP @Nls(capitalization = Nls.Capitalization.Title) @Override public String getDisplayName() { return "D8gerAutoCode"; } @Override public JComponent getPreferredFocusedComponent() { return d8gerSetting.getPreferredFocusedComponent(); } @Nullable @Override public JComponent createComponent() { LOG.info("prepare D8gerAutoCode setting..."); d8gerSetting = new D8gerSetting(this.currentProject); return d8gerSetting.getPanel(); } @Override public boolean isModified() { D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject); return !Objects.equals(d8gerSetting.getMoPath(), settings.moPath) || !Objects.equals(d8gerSetting.getMapperPath(), settings.mapperPath) || !Objects.equals(d8gerSetting.getMapperExamplePath(), settings.mapperExamplePath) || !Objects.equals(d8gerSetting.getMapperXmlPath(), settings.mapperXmlPath) || !Objects.equals(d8gerSetting.getSqlPath(), settings.sqlPath) || !Objects.equals(d8gerSetting.getVoPath(), settings.voPath) || !Objects.equals(d8gerSetting.getHandlerPath(), settings.handlerPath) || !Objects.equals(d8gerSetting.getControllerPath(), settings.controllerPath) || !Objects.equals(d8gerSetting.getDefaultAuthor(), settings.defaultAuthor) || !Objects.equals(d8gerSetting.getDefaultUrlPrefix(), settings.defaultUrlPrefix) || !Objects.equals(d8gerSetting.getDefaultLocale(), settings.defaultLocale) || !Objects.equals(d8gerSetting.getMoCheck(), settings.moCheck) || !Objects.equals(d8gerSetting.getMapperCheck(), settings.mapperCheck) || !Objects.equals(d8gerSetting.getMapperExampleCheck(), settings.mapperExampleCheck) || !Objects.equals(d8gerSetting.getMapperXmlCheck(), settings.mapperXmlCheck) || !Objects.equals(d8gerSetting.getSqlCheck(), settings.sqlCheck) || !Objects.equals(d8gerSetting.getVoCheck(), settings.voCheck) || !Objects.equals(d8gerSetting.getHandlerCheck(), settings.handlerCheck) || !Objects.equals(d8gerSetting.getControllerCheck(), settings.controllerCheck) || !Objects.equals(d8gerSetting.getFormatStyleCheck(), settings.formatStyleCheck) || !Objects.equals(d8gerSetting.getDetectSQLTimeColumnCheck(), settings.detectSQLTimeColumnCheck) || !Objects.equals(d8gerSetting.getMapperBetterThenRepositoryCheck(), settings.mapperBetterThenRepositoryCheck) ; } @Override public void apply() { D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject); settings.moCheck = d8gerSetting.getMoCheck(); settings.mapperCheck = d8gerSetting.getMapperCheck(); settings.mapperExampleCheck = d8gerSetting.getMapperExampleCheck(); settings.mapperXmlCheck = d8gerSetting.getMapperXmlCheck(); settings.sqlCheck = d8gerSetting.getSqlCheck(); settings.voCheck = d8gerSetting.getVoCheck(); settings.handlerCheck = d8gerSetting.getHandlerCheck(); settings.controllerCheck = d8gerSetting.getControllerCheck(); settings.formatStyleCheck = d8gerSetting.getFormatStyleCheck(); settings.detectSQLTimeColumnCheck = d8gerSetting.getDetectSQLTimeColumnCheck(); settings.mapperBetterThenRepositoryCheck = d8gerSetting.getMapperBetterThenRepositoryCheck(); settings.moPath = d8gerSetting.getMoPath(); settings.mapperPath = d8gerSetting.getMapperPath(); settings.mapperExamplePath = d8gerSetting.getMapperExamplePath(); settings.mapperXmlPath = d8gerSetting.getMapperXmlPath(); settings.sqlPath = d8gerSetting.getSqlPath(); settings.voPath = d8gerSetting.getVoPath(); settings.handlerPath = d8gerSetting.getHandlerPath(); settings.controllerPath = d8gerSetting.getControllerPath(); settings.defaultAuthor = d8gerSetting.getDefaultAuthor(); settings.defaultUrlPrefix = d8gerSetting.getDefaultUrlPrefix(); settings.defaultLocale = d8gerSetting.getDefaultLocale(); } @Override public void reset() { D8gerProjectState settings = D8gerProjectState.getInstance(this.currentProject); d8gerSetting.setMoCheck(settings.moCheck); d8gerSetting.setMapperCheck(settings.mapperCheck); d8gerSetting.setMapperExampleCheck(settings.mapperExampleCheck); d8gerSetting.setMapperXmlCheck(settings.mapperXmlCheck); d8gerSetting.setSqlCheck(settings.sqlCheck); d8gerSetting.setVoCheck(settings.voCheck); d8gerSetting.setHandlerCheck(settings.handlerCheck); d8gerSetting.setControllerCheck(settings.controllerCheck); d8gerSetting.setFormatStyleCheck(settings.formatStyleCheck); d8gerSetting.setDetectSQLTimeColumnCheck(settings.detectSQLTimeColumnCheck); d8gerSetting.setMapperBetterThenRepositoryCheck(settings.mapperBetterThenRepositoryCheck); d8gerSetting.setMoPath(settings.moPath); d8gerSetting.setMapperPath(settings.mapperPath); d8gerSetting.setMapperExamplePath(settings.mapperExamplePath); d8gerSetting.setMapperXmlPath(settings.mapperXmlPath); d8gerSetting.setSqlPath(settings.sqlPath); d8gerSetting.setVoPath(settings.voPath); d8gerSetting.setHandlerPath(settings.handlerPath); d8gerSetting.setControllerPath(settings.controllerPath); d8gerSetting.setDefaultAuthor(settings.defaultAuthor); d8gerSetting.setDefaultUrlPrefix(settings.defaultUrlPrefix); d8gerSetting.setDefaultLocale(settings.defaultLocale); } @Override public void disposeUIResources() { LOG.info("finish D8gerAutoCode setting"); d8gerSetting = null; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/CollectionUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import com.google.common.collect.Lists; import lombok.NonNull; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.StreamSupport; /** * Collection tools: https://dzone.com/articles/functional-programming-patterns-with-java-8 */ public class CollectionUtil extends CollectionUtils { /** * Find the union of two sets of the same element type, like (a ∪ b), * the container type of the result can be specified * * @param resultColl * @param a * @param b * @param * @param * @return */ @SuppressWarnings("unchecked") public static > C union(Supplier resultColl, Collection a, Collection b) { C result = resultColl.get(); union(a, b).forEach(item -> result.add((E) item)); return result; } /** * Find the intersection of two sets of the same element type, like (a ∩ b), * the container type of the result can be specified * * @param resultColl * @param a * @param b * @param * @param * @return */ @SuppressWarnings("unchecked") public static > C intersection(Supplier resultColl, Collection a, Collection b) { C result = resultColl.get(); intersection(a, b).forEach(item -> result.add((E) item)); return result; } /** * Find the complement of the intersection of two sets of the same element type, like ((a ∪ b) - (a ∩ b)), * the container type of the result can be specified * * @param resultColl * @param a * @param b * @param * @param * @return */ @SuppressWarnings("unchecked") public static > C disjunction(Supplier resultColl, Collection a, Collection b) { C result = resultColl.get(); disjunction(a, b).forEach(item -> result.add((E) item)); return result; } /** * Find the difference between two sets of the same element type, like (a - ( a ∩ b)), * the container type of the result can be specified * * @param resultColl * @param a * @param b * @param * @param * @return */ @SuppressWarnings("unchecked") public static > C subtract(Supplier resultColl, Collection a, Collection b) { C result = resultColl.get(); subtract(a, b).forEach(item -> result.add((E) item)); return result; } /** * Sum the specified elements of a list element (fields are numeric) * * @param coll * @param numberValueFunction * @param * @param * @return */ public static BigDecimal sum(Collection coll, Function numberValueFunction) { double sum = coll.stream() .filter(Objects::nonNull) .map(numberValueFunction) .mapToDouble(Number::doubleValue) .sum(); return BigDecimal.valueOf(sum); } /** * Average the specified elements of a list element (fields are numeric) * * @param coll * @param numberValueFunction * @param * @param * @return */ public static BigDecimal average(Collection coll, Function numberValueFunction) { Double average = coll.stream() .filter(Objects::nonNull) .map(numberValueFunction) .collect(Collectors.averagingDouble(Number::doubleValue)); return BigDecimal.valueOf(average); } /** * Max the specified elements of a list element (fields are numeric) * * @param coll * @param numberValueFunction * @param * @param * @return */ public static BigDecimal max(Collection coll, Function numberValueFunction) { double max = coll.stream() .filter(Objects::nonNull) .map(numberValueFunction) .mapToDouble(Number::doubleValue) .max() .orElse(0d); return BigDecimal.valueOf(max); } /** * Min the specified elements of a list element (fields are numeric) * * @param coll * @param numberValueFunction * @param * @param * @return */ public static BigDecimal min(Collection coll, Function numberValueFunction) { double min = coll.stream() .filter(Objects::nonNull) .map(numberValueFunction) .mapToDouble(Number::doubleValue) .min() .orElse(0d); return BigDecimal.valueOf(min); } /** * Detect duplicates for the specified field of the collection element, * return non-empty duplicate elements * * @param coll * @param mapper * @param * @param * @return */ public static Set probeRepeatValueSet(Collection coll, Function mapper) { List elementList = transToList(coll, mapper); List withoutNullElementList = transToList(elementList, Function.identity()); Set noRepeatElementSet = new HashSet<>(withoutNullElementList); return subtract(HashSet::new, withoutNullElementList, noRepeatElementSet); } /** * Converts a [number] string that is concatenated according to the separator into a list of the specified [number] * * @param source * @param splitSymbol * @param mapper * @param * @return */ public static List splitDelimitedStringToList(@NonNull String source, @NonNull String splitSymbol, Function mapper) { return transToList(Arrays.asList(source.split(splitSymbol)), mapper); } /** * Judge empty or not for Map * * @param sourceMap data source * @return boolean judge result */ public static boolean isEmpty(Map sourceMap) { return Objects.isNull(sourceMap) || sourceMap.isEmpty(); } public static boolean isNotEmpty(Map sourceMap) { return !isEmpty(sourceMap); } /** * Convert to Set, HashSet is used by default * * @param source data source * @param mapper field execution function * @return HashSet */ public static Set transToSet(Collection source, Function mapper) { return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toSet()); } /** * Convert to List, ArrayList is used by default * * @param source data source * @param mapper field execution function * @return ArrayList */ public static List transToList(Collection source, Function mapper) { return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList()); } /** * Convert to the specified collection, commonly used Set/List,HashSet/ArrayList,LinkedSet/LinkedList * * @param resultColl Specify a collection container * @param source data source * @param mapper field execution function * @return C */ public static > C transToCollection(Supplier resultColl, Collection source, Function mapper) { return source.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toCollection(resultColl)); } /** * Two layers of Nested Collection are collapsed and tiled into a List, and ArrayList is used by default * Multi-level nesting can be completed by repeatedly calling this method * * @param source Two levels of nested List data sources * @param mapper Outer element gets execution function of inner collection * @return List collected after tiling */ public static List transToListWithFlatMap(Collection source, Function> mapper) { return source.stream().filter(Objects::nonNull).map(mapper).flatMap(List::stream).collect(Collectors.toList()); } /** * Two layers of Nested Collection are collapsed and tiled into a List, and HashSet is used by default * Multi-level nesting can be completed by repeatedly calling this method * * @param source Two levels of nested Set data sources * @param mapper Outer element gets execution function of inner collection * @return Set collected after tiling */ public static Set transToSetWithFlatMap(Collection source, Function> mapper) { return source.stream().filter(Objects::nonNull).map(mapper).flatMap(List::stream).collect(Collectors.toSet()); } /** * Perform filtering based on element fields meeting certain conditions, and convert to Set * * @param coll data source * @param predicate filter conditions * @param mapper functions that compute the filtered out elements * @return HashSet */ public static Set filterAndTransSet(Collection coll, Predicate predicate, Function mapper) { return coll.stream().filter(Objects::nonNull).filter(predicate).map(mapper).collect(Collectors.toSet()); } /** * Remove the element fields that meet the condition removePredicate and convert to Set. * This method is opposite with {@link #filterAndTransSet}, so their results are complementary * * @param coll data source * @param removePredicate filter conditions * @param mapper functions that compute the filtered out elements * @return HashSet */ public static Set removeAndTransSet(Collection coll, Predicate removePredicate, Function mapper) { return coll.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toSet()); } /** * Perform filtering based on element fields meeting certain conditions, and convert to List. * * @param coll data source * @param predicate filter conditions * @param mapper functions that compute the filtered out elements * @return ArrayList */ public static List filterAndTransList(Collection coll, Predicate predicate, Function mapper) { return coll.stream().filter(Objects::nonNull).filter(predicate).map(mapper).collect(Collectors.toList()); } /** * Perform filtering based on the element field meeting certain conditions, and convert to List. * This method is opposite with {@link #filterAndTransList}, so their results are complementary * * @param coll data source * @param removePredicate filter conditions * @param mapper functions that compute the filtered out elements * @return ArrayList */ public static List removeAndTransList(Collection coll, Predicate removePredicate, Function mapper) { return coll.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toList()); } /** * Perform filtering based on the element field meeting certain conditions, * and convert to the specified collection * * @param resultColl results collection container * @param sourceColl data source * @param survivePredicate retention conditions * @param mapper functions that compute the filtered out elements * @return R */ public static > R filterAndTransColl(Supplier resultColl, Collection sourceColl, Predicate survivePredicate, Function mapper) { return sourceColl.stream().filter(Objects::nonNull).filter(survivePredicate).map(mapper).collect(Collectors.toCollection(resultColl)); } /** * Remove the element fields that meet the condition removePredicate and convert to List. * This method is opposite with {@link #filterAndTransColl}, so their results are complementary * * @param resultColl results collection container * @param sourceColl data source * @param removePredicate elimination conditions * @param mapper functions that compute the filtered out elements * @return R */ public static > R removeAndTransColl(Supplier resultColl, Collection sourceColl, Predicate removePredicate, Function mapper) { return sourceColl.stream().filter(Objects::nonNull).filter(item -> !removePredicate.test(item)).map(mapper).collect(Collectors.toCollection(resultColl)); } /** * Get a set of fields of an element, and remove duplicates * * @param source data source * @param mapper field execution function * @return */ public static List distinctList(Collection source, Function mapper) { return source.stream().filter(Objects::nonNull).map(mapper).distinct().collect(Collectors.toList()); } /** * Deduplication according to the specified field in the collection element, * return the deduplicated element collection * * @param coll data source * @param distinctComparator Element field comparator (may be a joint comparator for multiple fields) * @return Deduplicated original element collection */ public static List distinctListByField(Collection coll, Comparator distinctComparator) { if (isEmpty(coll)) { return Collections.emptyList(); } return coll.stream() .filter(Objects::nonNull) .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(distinctComparator)), ArrayList::new)); } /** * In order to avoid data loss, the bottom layer of the Steam API makes more rigid requirements for Collectors.toMap * 1.methods named 'toMap' are not allow duplicate keys first, * so you need to pay attention to using the KEY field when grouping * 2.not allow null VALUE either * * Therefore, please pay attention to the above two when using the following named '*ToMap' method, * and named '*ToMapEnhance' method allows the key to be duplicated and enables the new value to replace the old value * */ /** * Group conversion to Map>, support key function, value function, HashMap> is used by default * * @param source * @param kFunction * @return */ public static Map> groupIndexToMap(Collection source, Function kFunction) { return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction)); } /** * Group conversion to Map>, support key function, value function, HashMap> is used by default * * @param source * @param kFunction * @param vFunction * @param * @param * @param * @return */ public static Map> groupIndexToMap(Collection source, Function kFunction, Function vFunction) { return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, HashMap::new, Collectors.mapping(vFunction, Collectors.toList()))); } /** * Group conversion to specified Map>, such as TreeMap> | LinkedHashMap> * * @param mapColl * @param source * @param kFunction * @return */ public static >> M groupIndexToMap(Supplier mapColl, Collection source, Function kFunction) { return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, mapColl, Collectors.toList())); } /** * Group conversion to specified Map>, such as TreeMap> | LinkedHashMap> * * @param mapColl * @param vColl * @param source * @param kFunction */ public static , C extends Collection> M groupIndexToMap(Supplier mapColl, Supplier vColl, Collection source, Function kFunction) { return source.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(kFunction, mapColl, Collectors.toCollection(vColl))); } /** * Group conversion to specified Map>, such as TreeMap> | LinkedHashMap>, * and can calculate (convert) the original array elements into other objects * * @param mapColl * @param vColl * @param source * @param kGroupFunction * @param vFunction * @return */ public static , C extends Collection> M groupIndexToMap(Supplier mapColl, Supplier vColl, Collection source, Function kGroupFunction, Function vFunction) { return source.stream().filter(Objects::nonNull).collect( Collectors.groupingBy(kGroupFunction, mapColl, Collectors.mapping(vFunction, Collectors.toCollection(vColl)))); } /** * Convert to Map * * @param values * @param kFunction * @return */ public static Map transToMap(@NonNull Iterable values, Function kFunction) { return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, Function.identity())); } /** * Convert to Map-Value, any duplicate key will throw exception * * @param mapColl * @param values * @param kFunction * @return */ public static > M transToMap(Supplier mapColl, @NonNull Iterable values, Function kFunction) { return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, Function.identity(), nonDuplicateKey(), mapColl)); } /** * Convert to Map, allow duplicate key * * @param mapColl * @param values * @param kFunction * @return */ public static > M transToMapEnhance(Supplier mapColl, @NonNull Iterable values, Function kFunction) { return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, Function.identity(), enableNewOnDuplicateKey(), mapColl)); } /** * Convert to Map * * @param values * @param kFunction * @param vFunction * @return */ public static Map transToMap(@NonNull Iterable values, Function kFunction, Function vFunction) { return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, vFunction)); } /** * Convert to Map, any duplicate key will throw exception * * @param mapColl * @param values * @param kFunction * @param vFunction * @return */ public static > M transToMap(Supplier mapColl, @NonNull Iterable values, Function kFunction, Function vFunction) { return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, vFunction, nonDuplicateKey(), mapColl)); } /** * Convert two nested Lists into Map>, and superimpose List according to K * * @param mapColl * @param values * @param kFunction * @param vFunction * @return */ public static >> M transToMapByMerge(Supplier mapColl, Iterable values, Function kFunction, Function> vFunction) { if (Objects.isNull(values)) { return mapColl.get(); } return StreamSupport.stream(values.spliterator(), Boolean.FALSE) .filter(Objects::nonNull) .collect(Collectors.toMap(kFunction, vFunction, (list1, list2) -> { list1.addAll(list2); return list1; }, mapColl)); } /** * Splicing array elements into strings according to the specified delimiter * * @param arr * @param separator * @return */ public static String join(Object[] arr, String separator) { if (ArrayUtils.isEmpty(arr)) { return StringUtils.EMPTY; } return join(Arrays.asList(arr), separator); } /** * Splicing array elements into strings according to the specified delimiter * * @param coll * @param separator * @return */ public static String join(Collection coll, String separator) { if (CollectionUtil.isEmpty(coll)) { return StringUtils.EMPTY; } if (Objects.isNull(separator)) { separator = StringUtils.EMPTY; } return coll.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(separator)); } /** * Sorting Map * * @param sourceMap * @param comparator * @param * @param * @return */ public static > LinkedHashMap sortedMapByValue(Map sourceMap, Comparator> comparator) { if (isEmpty(sourceMap)) { return new LinkedHashMap<>(2, 0.5F, Boolean.FALSE); } List> entryList = sourceMap.entrySet().stream().sorted(comparator).collect(Collectors.toList()); return transToMap(LinkedHashMap::new, entryList, Entry::getKey, Entry::getValue); } /** * Find elements in the List according to the specified field function, * if any one is found, it will be returned, or null if it is not found. * * @param coll * @param function * @param value * @return */ public static T findAny(Collection coll, Function function, @NonNull F value) { return coll.stream().filter(item -> value.equals(function.apply(item))).findAny().orElse(null); } /** * Find a value in a array, normally used in Enum class * * @param source * @param function * @param value * @param * @param * @return */ public static T findAnyInArrays(T[] source, Function function, @NonNull F value) { return findAny(Arrays.asList(source), function, value); } /** * Find elements in a list according to a custom field function, * return the first element found or null if not found * * @param coll * @param function * @param value * @return */ public static T findFirst(Collection coll, Function function, @NonNull F value) { return coll.stream().filter(item -> value.equals(function.apply(item))).findFirst().orElse(null); } /** * Finds elements according to specified conditions, * return the first element found or null if not found * * @param coll * @param predicate * @return */ public static T findFirst(Collection coll, Predicate predicate) { return coll.stream().filter(predicate).findFirst().orElse(null); } /** * Find all elements from the list based on unique field values * * @param coll * @param function * @param value * @return */ public static List findAll(Collection coll, Function function, @NonNull F value) { if (isEmpty(coll)) { return Lists.newArrayList(); } return coll.stream() .filter(Objects::nonNull) .filter(item -> value.equals(function.apply(item))) .collect(Collectors.toList()); } /** * Determine and find all elements existed in the list * * @param coll * @param predicate * @return */ public static List findAll(Collection coll, Predicate predicate) { return coll.stream().filter(predicate).collect(Collectors.toList()); } /** * Determine if an element has at least one value in the list, * and return immediately if it exists * * @param coll * @param function * @param value * @return */ public static boolean existAtLeastOne(Collection coll, Function function, @NonNull F value) { return coll.stream().anyMatch(item -> value.equals(function.apply(item))); } /** * Determine if an element exists in the list * * @param coll * @param function * @param value * @return */ public static boolean exist(Collection coll, Function function, @NonNull F value) { return coll.stream().allMatch(item -> value.equals(function.apply(item))); } /** * Determine if an element exists in the list * * @param coll * @param predicate * @return */ public static boolean exist(Collection coll, Predicate predicate) { T existFirstOne = coll.stream().filter(predicate).findFirst().orElse(null); return Objects.nonNull(existFirstOne); } /** * Map key-value pair inversion, * for example, * { examA : [stu1, stu2, stu3], examB: [stu1, stu2] } * ⬇ * {stu1 : [examA, examB], stu2 : [examA, examB], stu3 : [examA]} * * @param sourceMap * @param kFunction * @param vFunction * @return */ public static Map> reverseKV(@NonNull Map> sourceMap, Function kFunction, Function vFunction) { Map> aux = new HashMap<>(); sourceMap.entrySet().stream() .filter(Objects::nonNull) .forEach(entry -> entry.getValue().stream() .filter(Objects::nonNull) .forEach(v -> aux.computeIfAbsent(vFunction.apply(v), init -> new ArrayList<>()).add(kFunction.apply(entry.getKey()))) ); return aux; } /** * Map key-value pair inversion, support return a custom collection container, * for example, return LinkedHashMap *

* Map> ==> Map> * kFunction.apply(k1) ==> v2 * vFunction.apply(v1) ==> k2 * * @param mapColl * @param vColl * @param sourceMap * @param kFunction * @param vFunction * @return */ public static , C2 extends Collection, M1 extends Map, M2 extends Map> M2 reverseKV(Supplier mapColl, Supplier vColl, @NonNull M1 sourceMap, Function kFunction, Function vFunction) { M2 aux = mapColl.get(); sourceMap.entrySet().stream() .filter(Objects::nonNull) .forEach(entry -> entry.getValue().stream() .filter(Objects::nonNull) .forEach(v -> aux.computeIfAbsent(vFunction.apply(v), init -> vColl.get()).add(kFunction.apply(entry.getKey()))) ); return aux; } /** * For complex maps, find the set of key-value pairs for the key matching function * Returns null if the matching function conditions are not met * * @param srcMap * @param kFunction * @param value * @return */ public static List> findInMap(Map srcMap, Function kFunction, @NonNull T value) { if (isEmpty(srcMap)) { return null; } return srcMap.entrySet().stream() .filter(Objects::nonNull) .map(entry -> { if (value.equals(kFunction.apply(entry.getKey()))) { return entry; } return null; }) .filter(Objects::nonNull) .collect(Collectors.toList()); } /** * For complex Maps, find the key-value pairs of the key matching function, and only take one * Returns null if the matching function conditions are not met * * @param srcMap * @param kFunction * @param value * @return */ public static Entry findOneInMap(Map srcMap, Function kFunction, @NonNull T value) { if (isEmpty(srcMap)) { return null; } return srcMap.entrySet().stream() .filter(Objects::nonNull) .filter(entry -> value.equals(kFunction.apply(entry.getKey()))) .findAny() .get(); } /** * For complex Maps, find the key-value pairs of the key matching function, and only take one * Returns null if the matching function conditions are not met * * @param srcMap * @param kFunction * @param value * @return */ public static V findOneValue(Map srcMap, Function kFunction, @NonNull T value) { Entry resultEntry = findOneInMap(srcMap, kFunction, value); return Objects.isNull(resultEntry) ? null : resultEntry.getValue(); } /** * Returns a merge function, suitable for use in * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or * throws {@code IllegalStateException}. This can be used to enforce the * assumption that the elements being collected are distinct. * * @param the type of input arguments to the merge function * @return a merge function which always throw {@code IllegalStateException} */ private static BinaryOperator nonDuplicateKey() { return (u, v) -> { throw new IllegalStateException(String.format("Duplicate keys are not allowed when converting Map: [%s]", u)); }; } private static BinaryOperator enableNewOnDuplicateKey() { return (oldValue, newValue) -> newValue; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/ConstantUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import java.util.Collections; /** * Common symbols * * @author caofanCPU */ public class ConstantUtil { /** * Enum name suffix */ public static final String ENUM_SUFFIX = "Enum"; /** * Comma */ public static final String ENGLISH_COMMA = ","; /** * Chinese Comma */ public static final String CHINESE_COMMA = ","; /** * English colon */ public static final String ENGLISH_COLON = ":"; /** * English double quotes */ public static final String ENGLISH_DOUBLE_QUOTES = "\""; /** * Escapes */ public static final String ESCAPES = "\\"; /** * Double Escapes, normally used in regex */ public static final String DOUBLE_ESCAPES = "\\\\"; /** * Period */ public static final String ENGLISH_FULL_STOP = "."; /** * Fill in the blank placeholder: two dashes */ public static final String FILL_EMPTY_PLACE_HOLDER = "--"; /** * Joiner: single dash */ public static final String JOINER = "-"; /** * Underline */ public static final String UNDERLINE = "_"; /** * Empty string */ public static final String EMPTY = StringUtils.EMPTY; /** * Single space character */ public static final String SPACE = StringUtils.SPACE; /** * Tab: Two spaces */ public static final String MINI_TAB = CollectionUtil.join(Collections.nCopies(2, SPACE), EMPTY); /** * Tab: Four spaces */ public static final String TAB = CollectionUtil.join(Collections.nCopies(2, MINI_TAB), EMPTY); /** * Origin Tab character */ public static final String ORIGIN_TAB = "\t"; /** * Double Tabs */ public static final String DOUBLE_TAB = TAB + TAB; /** * Triple Tabs */ public static final String TRIPLE_TAB = DOUBLE_TAB + TAB; /** * Quaternary Tabs */ public static final String QUATERNARY_TAB = TRIPLE_TAB + TAB; /** * Penta Tabs */ public static final String PENTA_TAB = QUATERNARY_TAB + TAB; /** * Windows OS linebreak character */ public static final String WINDOWS_NEXT_LINE = "\r\n"; /** * Newline character */ public static final String NEXT_LINE = "\n"; /** * Double newlines */ public static final String DOUBLE_NEXT_LINE = NEXT_LINE + NEXT_LINE; /** * Semicolon */ public static final String ENGLISH_SEMICOLON = ";"; /** * Java file extension */ public static final String JAVA_FILE_SUFFIX = ".java"; /** * xml file extension */ public static final String XML_FILE_SUFFIX = ".xml"; /** * sql file extension */ public static final String SQL_FILE_SUFFIX = ".sql"; /** * SQL ID column */ public static final String SQL_ID = "id"; /** * SQL create time column */ public static final String SQL_CREATE_TIME = "createTime"; /** * ZN SQL create time */ public static final String ZN_SQL_CREATE_TIME = "创建时间"; /** * SQL update time column */ public static final String SQL_UPDATE_TIME = "updateTime"; /** * ZN SQL update time */ public static final String ZN_SQL_UPDATE_TIME = "更新时间"; /** * Mo name suffix */ public static final String MO_SUFFIX = "Mo"; /** * SwaggerMo name suffix */ public static final String SWAGGER_MO_SUFFIX = "Vo"; /** * MoMapper name suffix */ public static final String MO_MAPPER_NAME_SUFFIX = "Mapper"; /** * MoExample name suffix */ public static final String MO_EXAMPLE_NAME_SUFFIX = "Example"; /** * MoHandler name suffix */ public static final String MO_HANDLER_SUFFIX = "Handler"; /** * MoController name suffix */ public static final String MO_CONTROLLER_NAME_SUFFIX = "Controller"; /** * Auto code file directory name */ public static final String GENERATE_DIR = "D8AutoCode"; /** * Field access Default modifier */ public static final String DEFAULT_ACCESS_MODIFIER = "private"; /** * Notification group view ID */ public static final String NOTIFICATION_GROUP_VIEW_ID = "xtools"; /** * Config file name */ public static final String D8GER_CONFIG_FILE_NAME = "d8ger.properties"; /** * Author config key */ public static final String CONFIG_AUTHOR_KEY = "author"; /** * Default author name */ public static final String DEFAULT_AUTHOR = "D8ger"; /** * Interface url prefix config key */ public static final String CONFIG_API_URL_PREFIX_KEY = "apiUrlPrefix"; /** * Default interface url prefix */ public static final String DEFAULT_API_URL_PREFIX = "/d8gerAutoCoding"; /** * Language config key */ public static final String CONFIG_LANGUAGE_KEY = "locale"; /** * Default config language, EN(English) */ public static final String DEFAULT_CONFIG_LANGUAGE = "EN"; /** * Optional config language, ZN(Chinese Simplified) */ public static final String OPTIONAL_CONFIG_LANGUAGE = "ZN"; /** * Pagination number field name */ public static final String PAGE_NUM_NAME = "pageNum"; /** * Pagination size field name */ public static final String PAGE_SIZE_NAME = "pageSize"; /** * Spring MVC mapper with annotation @Repository */ public static final Pair MVC_MAPPER = Pair.of("org.springframework.stereotype.Repository", "@Repository"); /** * SpringBoot mapper with annotation @Mapper */ public static final Pair BOOT_MAPPER = Pair.of("org.apache.ibatis.annotations.Mapper", "@Mapper"); public static final String FILE_CHOOSE_TITLE = "Please Select a Generate Directory"; public static final String FILE_CHOOSE_DESCRIPTION = "The file will be generated by D8gerAutoCode here"; public static final String DONATE_BACKGROUND_KEY = "JButton.backgroundColor"; public static final String DONATE_CLICK_URL = "http://www.debuggerpowerzcy.top/home/2020/09/05/D8gerAutoCode%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/"; public static final String PLUGIN_ID = "com.xyz.caofancpu.D8gerAutoCode"; public static final String RENDER_TITLE = "D8ger•帝八哥"; /** * Greater */ public static final String GREATER = ">"; /** * Less then */ public static final String LESS_THEN = "<"; /** * English mid left bracket */ public static final String ENGLISH_MID_LEFT_BRACKET = "["; /** * English mid right bracket */ public static final String ENGLISH_MID_RIGHT_BRACKET = "]"; } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/DateUtil.java ================================================ /* * Copyright 2016-2020 the original author * * @D8GER(https://github.com/caofanCPU). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.xyz.caofancpu.d8ger.util; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Objects; import java.util.regex.Pattern; /** * LocalDateTime-Data converter and handler * * @author D8GER */ @Slf4j public class DateUtil { public static final Pattern DATE_TIME_REGEX = Pattern.compile("(?:[Tt])+"); public final static String DATETIME_FORMAT_SIMPLE = "yyyy-MM-dd HH:mm:ss"; public final static String DATETIME_FORMAT_DETAIL = "yyyy-MM-dd HH:mm:ss:SSS"; public final static String DATETIME_FORMAT_DETAIL_DOT = "yyyy-MM-dd HH:mm:ss.SSS"; public final static String DATETIME_FORMAT_CN = "yyyy年MM月dd日HH时mm分ss秒"; public final static ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of("+8"); /** * Long to LocalDateTime */ public static LocalDateTime toLocalDateTime(@NonNull Long milliSeconds) { return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliSeconds), DEFAULT_ZONE_OFFSET); } /** * String of date and time, for example, 2020-09-14 15:45:57 convert to Long: milliseconds * * @param dateTimeStr * @return */ public static Long parseStandardMilliSeconds(String dateTimeStr) { return parseStandardDateTime(dateTimeStr).toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli(); } /** * String of date and time, for example, 2020-09-14 15:45:57 convert to LocalDateTime * * @param dateTimeStr * @return */ public static LocalDateTime parseStandardDateTime(String dateTimeStr) { return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(DATETIME_FORMAT_SIMPLE)); } /** * Long to LocalDateTimeString */ public static String enhanceToLocalDateTime(@NonNull Long milliSeconds) { LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(milliSeconds), DEFAULT_ZONE_OFFSET); return localDateTime.format(DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL_DOT)); } /** * String of date and time, convert to String: milliseconds * for example: * 2020-09-14 15:45:57 * 2020-09-14T15:45:57 * 2020-09-14t15:45:57 * 2020-09-14 15:45:57.007 * 2020-09-14 15:45:57:007 * 2020年09月14日15时45分57秒 * * @param dateTimeStr * @return */ public static String enhanceParseMilliSeconds(String dateTimeStr) { if (StringUtils.isBlank(dateTimeStr)) { return dateTimeStr; } String originWord = dateTimeStr.replaceAll(DATE_TIME_REGEX.pattern(), ConstantUtil.SPACE); LocalDateTime parse = null; try { parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_SIMPLE)); } catch (Exception e) { try { parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL)); } catch (Exception exception) { try { parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_DETAIL_DOT)); } catch (Exception ex) { parse = LocalDateTime.parse(originWord, DateTimeFormatter.ofPattern(DATETIME_FORMAT_CN)); } } } return Objects.nonNull(parse) ? String.valueOf(parse.toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli()) : dateTimeStr; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/IdeaPlatformFileTreeUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.file.PsiDirectoryFactory; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import lombok.NonNull; import java.io.File; import java.io.IOException; import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; /** * IDEA platform file system operation tools * * @author caofanCPU **/ public class IdeaPlatformFileTreeUtil { /** * Create a file forcibly, delete the source file before creating it * * @param psiDirectory * @param project * @param dotFileName for example: a.java | b.xml | c.sql | d.txt | e.mp3 * @param content * @return */ public static PsiJavaFile forceCreateJavaFile(@NonNull PsiDirectory psiDirectory, @NonNull Project project, @NonNull String dotFileName, @NonNull CharSequence content) { PsiFile originFile = psiDirectory.findFile(dotFileName); if (Objects.nonNull(originFile)) { originFile.delete(); } return createJavaFile(project, dotFileName, content); } /** * Create file, throw exception when source file exists * * @param project * @param dotFileName * @param content * @return */ public static PsiJavaFile createJavaFile(@NonNull Project project, @NonNull String dotFileName, @NonNull CharSequence content) { return (PsiJavaFile) PsiFileFactory.getInstance(project).createFileFromText(dotFileName, JavaFileType.INSTANCE, content); } /** * Formatting code * * @param project * @param psiElement File which needs to be formatted */ public static void format(@NonNull Project project, @NonNull PsiElement psiElement) { CodeStyleManager.getInstance(project).reformat(psiElement); } /** * Find class * * @param className class name * @return */ public static Optional findClass(@NonNull Project project, @NonNull String className) { return findClass(project, className, psiClass -> true); } public static Optional findClass(@NonNull Project project, @NonNull String className, Predicate predicate) { PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(project); int idx = className.lastIndexOf("."); if (-1 != idx) { String packageName = className.substring(0, idx); String name = className.substring(idx + 1); PsiClass[] classes = shortNamesCache.getClassesByName(name, GlobalSearchScope.allScope(project)); if (0 != classes.length) { for (PsiClass aClass : classes) { PsiJavaFile javaFile = (PsiJavaFile) aClass.getContainingFile(); if (javaFile.getPackageName().equals(packageName) && predicate.test(aClass)) { return Optional.of(aClass); } } } } else { PsiClass[] classes = shortNamesCache.getClassesByName(className, GlobalSearchScope.allScope(project)); if (0 != classes.length) { for (PsiClass aClass : classes) { if (predicate.test(aClass)) { return Optional.ofNullable(aClass); } } } } return Optional.empty(); } /** * Get or create a subdirectory * * @param project current project * @param subDirVirtualFile subdirectory file name * @return */ public static PsiDirectory getOrCreateSubDir(@NonNull Project project, @NonNull VirtualFile subDirVirtualFile) { return PsiDirectoryFactory.getInstance(project).createDirectory(subDirVirtualFile); } /** * Get or create a subdirectory * * @param currentProject current project * @param directoryAbsolutePath directoryRelativePath refer project's root path, see: Project.getBasePath() * @return */ public static PsiDirectory getOrCreateSubDirByPath(@NonNull Project currentProject, @NonNull String directoryAbsolutePath) { String fileDirAbsolutePath = VerbalExpressionUtil.correctUrl(directoryAbsolutePath); VirtualFile fileByIoFileDir = LocalFileSystem.getInstance().findFileByIoFile(new File(fileDirAbsolutePath)); if (Objects.isNull(fileByIoFileDir) || !fileByIoFileDir.exists()) { return null; } PsiDirectory result = null; try { result = IdeaPlatformFileTreeUtil.getOrCreateSubDir(currentProject, fileByIoFileDir); } catch (Throwable e) { // this exception means the directory of directoryRelativePath does't exist! so just ignore it } return result; } /** * Create child files * * @param currentVirtualFile * @param subVirtualFileName * @return */ public static VirtualFile getOrCreateSubVirtualFile(@NonNull VirtualFile currentVirtualFile, @NonNull String subVirtualFileName) { VirtualFile child = currentVirtualFile.findChild(subVirtualFileName); if (Objects.isNull(child)) { try { child = currentVirtualFile.createChildDirectory(null, subVirtualFileName); } catch (IOException e) { // When the creation fails, the directory indicated by the currentVirtualFile root shall prevail child = currentVirtualFile; } } return child; } /** * Create a sub file directory * * @param project * @param currentVirtualFile * @param subVirtualFileName * @return */ public static PsiDirectory getOrCreateSubDir(@NonNull Project project, @NonNull VirtualFile currentVirtualFile, @NonNull String subVirtualFileName) { return getOrCreateSubDir(project, getOrCreateSubVirtualFile(currentVirtualFile, subVirtualFileName)); } /** * Create a sub file directory which class type is PsiDirectory * * @param currentPsiDir * @param subDirName * @return */ public static PsiDirectory getOrCreateSubDir(@NonNull PsiDirectory currentPsiDir, @NonNull String subDirName) { return Optional.ofNullable(currentPsiDir.findSubdirectory(subDirName)).orElseGet(() -> currentPsiDir.createSubdirectory(subDirName)); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/JSONUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import lombok.NonNull; /** * JSON tool * * @author caofanCPU */ public class JSONUtil { public static String formatStandardJSON(@NonNull String source) { String result = source; try { Gson gson = new GsonBuilder().setPrettyPrinting().create(); JsonElement element = JsonParser.parseString(source); result = gson.toJson(element); } catch (JsonSyntaxException e) { // Just ignore, and return the origin text } return result; } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/PropertiesUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.xyz.caofancpu.d8ger.core.KeyEnum; import com.xyz.caofancpu.d8ger.setting.D8gerProjectState; import org.apache.commons.lang3.StringUtils; import java.util.Properties; /** * Properties file tool * * @author caofanCPU */ public class PropertiesUtil { private static final Logger LOG = Logger.getInstance(PropertiesUtil.class); /** * Load configuration file * * @return */ public static Properties loadPropertiesFromRootResource(Project currentProject) { Properties customerProperties = new Properties(); D8gerProjectState settings = D8gerProjectState.getInstance(currentProject); customerProperties.setProperty(KeyEnum.MO.getKey(), settings.moCheck + ConstantUtil.ENGLISH_COMMA + settings.moPath); customerProperties.setProperty(KeyEnum.MO_MAPPER.getKey(), settings.mapperCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperPath); customerProperties.setProperty(KeyEnum.MO_EXAMPLE.getKey(), settings.mapperExampleCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperExamplePath); customerProperties.setProperty(KeyEnum.MO_MAPPER_XML.getKey(), settings.mapperXmlCheck + ConstantUtil.ENGLISH_COMMA + settings.mapperXmlPath); customerProperties.setProperty(KeyEnum.MO_SQL.getKey(), settings.sqlCheck + ConstantUtil.ENGLISH_COMMA + settings.sqlPath); customerProperties.setProperty(KeyEnum.SWAGGER_MO.getKey(), settings.voCheck + ConstantUtil.ENGLISH_COMMA + settings.voPath); customerProperties.setProperty(KeyEnum.MO_HANDLER.getKey(), settings.handlerCheck + ConstantUtil.ENGLISH_COMMA + settings.handlerPath); customerProperties.setProperty(KeyEnum.MO_CONTROLLER.getKey(), settings.controllerCheck + ConstantUtil.ENGLISH_COMMA + settings.controllerPath); customerProperties.setProperty(KeyEnum.FORMAT_STYLE.getKey(), settings.formatStyleCheck + ConstantUtil.EMPTY); customerProperties.setProperty(KeyEnum.SQL_DETECT_TIME_COLUMN.getKey(), settings.detectSQLTimeColumnCheck + ConstantUtil.EMPTY); customerProperties.setProperty(KeyEnum.MO_MAPPER_ANNOTATION.getKey(), settings.mapperBetterThenRepositoryCheck + ConstantUtil.EMPTY); customerProperties.setProperty(ConstantUtil.CONFIG_AUTHOR_KEY, settings.defaultAuthor); customerProperties.setProperty(ConstantUtil.CONFIG_API_URL_PREFIX_KEY, settings.defaultUrlPrefix); customerProperties.setProperty(ConstantUtil.CONFIG_LANGUAGE_KEY, settings.defaultLocale); return customerProperties; } /** * Check if the configuration item is configured as 'true' or 'TRUE' * * @param properties * @param propertyKey * @return */ public static boolean checkConfigTakeEffect(Properties properties, String propertyKey) { String property = properties.getProperty(propertyKey); if (StringUtils.isBlank(property)) { // if no config, just ignore return false; } String noWhiteCharProperty = VerbalExpressionUtil.cleanWhiteChar(property); String[] itemConfigs = noWhiteCharProperty.split(ConstantUtil.ENGLISH_COMMA); return Boolean.parseBoolean(itemConfigs[0]); } /** * Detect if a configuration item contains a directory relative path, * if true then return it, otherwise return null. * * @param properties * @param propertyKey * @return */ public static String detectConfigDirectoryPath(Properties properties, String propertyKey) { String property = properties.getProperty(propertyKey); String noWhiteCharProperty = VerbalExpressionUtil.cleanWhiteChar(property); String[] itemConfigs = noWhiteCharProperty.split(ConstantUtil.ENGLISH_COMMA); if (itemConfigs.length == 1) { // if there is just one item config, ignore too return null; } // here, need to create file, so we should check need put it into custom directory or not return StringUtils.isBlank(itemConfigs[1]) ? null : itemConfigs[1]; } /** * Check and detect if a configuration item contains a directory relative path, * if true then return it, otherwise return null. * * @param properties * @param propertyKey * @return */ public static String checkAndDetectConfigDirectoryPath(Properties properties, String propertyKey) { if (!checkConfigTakeEffect(properties, propertyKey)) { return null; } return detectConfigDirectoryPath(properties, propertyKey); } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/StringAlignUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; import com.alibaba.druid.util.JdbcUtils; import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.regex.Pattern; /** * Handle multi-lines align, batch add prefix | suffix * * @author caofanCPU */ @Slf4j public class StringAlignUtil { /** * White char regex */ public static final Pattern WHITE_CHAR_PATTERN = Pattern.compile("(?:\\s)+"); /** * Compatibility separator pattern, support one or more lineBreak | English comma as ',' | Chinese comma as ',' */ public static final Pattern ORIGIN_COMPATIBILITY_SEPARATOR = Pattern.compile("((?:\\n|(?:\\r\\n))|(?:,)|(?:,))+"); /** * Line begins with English comma */ public static final Pattern START_WITH_ENGLISH_COMMA_PATTERN = Pattern.compile("^(?:,)+"); /** * Config key parser regex */ public static final Pattern CONFIG_PARSER_PATTERN = Pattern.compile("(?:@<)(?:.*)(?:>@)"); /** * Format mysql * * @param sql * @return */ public static String formatMySQL(String sql) { if (StringUtils.isBlank(sql)) { return sql; } try { String dbType = JdbcUtils.MYSQL; List statementList = SQLUtils.toStatementList(sql, dbType); StringBuilder out = new StringBuilder(); SQLASTOutputVisitor visitor = SQLUtils.createFormatOutputVisitor(out, statementList, dbType); for (SQLStatement stmt : statementList) { stmt.accept(visitor); } return out.toString().replaceAll(ConstantUtil.ORIGIN_TAB, ConstantUtil.TAB) + ConstantUtil.ENGLISH_SEMICOLON; } catch (Throwable t) { // any exception, give back the origin sql return sql; } } /** * Handling multi lines by conventional separator * * @param originText * @return */ public static List handleSplitMultiLines(@NonNull String originText) { String legalText = originText.replaceAll(ORIGIN_COMPATIBILITY_SEPARATOR.pattern(), ConstantUtil.ENGLISH_COMMA) .replaceAll(WHITE_CHAR_PATTERN.pattern(), ConstantUtil.EMPTY) .replaceAll(START_WITH_ENGLISH_COMMA_PATTERN.pattern(), ConstantUtil.EMPTY); String splitSymbol = ConstantUtil.ENGLISH_COMMA; return CollectionUtil.splitDelimitedStringToList(legalText, splitSymbol, String::toString); } /** * Format SQL columns, for example, add function or rename by using 'AS' * * @param originText * @param formatAlignment * @param prefix * @param suffix * @param formatSQL * @param formatAsCamel * @return */ public static String formatSQLColumn(@NonNull String originText, Alignment formatAlignment, @NonNull String prefix, @NonNull String suffix, boolean formatSQL, boolean formatAsCamel) { List stringList = handleSplitMultiLines(originText); List completeFixList = CollectionUtil.transToList(stringList, item -> prefix + item + suffix); int singleLineMaxChars = CollectionUtil.max(completeFixList, String::length).intValue(); if (Objects.isNull(formatAlignment)) { formatAlignment = Alignment.LEFT; } List formattedLineList = formatSQLColumn(singleLineMaxChars, formatAlignment, completeFixList); if (formatSQL && formatAsCamel) { stringList = CollectionUtil.transToList(stringList, StringAlignUtil::cleanUnderLineForSQLAliasName); } Map indexMap = CollectionUtil.transToMap(stringList, stringList::indexOf, Function.identity()); StringBuilder result = new StringBuilder(); for (int i = 0; i < formattedLineList.size(); i++) { String column = indexMap.get(i); result.append(formattedLineList.get(i)); if (formatSQL) { result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append("AS").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(column); } result.append(ConstantUtil.ENGLISH_COMMA).append(ConstantUtil.NEXT_LINE); } return StringUtils.isEmpty(result) ? result.toString() : result.deleteCharAt(result.lastIndexOf(ConstantUtil.ENGLISH_COMMA)).toString(); } /** * format multi-lines and handling encryption | decryption * * @param originText * @param alignStyle * @param algorithm * @param endOperate * @return */ public static String formatEND(@NonNull String originText, Alignment alignStyle, Algorithm algorithm, ENDOperate endOperate) { List originStringList = handleSplitMultiLines(originText); // init param if (Objects.isNull(alignStyle)) { alignStyle = Alignment.LEFT; } if (Objects.isNull(algorithm)) { algorithm = Algorithm.AES; } if (Objects.isNull(endOperate)) { endOperate = ENDOperate.ENCRYPTION_AND_DECRYPTION; } // calculate operate List operateList = new ArrayList<>(4); if (ENDOperate.ENCRYPTION_AND_DECRYPTION == endOperate) { operateList.add(ENDOperate.ENCRYPTION); operateList.add(ENDOperate.DECRYPTION); if (Algorithm.PINYIN == algorithm) { operateList.add(ENDOperate.PINYIN); } } else { operateList.add(endOperate); if (ENDOperate.ENCRYPTION == endOperate && Algorithm.PINYIN == algorithm) { operateList.add(ENDOperate.PINYIN); } } Map> handleResultMap = new HashMap<>(8, 0.75f); handleResultMap.put(ENDOperate.ORIGIN, originStringList); if (operateList.contains(ENDOperate.PINYIN)) { // calculate pinyin handleResultMap.put(ENDOperate.PINYIN, CollectionUtil.transToList(originStringList, String::toString)); } if (operateList.contains(ENDOperate.ENCRYPTION)) { List targetList; if (operateList.contains(ENDOperate.PINYIN)) { targetList = handleResultMap.get(ENDOperate.PINYIN); } else { targetList = originStringList; } if (Algorithm.PINYIN == algorithm) { // PINYIN encryption TODO handleResultMap.put(ENDOperate.ENCRYPTION, CollectionUtil.transToList(targetList, String::toUpperCase)); } else { // AES encryption TODO handleResultMap.put(ENDOperate.ENCRYPTION, CollectionUtil.transToList(targetList, String::toLowerCase)); } } if (operateList.contains(ENDOperate.DECRYPTION)) { List targetList; if (operateList.contains(ENDOperate.ENCRYPTION)) { targetList = handleResultMap.get(ENDOperate.ENCRYPTION); } else { targetList = originStringList; } if (Algorithm.PINYIN == algorithm) { // PINYIN decryption TODO handleResultMap.put(ENDOperate.DECRYPTION, CollectionUtil.transToList(targetList, String::toLowerCase)); } else { // AES decryption TODO handleResultMap.put(ENDOperate.DECRYPTION, CollectionUtil.transToList(targetList, String::toUpperCase)); } } // align string for (ENDOperate key : handleResultMap.keySet()) { List itemList = handleResultMap.get(key); int maxCharLength = CollectionUtil.max(itemList, String::length).intValue(); handleResultMap.put(key, formatSQLColumn(maxCharLength, alignStyle, itemList)); } StringBuilder result = new StringBuilder(); List formattedOriginList = handleResultMap.get(ENDOperate.ORIGIN); List pinyinList = handleResultMap.get(ENDOperate.PINYIN); List encryptionList = handleResultMap.get(ENDOperate.ENCRYPTION); List decryptionList = handleResultMap.get(ENDOperate.DECRYPTION); for (int i = 0; i < formattedOriginList.size(); i++) { result.append(formattedOriginList.get(i)); if (i != formattedOriginList.size() - 1) { result.append(ConstantUtil.ENGLISH_COMMA); } else { result.append(ConstantUtil.SPACE); } if (CollectionUtil.isNotEmpty(pinyinList)) { result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append("-->(PinYin Result)").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(pinyinList.get(i)); if (i != formattedOriginList.size() - 1) { result.append(ConstantUtil.ENGLISH_COMMA); } else { result.append(ConstantUtil.SPACE); } } if (CollectionUtil.isNotEmpty(encryptionList)) { result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append("-->(Encryption Result)").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(encryptionList.get(i)); if (i != formattedOriginList.size() - 1) { result.append(ConstantUtil.ENGLISH_COMMA); } else { result.append(ConstantUtil.SPACE); } } if (CollectionUtil.isNotEmpty(decryptionList)) { result.append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append("-->(Decryption Result)").append(ConstantUtil.SPACE).append(ConstantUtil.SPACE).append(decryptionList.get(i)); if (i != formattedOriginList.size() - 1) { result.append(ConstantUtil.ENGLISH_COMMA); } else { result.append(ConstantUtil.SPACE); } } result.append(ConstantUtil.NEXT_LINE); } return result.toString(); } public static String cleanUnderLineForSQLAliasName(@NonNull String columnName) { String result = columnName; for (int i = 0; i < 4; i++) { if (VerbalExpressionUtil.CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE.matcher(result).matches()) { break; } result = VerbalExpressionUtil.camelUnderLineNameConverter(result); } return result; } /** * Format by splitSymbol, such as ',' or NEXT_LINE * * @param originText * @param splitSymbol * @param currentAlignment * @return */ public static String formatBySplitSymbol(String originText, String splitSymbol, Alignment currentAlignment) { List stringList = CollectionUtil.splitDelimitedStringToList(originText, splitSymbol, String::toString); return formatMultiLine(stringList, currentAlignment); } /** * MultiLine format * * @param stringList * @param currentAlignment * @return */ public static String formatMultiLine(List stringList, Alignment currentAlignment) { int singleLineMaxChars = CollectionUtil.max(stringList, String::length).intValue(); return format(singleLineMaxChars, currentAlignment, stringList); } /** * Format multi-string * * @param singleLineMaxChars * @param currentAlignment * @param stringList * @return */ public static String format(int singleLineMaxChars, Alignment currentAlignment, List stringList) { checkAlignmentParam(singleLineMaxChars, currentAlignment); StringBuilder result = new StringBuilder(); for (String wanted : stringList) { switch (currentAlignment) { case RIGHT: pad(result, singleLineMaxChars - wanted.length()); result.append(wanted); break; case CENTER: int toAdd = singleLineMaxChars - wanted.length(); pad(result, toAdd / 2); result.append(wanted); pad(result, toAdd - toAdd / 2); break; case LEFT: result.append(wanted); pad(result, singleLineMaxChars - wanted.length()); break; } result.append(ConstantUtil.NEXT_LINE); } return result.toString(); } /** * Format sql columns, return multi-lines * * @param stringList * @param singleLineMaxChars * @param currentAlignment * @return */ public static List formatSQLColumn(int singleLineMaxChars, Alignment currentAlignment, List stringList) { String result = format(singleLineMaxChars, currentAlignment, stringList); return CollectionUtil.splitDelimitedStringToList(result, ConstantUtil.NEXT_LINE, String::toString); } /** * Supplementary space * * @param to * @param howMany */ public static void pad(StringBuilder to, int howMany) { for (int i = 0; i < howMany; i++) { to.append(ConstantUtil.SPACE); } } /** * Split text, especially is paragraph * * @param text * @param singleLineMaxChars * @return */ public static List splitInputText(String text, int singleLineMaxChars) { List list = new ArrayList<>(); if (StringUtils.isBlank(text)) { return list; } if (singleLineMaxChars < 0) { throw new IllegalArgumentException("singleLineMaxChars must be positive."); } for (int i = 0; i < text.length(); i = i + singleLineMaxChars) { list.add(text.substring(i, Math.min(i + singleLineMaxChars, text.length()))); } return list; } /** * Basic check * * @param singleLineMaxChars * @param align */ public static void checkAlignmentParam(int singleLineMaxChars, Alignment align) { if (singleLineMaxChars < 0) { throw new IllegalArgumentException("singleLineMaxChars must be positive."); } if (align != Alignment.LEFT && align != Alignment.CENTER && align != Alignment.RIGHT) { throw new IllegalArgumentException("invalid justification arg."); } } /** * Format paragraph * * @param text * @param singleLineMaxChars * @param currentAlignment * @return */ public String formatText(String text, int singleLineMaxChars, Alignment currentAlignment) { List stringList = splitInputText(text, singleLineMaxChars); return format(singleLineMaxChars, currentAlignment, stringList); } public enum Alignment { LEFT, CENTER, RIGHT, ; } public enum Algorithm { AES("1"), PINYIN("2"); @Getter private String value; Algorithm(String value) { this.value = value; } } public enum ENDOperate { /** * Fast sqrt magic number in 64 bit. */ ORIGIN("0x5fe6ec85e7de30da"), /** * Fast sqrt magic number, haha, can you guess it? */ PINYIN("0x5f3759df"), ENCRYPTION_AND_DECRYPTION("0"), ENCRYPTION("1"), DECRYPTION("2"), ; @Getter private String value; ENDOperate(String value) { this.value = value; } } } ================================================ FILE: src/main/java/com/xyz/caofancpu/d8ger/util/VerbalExpressionUtil.java ================================================ package com.xyz.caofancpu.d8ger.util; import lombok.NonNull; import org.apache.commons.lang3.StringUtils; import ru.lanwen.verbalregex.VerbalExpression; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Regex common util * Tips: https://github.com/VerbalExpressions/JavaVerbalExpressions * 1. DO NOT USE or(), take oneOf() | add(Regex string) place of it * 2. USE multi segment capt()+endCapt() for easy reading * 3. add() is very powerful, some times it's easy to express OR logic * * @author caofanCPU */ public class VerbalExpressionUtil { /** * Judge current system is WINDOWS, by the way, WINDOWS is real ***... */ public static final boolean CURRENT_OS_IS_WINDOWS = Objects.equals(System.getProperty("os.name").toLowerCase(), "windows"); /** * Uppercase regular expression */ public static final Pattern HUMP_TO_UNDERLINE = Pattern.compile("[A-Z]"); /** * No '_' or '-' and begin with [A-Z] regex, it will trigger to execute CamelToUnderline when regex detect is true */ public static final Pattern CAMEL_UNDERLINE_1_NO_UNDERLINE_CAPITALIZE = Pattern.compile("^(?![_-])(?:[A-Z])[a-zA-Z0-9\\W]+$"); /** * No '_' or '-' and begin with [a-z] regex, it will trigger to execute CamelToUnderline when regex detect is true */ public static final Pattern CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE = Pattern.compile("^(?![_-])(?:[a-z])[a-zA-Z0-9\\W]+$"); /** * No upper case regex, it will trigger to execute LowerCaseToUpperCase when regex detect is true */ public static final Pattern CAMEL_UNDERLINE_3_NO_UPPER_CASE = Pattern.compile("^(?![A-Z])[a-z0-9\\W_-]+$"); /** * No lower case, it will trigger to execute UpperCaseToCamel when regex detect is true */ public static final Pattern CAMEL_UNDERLINE_4_NO_LOWER_CASE = Pattern.compile("^(?![a-z])[A-Z0-9\\W_-]+$"); /** * Swagger field | interface position order regular match expression */ public static final Pattern SWAGGER_MODEL_PATTERN = Pattern.compile("(((?:position)|(?:order))(?:\\s)*(?:=)(?:\\s)*(?:\\d)*)"); /** * When we clear white chars, considering spaces can be part of data we should except spaces in JSON string */ public static final Pattern WHITE_CHAR_IN_JSON_REGEX_0 = Pattern.compile("(?:[\\t\\n\\x0B\\f\\r])+"); /** * Beauty JSON view regex */ public static final Pattern WHITE_CHAR_IN_JSON_REGEX_1 = Pattern.compile("(?:\")+[ ]*[::]+[ ]*"); /** * JSON string definition regex */ public static final Pattern JSON_STRING_JUDGE_REGEX = Pattern.compile("^(?:\\{).*(?:})$"); /** * Next line separator regex */ public static final Pattern NEXT_LINE_REGEX = Pattern.compile("(?:\\n|(?:\\r\\n))+"); /** * English dot as key symbol regex */ public static final Pattern KEY_ENGLISH_DOT_REGEX = Pattern.compile("\\."); /** * Symbols '[', ']', '<', '>' OR relationship regex */ public static final Pattern KEY_COLLECTION_EDGE_SYMBOL_REGEX = Pattern.compile("[\\[\\]<>]"); /** * String.replaceAll(), matched result can be access by $0 */ public static final String REPLACE_MATCH_RESULT_SYMBOL = "$0"; /** * Java file as source code, which prefix path */ public static Pattern PREFIX_JAVA_SOURCE_FILE_PATH = Pattern.compile("^(?:.*)(?:[/\\\\]*)(?:src)(?:[/\\\\]+)(?:main)(?:[/\\\\]+)(?:java)(?:[/\\\\]+)"); /** * File path split symbol */ public static Pattern FILE_PATH_SPLIT_SYMBOL = Pattern.compile("(?:[/\\\\]+)"); /** * File path prefix split in Windows OS */ public static Pattern WINDOWS_PREFIX_JAVA_SOURCE_FILE_PATH = Pattern.compile("(?:[a-zA-Z]*:\\.*)"); /** * CaoFAn -->(Uncapitalize) caoFAn -->(CamelToUnderline) cao_f_an -->(LowerCaseToUpperCase) CAO_F_AN -->(UpperCaseToCamel) CaoFAn * * @param originName * @return */ public static String camelUnderLineNameConverter(@NonNull String originName) { int matchNo = 0; if (CAMEL_UNDERLINE_1_NO_UNDERLINE_CAPITALIZE.matcher(originName).matches()) { matchNo = 1; } if (CAMEL_UNDERLINE_2_NO_UNDERLINE_UNCAPITALIZE.matcher(originName).matches()) { matchNo = 2; } if (CAMEL_UNDERLINE_3_NO_UPPER_CASE.matcher(originName).matches()) { matchNo = 3; } if (CAMEL_UNDERLINE_4_NO_LOWER_CASE.matcher(originName).matches()) { matchNo = 4; } if (matchNo == 0) { return originName; } String result = originName; switch (matchNo) { case 1: // Uncapitalize result = StringUtils.uncapitalize(originName); break; case 2: // CamelToUnderline result = StringUtils.lowerCase(originName.replaceAll(HUMP_TO_UNDERLINE.pattern(), "_$0")); break; case 3: // LowerCaseToUpperCase result = StringUtils.upperCase(originName); break; case 4: // UpperCaseToCamel String[] words = originName.split("[_-]"); List resultItemWordList = new ArrayList<>(words.length); for (String word : words) { resultItemWordList.add(StringUtils.capitalize(StringUtils.lowerCase(word))); } result = CollectionUtil.join(resultItemWordList, ConstantUtil.EMPTY); break; default: break; } return result; } /** * Swagger field | interface position order regular replacement * * @param originString * @param replaceString * @return */ public static String regexHandleSwaggerModelProperty(String originString, final String replaceString) { Matcher matcher = SWAGGER_MODEL_PATTERN.matcher(originString); return matcher.replaceAll(replaceString); } /** * Extract matched content list by pattern * * @param originContext * @param pattern * @return */ public static List extractMatchContent(@NonNull String originContext, Pattern pattern) { List resultList = new ArrayList<>(); Matcher matcher = pattern.matcher(originContext); while (matcher.find()) { // add current matched group value resultList.add(matcher.group()); } return resultList; } /** * Create a regular expression object * * @param matchKeyWord * @return */ public static VerbalExpression buildRegex(String matchKeyWord) { return VerbalExpression.regex().capt().find(matchKeyWord).endCapt().build(); } /** * Disjunction regular expression * * @param originComment * @return */ public static String extractComment(String originComment) { VerbalExpression regex = VerbalExpression.regex() .capt() .oneOf("/", "\\*", ConstantUtil.NEXT_LINE, ConstantUtil.TAB, ConstantUtil.ORIGIN_TAB, ConstantUtil.MINI_TAB).oneOrMore() .endCapt() .build(); return executePatternRex(regex, originComment, ConstantUtil.EMPTY); } /** * Regular replacement * * @param regexExpression * @param originText * @param replacer * @return */ public static String executePatternRex(VerbalExpression regexExpression, String originText, String replacer) { Pattern pattern = Pattern.compile(regexExpression.toString()); Matcher matcher = pattern.matcher(originText); return matcher.replaceAll(replacer); } /** * Regular replacement of relatively large strings, using StringBuilder to store strings * * @param regexExpression * @param originText * @param replacer * @return */ public static StringBuilder executePatternRex(VerbalExpression regexExpression, StringBuilder originText, StringBuilder replacer) { Pattern pattern = Pattern.compile(regexExpression.toString()); Matcher matcher = pattern.matcher(originText); return new StringBuilder(matcher.replaceAll(replacer.toString())); } /** * Camel convert to underline * * @param originName * @return */ public static String sqlUnderLineName(String originName) { return StringUtils.lowerCase(StringUtils.uncapitalize(originName).replaceAll(HUMP_TO_UNDERLINE.pattern(), "_$0")); } /** * Remove the trailing one or more 'Mo's from the original Model object's name * * @param originMoName * @return */ public static String cropMoSuffix(@NonNull String originMoName) { VerbalExpression regex = VerbalExpression.regex().capt().find(ConstantUtil.MO_SUFFIX).oneOrMore().endCapt().endOfLine().build(); return executePatternRex(regex, originMoName, ConstantUtil.EMPTY); } /** * url path correction, remove rare '/' to keep just one '/' and begin with it * compatible windows file path * * @param property * @return */ public static String correctUrl(String property) { String resultPrefix = File.separator; try { if (CURRENT_OS_IS_WINDOWS) { String[] splits = property.split(ConstantUtil.ENGLISH_COLON); resultPrefix = splits[0] + ConstantUtil.ENGLISH_COLON; if (splits.length == 1 || StringUtils.isBlank(splits[1])) { return resultPrefix + "/"; } property = splits[1]; } else { property = resultPrefix + property; } } catch (Throwable e) { throw new RuntimeException("Illegal file path, please check carefully!"); } VerbalExpression regex = VerbalExpression.regex() .capt() .oneOf("/", "\\\\").oneOrMore() .endCapt() .build(); String tempResult = executePatternRex(regex, property, "/"); return CURRENT_OS_IS_WINDOWS ? resultPrefix + tempResult : tempResult; } /** * Convert path string to package, * for example: /ModuleName//src/main/java/com/xyz/caofancpu/d8ger/test --> com.xyz.caofancpu.d8ger.test * Compatible with WINDOWS: D:/ModuleName//src\main\\java/com/xyz/caofancpu/d8ger/test --> com.xyz.caofancpu.d8ger.test * * @param originPath * @return */ public static String convertPathToPackage(String originPath) { String first = originPath.replaceAll(PREFIX_JAVA_SOURCE_FILE_PATH.pattern(), ConstantUtil.EMPTY); String second = first.replaceAll(FILE_PATH_SPLIT_SYMBOL.pattern(), ConstantUtil.ENGLISH_FULL_STOP); if (StringUtils.isBlank(second) || second.length() < 2) { throw new RuntimeException("Illegal file path, please check carefully!"); } if (CURRENT_OS_IS_WINDOWS) { String winR = second.replaceAll(WINDOWS_PREFIX_JAVA_SOURCE_FILE_PATH.pattern(), ConstantUtil.EMPTY); if (StringUtils.isBlank(winR)) { throw new RuntimeException("Illegal file path, please check carefully!"); } return winR; } return Objects.equals(second.charAt(0), '.') ? second.substring(1) : second; } public static String convertPathToPackage2(String originPath) { VerbalExpression regex1 = VerbalExpression.regex() .startOfLine().anything() .capt().oneOf("/", "\\\\").zeroOrMore().endCapt() .capt().find("src").oneOf("/", "\\\\").oneOrMore().endCapt() .capt().find("main").oneOf("/", "\\\\").oneOrMore().endCapt() .capt().find("java").oneOf("/", "\\\\").oneOrMore().endCapt() .build(); String first = executePatternRex(regex1, originPath, ConstantUtil.EMPTY); VerbalExpression regex2 = VerbalExpression.regex() .capt() .oneOf("/", "\\\\").oneOrMore() .endCapt() .build(); String second = executePatternRex(regex2, first, ConstantUtil.ENGLISH_FULL_STOP); if (StringUtils.isBlank(second) || second.length() < 2) { throw new RuntimeException("Illegal file path, please check carefully!"); } if (CURRENT_OS_IS_WINDOWS) { VerbalExpression regex3 = VerbalExpression.regex() .capt() .add("[a-zA-Z]").zeroOrMore().then(":").then(".").zeroOrMore() .endCapt() .build(); String winR = executePatternRex(regex3, second, ConstantUtil.EMPTY); if (StringUtils.isBlank(winR)) { throw new RuntimeException("Illegal file path, please check carefully!"); } return winR; } return Objects.equals(second.charAt(0), '.') ? second.substring(1) : second; } /** * Beautify multiple newlines * (?:\\n|(?:\\r\\n))+ * * @param source * @return */ public static String beautyNextLine(@NonNull String source) { VerbalExpression regex = VerbalExpression.regex() .lineBreak().oneOrMore() .build(); return executePatternRex(regex, source, ConstantUtil.NEXT_LINE); } /** * Clear whitespace * (?:\\s)+ * * @param source * @return */ public static String cleanWhiteChar(@NonNull String source) { VerbalExpression regex = VerbalExpression.regex() .space().oneOrMore() .build(); return executePatternRex(regex, source, ConstantUtil.EMPTY); } /** * Clear whitespace in JSON string * * @param source * @return */ public static String cleanJSONWhiteChar(@NonNull String source) { return source.replaceAll(WHITE_CHAR_IN_JSON_REGEX_0.pattern(), ConstantUtil.EMPTY) .replaceAll(WHITE_CHAR_IN_JSON_REGEX_1.pattern(), ConstantUtil.ENGLISH_DOUBLE_QUOTES + ConstantUtil.ENGLISH_COLON); } } ================================================ FILE: src/main/resources/META-INF/plugin.xml ================================================ com.xyz.caofancpu.D8gerAutoCode D8gerAutoCode D8ger•帝八哥 As JetBrains' said, I believe that you should be good use of tools will save you precious hours on your busing work.
I always wonder, "If someone else has already solved the repeating work, why do I need to repeat it again?"
Well, that's a valid question for my drive to find the repeat parts at daily work and develop this plugin to save my time.
After 13 version iterations, I believe you're really worthy of using this plugin.
重复编码老瞎忙,️ 写来写去那几行. 不知工具在何方? 八哥智能一键帮!
Java自动代码生成利器, 配合LaoYouTiao, 还有强大的字符串批处理, Linux命令工具, 正则表达式奇淫巧技.


]]> com.intellij.modules.platform com.intellij.modules.java com.intellij.java If you like D8gerAutoCode, please star the source project for supporting me, thanks!
  • 4.1

    • BugFix:
      • Fix 'D8gerAutoCode' error file path parsing while in WINDOWS system. For more detail, please refer issue2

  • 4.0(HIGH.START)

    • Important note: This time the function is migrated and upgraded, the plug-in has been divided into functions, the purpose is to be full-time and dedicated, and the general functions are sinking to serve more programmers
      • No.0: Each plug-in is positioned in two aspects, one is efficient coding, and the other is high-quality knowledge links to help users obtain enough useful information to improve their skills
      • No.1: LaoYouTiao, Published, located JetBrains full product plug-in, general functions, covering text parsing, numerical processing, shell script processing
      • No.2: D8gerAutoCode, Published, located IntelliJ IDEA, auto coding
      • No.3: D8gerByteSleep, Hatching, located PyCharm
      • No.4: D8gerJustGo, Hatching, located GoLand
      • No.5: D8gerAndison, Hatching, located Android Studio
      • No.6: D8gerWebit, Hatching, located WebStorm
      • No.7: RoadMap refers DSP(D8ger Series Plan)
    • Function migration:
      • BeautifulJSON、SimplifyOneLine、BeautifulMySQL、CamelUnderlineConvert、D8gerMore are migrated into plugin named LaoYouTiao.
      • The shortcut keys and usage methods have not changed, only the code generation functions related to Java are retained.

  • 3.2

    • BugFix:
      • Fix 'BeautifulJSON' issue when parsing complex JSON string.
    • Optimization: 'CamelUnderlineConvert' now supports timestamp-dateTime convert, select the text and use shortcut `alt` + `shift` + `cmd` + `U` to find out.

  • 3.4

    • Addition: 'OhMyZSH' easter eggs, try to type 'ohmyzsh' in the blank file in IDEA to get some useful linux commands. I'm sure you'll save much time.
    • BugFix: Fix donate url(I'm waiting for your 🌟 the project on the github).
    • Optimization: 'BeautifulJSON', 'SimplifyOneLine' and 'BeautifulMySQL' now supports section or whole document convert.

  • 3.2

    • BugFix:
      • Fix 'BeautifulJSON' issue when parsing complex JSON string.
    • Optimization: 'CamelUnderlineConvert' now supports timestamp-dateTime convert, select the text and use shortcut `alt` + `shift` + `cmd` + `U` to find out.

  • 3.1

    • BugFix:
      • Fix config item 'locale' problem when selected as 'ZN', and before before the 3.0 version's comment was English default.
      • Fix SQL definition in x.sql file.️
      • Fix batch insert records in xMapper.xml file cause 'id', 'createTime', 'updateTime' all should according to the Database.
    • Optimization: Config item 'autoDetectSQLTimeColumn' now is more intelligent. If you checked, 'createTime' and 'updateTime' would be generated perfectly in there right position.

  • 3.0

    • Addition:
      • Grand celebration for 'D8gerAutoCode' getting his face! Now you can config the generated property parameters by setting GUI.
      • First, Open the configuration box to set the generation parameters, 'Preference' --> 'Other Settings' --> 'D8gerAutoCode'
      • Then, Check the file to be generated and choose the generation path, rewrite 'author'、'apiUrlPrefix' and 'locale', and click the button to save your configuration.
    • Optimization: Support project level setting parameters for non-invasive, d8ger.properties should exist invisible.
    • Adjustment: Remove the generate params by 'd8ger.properties' file, replace of D8gerAutoCode setting GUI.

  • 2.5

    • Addition:
      • Add 'autoDetectSQLTimeColumn' configuration for supporting disable default generating 'create_time' and 'update_time' column definition in SQL.
      • Add 'mapperBatterThenRepository' configuration for supporting custom mapper annotation in both SpringMVC and SpringBoot.
      • Add 'selectOneByExample' in Mapper.java for supporting query one record.
      • Add 'insertSelectiveWithId' in Mapper.java for supporting insert non null field and the null field will be filled with the database default value.
    • Optimization: 'cause 'id' is the primary key, all insert operations should exclude 'id' column.
    • BugFix:
      • Generation 'update_time' column definition remove the rare comma.
      • Troubleshooting the rare dir named 'D8gerAutoCode', now you can see it only with unspecified directory configuration.
    • Adjustment: Remove 'ServiceInterface' and 'ServiceImpl', 'cause I think 'Handler' is more suitable.

  • 2.4

    • Addition: One-click to beauty MySQL, isn't fragrant?
    • Optimization: String parsing performance.
    • Attention: Select your MySQL text, ctrl + alt + shift + 'B' will back a surprise.

  • 2.3

    • BugFix: Json format bug.
    • Addition:
      • NASA easter eggs, try to type 'nasa' in the blank file in IDEA to get the nasa-template.
      • NASA easter eggs, multi-lines can be batch handled with the nasa-template, special for sql columns.
    • Optimization:
      • Optimize some regex performance.
      • Support linebreak or comma as the delimiter.
      • Support windows linebreak when rendering origin code.
    • Attention: When execute auto-coding, you should be careful at the linebreak, it maybe different from your project config.
    • Adjustment:
      • Icons changed for align, friendly view etc.
      • The manual of this plugin has been moved to my website.

  • 2.1

    • BugFix: add Uncapitalize, and the circle is Camel-Underline-Uppercase-Uncapitalize-Lowercase.
    • Optimization: Optimize some regex performance.
    • Attention: Regex easter eggs add some very useful regex search-replace skills hidden in JetBrains' IDE products. Try to learn and you will save much time at working.

  • 2.0

    • BugFix: Modify method name in Controller.java.
    • Addition:
      • Remove repeat work of moving file into directories for smart coding.
      • Camel-Underline-Uppercase-Lowercase can be converted to each other by shortcut `alt` + `shift` + `cmd` + `U`.
      • Regex easter eggs, try to type 'regex' in the blank file in IDEA to find it.
    • Optimization: Optimize source code and improve performance.
    • Attention: If the icon of plugin shows error(red square with a cross), try to upgrade the version of Intellij util 2019.3.*(greater than 2019.2.*).

  • 1.24

    • BugFix: Update method named 'updateBatchByPrimaryKeySelective' in mapper.xml.
    • Addition: Set default language English and you can config it as Chinese Simplified, as before, typing 'd8ger' for the latest configuration template.
    • Attention: You should configure your database connection like 'allowMultiQueries=true' for supporting batchUpdate operation.

  • 1.23

    • BugFix: Fix required dependencies by JetBrains' suggestion for some known compatibility issues.
    • Addition: Add JSON-formatter and WhiteChar-cleaner.
    • Attention: Can you star the project on the github?

  • 1.22

    • BugFix: Fix README of style, description, picture problems.
    • Enhance: Enhance profile for generating codes by using regex to replace the circle of matching string.
    • Attention: Can you star the project on the github?

  • 1.21

    • BugFix: Fix README of style, description, picture problems.
    • Addition: Add MoExample autoCoding for supporting simple sql.
    • Attention: Can you star the project on the github?

  • 1.20

    • Completion: Auto coding for Mo/Example/Mapper/Xml/SQL/Service completed, wow!
    • Attention: Can you star the project on the github?
    ]]>
    ================================================ FILE: src/main/resources/icons/Icon ================================================ [阿里icon](https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=991968) [图片压缩](https://tinypng.com/) 0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions Usage, static pattern can improve performance in regex searching: public static final Pattern XXX_REGEX = Pattern.compile("...Regex string..."); 1.Whitespace Regex (?:(?:(?:((?:\s)+)|(?:(?:\\n)+)|(?:(?:\\r\\n)+)|(?:(?:\\t)+)))) 2.One or more newlines Regex (?:\\n|(?:\\r\\n))+ 3.Phone validate Regex ^1[0-9]{10}$ 4.Email validate Regex ^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$ 5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species ^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,30}$ 6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital] (?:position)(?:\\s)*(?:\\=)(?:\\s)*(?:\\d)* 7.No '_' in word Regex ^(?!_)[a-zA-Z0-9\\W]+$ 8.No upper case in word Regex ^(?![A-Z])[a-z0-9\\W_]+$ 9.No lower case in word Regex ^(?![a-z])[A-Z0-9\\W_]+$ 10.'www' Url detect Regex ^(?:http)(?:s)?(?:\:\/\/)(?:www\.)?(?:[^\ ]*)$ ================================================ FILE: src/main/resources/template/.zshrc ================================================ export ZSH="$HOME/.oh-my-zsh" export HOMEBREW_NO_AUTO_UPDATE=true ZSH_THEME="powerlevel9k/powerlevel9k" POWERLEVEL9K_MODE="nerdfont-complete" POWERLEVEL9K_PROMPT_ON_NEWLINE=true POWERLEVEL9K_RPROMPT_ON_NEWLINE=false POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon user dir_writable dir vcs) POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time root_indicator background_jobs time disk_usage ram) #POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )" #POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX="" #POWERLEVEL9K_USER_ICON="\uF415" #  POWERLEVEL9K_ROOT_ICON="\uF09C" #POWERLEVEL9K_SUDO_ICON=$'\uF09C' #  POWERLEVEL9K_TIME_FORMAT="%D{%H:%M}" #POWERLEVEL9K_VCS_GIT_ICON='\uF408 ' #POWERLEVEL9K_VCS_GIT_GITHUB_ICON='\uF408 ' ZSH_DISABLE_COMPFIX=true #ENABLE_CORRECTION="true" DISABLE_CORRECTION=true COMPLETION_WAITING_DOTS=true # 左侧栏目显示的要素(指定的关键字参考官网) #POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(os_icon context dir vcs) # 右侧栏目显示的要素 #POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs time virtualenv) #新起一行显示命令 (推荐!极其方便) #POWERLEVEL9K_PROMPT_ON_NEWLINE=true #右侧状态栏与命令在同一行 #POWERLEVEL9K_RPROMPT_ON_NEWLINE=false #缩短目录层级 #POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 #缩短目录策略:隐藏上层目录中间的字 #POWERLEVEL9K_SHORTEN_STRATEGY="truncate_middle" #添加连接上下连接箭头更方便查看 #POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX="↱" #POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX="↳ " # 新的命令与上面的命令隔开一行 #POWERLEVEL9K_PROMPT_ADD_NEWLINE=true # Git仓库状态的色彩指定 #POWERLEVEL9K_VCS_CLEAN_FOREGROUND='blue' #POWERLEVEL9K_VCS_CLEAN_BACKGROUND='black' #POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND='yellow' #POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='black' #POWERLEVEL9K_VCS_MODIFIED_FOREGROUND='red' #POWERLEVEL9K_VCS_MODIFIED_BACKGROUND='black' DISABLE_AUTO_UPDATE="true" # autojump : 'j'历史目录 # cp : 'cpv'带进度条的复制 # zsh_reload : 'src'快速重载.zshrc # 快速编辑.zshrc: alias 'vrc=vim ~/.zshrc' # 快速展示.zshrc: alias 'crc=cat ~/.zshrc' # extract : 'x'解压任何文件 plugins=(git autojump cp zsh_reload extract zsh-syntax-highlighting) export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 # Maven家目录 export M2_HOME=/usr/local/maven-3.6.1/apache-maven-3.6.1 alias mcf="/usr/local/maven-3.6.1/caofanCPU-apache-maven-3.6.1/bin/mvn" # 查看java安装位置命令 /usr/libexec/java_home -V export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home export JRE_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH export PATH=$M2_HOME/bin:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH # Python项目打包工具包 export TWINE_HOME=/Users/D8GER/Library/Python/3.7 export PATH=$PATH:$TWINE_HOME/bin export PATH=$PATH:$HOME/bin export PATH="$PATH:/usr/local/python3/bin" # thefuck插件 eval "$(thefuck --alias)" # 服务器 alias caofanCPU='sshpass -f PWD_DIR ssh xxxx@xx.xx.xx.xx' alias caofanJumpAli='sshpass -f PWD_DIR ssh xx@xx.xx.xx.xx' function execute() { http --session=~/Desktop/ssoLogin/session-${1}.json --verify=no -v ${2} POST ${@:3} } function downLoadResponse() { echo "执行命令内容: \n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2}\n" http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -d >>~/Desktop/ssoLogin/ResponseBody.json ${@:2} } function downLoadExcel() { echo "执行命令内容: \n http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2}" http --verify=no -v --download --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json -o ${2} } function downloadD8ger() { echo "执行命令内容: 并发下载文件" for i in {1..30} do http --verify=no -v --download GET ${1} -o D8.zip done } function show() { echo "执行命令内容: \n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2}\n" http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${1} < ~/Desktop/ssoLogin/requestBody.json ${@:2} } function searchPortOccupy(){ lsof -i :${1} } function searchPID(){ ps aux | grep ${1} | grep -v grep | awk '{print $2}' } function killPID(){ pid=`ps aux | grep ${1} | grep -v grep | awk '{print $2}'` if [ -n "$pid" ]; then kill -9 $pid sleep 1 fi } # 环境 function xDev() { sshpass -f ENV_PIR.txt ssh xx@xx.xx.xx.${1} -t 'cd /work/www/d8ger.com/logs/; exec $SHELL' } # 环境普通模式 function xDevNormal(){ sshpass -f ENV_PIR.txt ssh xx@xx.xx.xx.${1} } # 不同环境 function backgroundENV() { env=${1} if [ -z "$env" ]; then echo "请选择可用环境: 1,2,3,4,5,6,7,8,9,10" return fi domain='' if [ "$env" = '1' ]; then domain='https://1.d8ger.com' elif [ "$env" = '2' ]; then domain='https://2.d8ger.com' elif [ "$env" = '3' ]; then domain='https://3.d8ger.com' elif [ "$env" = '4' ]; then domain='https://4.d8ger.com' elif [ "$env" = '5' ]; then domain='https://5.d8ger.com' elif [ "$env" = '6' ]; then domain='https://6.d8ger.com' elif [ "$env" = '7' ]; then domain='https://7.d8ger.com' elif [ "$env" = '8' ]; then domain='https://8.d8ger.com' elif [ "$env" = '9' ]; then domain='https://9.d8ger.com' elif [ "$env" = '10' ]; then domain='https://ok.d8ger.com' fi # 判断 if [ -z "$domain" ]; then echo "请选择可用环境: 1,2,3,4,5,6,7,8,9,10" return fi echo "德玛西亚, http -v --verify=no POST ${domain}/ok/xx" echo "查询任务是否启动及是否完成: grep \"德玛西亚\" all.log | grep \"end\"" http -v --verify=no POST ${domain}/ok/xx } function justDoIT(){ SID=${1} if [ -z "$SID" ]; then echo "非法的SID, 请检查" return fi url="https://1.d8ger.com/xx/yy/zz" # 登录 login-cookie -f ~/Desktop/ssoLogin/sso-on-admin.json -a 6 # 执行 echo "执行:\n http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true\n" # http多个参数不能放在一个字符串中, 用多个变量来区分解决 http --verify=no -v --session-read-only=~/session-cookie-read-only.json POST ${url} sId:=${SID} bId:=50220671 cIds:='[]' areUok:=false healthy:=true } function cph(){ echo ",------. ,---. ,----. ,------.,------." echo "| .-. \\ | o |' .-./ | .---'| .--. '" echo "| | \\ :.' '.| | .---.| \`--, | '--'.'" echo "| '--' /| o |' '--' || \`---.| |\\ \\" echo "\`-------' \`---' \`------' \`------'\`--' '--'" echo "##### SCP命令 #####" echo "# -r 支持复制目录及其子文件" echo "- 本地文件传到远程服务器" echo "scp /X_DIR/LEARN-SH.sh xx@xx.xx.xx.xx:~/" echo "- 从远程服务器拉取文件" echo "scp xx@xx.xx.xx.xx:~/HAHA.tmp /X_DIR/ZZ.xls" echo "- 无痕登录" echo "xD8scp || d8scp" echo "sshpass -f /X_DIR/PWD-SSH.txt scp /X_DIR/LEARN-SH.sh xx@xx.xx.xx.xx:~/" echo "sshpass -f /X_DIR/PWD-SSH.txt scp xx@xx.xx.xx.xx:~/HAHA.tmp /X_DIR/ZZ.xls" echo "##### cpv #####, zsh的一个插件cp, 文件复制时展示进度条" echo "##### sudo cp #####, 普通复制" } function fkgrep(){ echo ",------.,--. ,--. ,----. ,------. ,------.,------." echo "| .---'| .' /' .-./ | .--. '| .---'| .--. '" echo "| \`--, | . ' | | .---.| '--'.'| \`--, | '--' |" echo "| |\` | |\\ \' '--' || |\\ \\ | \`---.| | --'" echo "\`--' \`--' '--' \`------' \`--' '--'\`------'\`--'" echo "" echo "grep -n '[a-zA-Z0-9]D8' X.txt" echo "grep -n '[^a-zA-Z0-9]D9' X.txt" echo "grep -n '^[a-z]' X.txt" echo "grep -n '^[^a-z]' X.txt" echo "grep -n '^$' X.txt" echo "grep -n '\.$' X.txt" echo "grep -n 'g.*d' X.txt" echo "grep -n 'go*d' X.txt" echo "grep -n 'o\{2,3\}' X.txt" echo "grep -En 'God|The' X.txt grep -n 'god\|The' X.txt" echo "grep -En 'o+' X.txt grep -n 'o\+' X.txt" echo "grep -n '\.' X.txt grep -En '\.' X.txt" echo "grep -En '(oo)+' X.txt grep -n '\(oo\)\+' X.txt" echo "Search Today's log: ll -ah | grep \"[a-z_A-Z]\+\.log\"" } function arthasHelp(){ echo " ,---. ,------. ,--------.,--. ,--. ,---. ,---." echo " / O \\ | .--. ''--. .--'| '--' | / O \\ ' .-'" echo "| .-. || '--'.' | | | .--. || .-. |\`. \`-." echo "| | | || |\\ \\ | | | | | || | | |.-' |" echo "\`--' \`--'\`--' '--' \`--' \`--' \`--'\`--' \`--'\`-----'" # `和\ 为特殊字符, 必须使用\转义 echo "\n# 观察方法返回值" echo "watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \"{params,returnObj}\" -x 2" echo "watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \"{params,returnObj}\"" echo "# 观察方法入参, 对象层次限制2级" echo "watch com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage \"{params,returnObj}\" -x 2 -b" echo "# 持续记录3次接口调用" echo "tt -t -n 3 com.xyz.caofancpu.trackingtime.controller.D8gerController queryD8gerMoPage" echo "# 展示记录接口调用的列表" echo "tt -l" echo "# 展示某个具体调用过程" echo "tt -i 1002" echo "# 重复某个具体调用, 重复3次, 重复间隔2秒" echo "tt -i 1002 -p --replay-times 3 --replay-interval 2000" echo "# 日志器" echo "logger" echo "# 类加载器列表" echo "classloader -t" echo "history" echo "help" echo "keymap" echo "dashboard" echo "# 清屏" echo "cls" echo "# 线程" echo "thread" echo "thread --state WAITING" echo "thread --state TIMED_WAITING" echo "thread --state RUNNABLE" echo "\n# 退出、关闭等命令, 禁止ctrl + C" echo "# 退出某个命令" echo "Q" echo "# 退出当前arthas-client" echo "quit" echo "# 关闭arthas-server" echo "shutdown" } alias searchPID='searchPID' alias killPID='killPID' alias searchPortOccupy='searchPortOccupy' alias https-downLoadResponse='downLoadResponse' alias https-show='show' alias https-downLoadExcel='downLoadExcel' alias https-downloadD8ger='downloadD8ger' alias 'xDev=xDev' alias 'xDevNormal=xDevNormal' alias 'backgroundENV=backgroundENV' alias 'showssh=ps -ef | grep ssh' alias 'tsm=justDoIT' # 开隧道 alias 'iphone4j=nohup sshpass -f TUNNEL_DIR ssh xx@xx.xx.xx.xx -L 11186:xx.xx.xx.xx:1186 -N &' alias 'ip=ifconfig | grep xxx' alias 'cph=cph' alias 'fkgrep=fkgrep' alias 'arthasHelp=arthasHelp' # 快速编辑.zshrc alias 'vrc=vim ~/.zshrc' # 快速展示.zshrc alias 'crc=cat ~/.zshrc' # source ~/.bash_profile if [ -f ~/.bash_profile ]; then . ~/.bash_profile; fi source $ZSH/oh-my-zsh.sh ================================================ FILE: src/main/resources/template/ControllerTemplate.txt ================================================ package @controllerPackage@; import @handlerPackage@.@MoName@Handler; import @moPackage@.@MoName@Mo; import @swaggerMoPackage@.@MoName@Vo; import com.alibaba.fastjson.JSONObject; import com.github.pagehelper.PageInfo; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSort; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.util.ArrayList; import java.util.List; /** * @MoName@Mo控制器 * * @author @d8Author@ */ @RestController @Api(tags = {"@MoName@Mo模块接口"}) @ApiSort(0) @Slf4j public class @MoName@Controller { @Resource private @MoName@Handler @uncapitallizeMoName@Handler; @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/add") @ApiOperationSupport(order = 1) @ApiOperation(value = "@MoName@Mo新增记录") public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // 转换数据 @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo); return @uncapitallizeMoName@Mo.getId(); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd") @ApiOperationSupport(order = 2) @ApiOperation(value = "@MoName@Mo批量新增") public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) { List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size()); for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) { @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class)); } return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList") @ApiOperationSupport(order = 3) @ApiOperation(value = "@MoName@Mo列表查询") public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // 转换数据 @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage") @ApiOperationSupport(order = 4) @ApiOperation(value = "@MoName@Mo分页查询") public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // 转换数据 @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize()); return PageInfo.of(result@MoName@MoList); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "@MoName@Mo修改记录") public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // 转换数据 @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate") @ApiOperationSupport(order = 5) @ApiOperation(value = "@MoName@Mo批量修改记录") public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) { // 转换数据 List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size()); @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class))); return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete") @ApiOperationSupport(order = 6) @ApiOperation(value = "@MoName@Mo删除记录") public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId()); } } ================================================ FILE: src/main/resources/template/DeletedServiceInterfaceTemplate.txt ================================================ package @serviceInterfacePackage@; import @moPackage@.@MoName@Mo; import java.util.List; /** * @MoName@Mo对应的Service接口定义 * * @author @d8Author@ */ public interface @MoName@Service { /** * 插入单条记录 * * @param @uncapitallizeMoName@Mo * @return */ int add(@MoName@Mo @uncapitallizeMoName@Mo); /** * 批量插入 * * @param @uncapitallizeMoName@MoList * @return */ int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * 查询列表, 如果携带分页参数则返回分页后的列表 * * @param @uncapitallizeMoName@Mo * @param pageParams 可选分页参数 * @return */ List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams); /** * 根据id更新非null字段 * * @param @uncapitallizeMoName@Mo * @return */ int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo); /** * 批量根据id更新非null字段 * * @param @uncapitallizeMoName@MoList * @return */ int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * 根据id物理删除 * * @param id * @return */ int delete(T id); } ================================================ FILE: src/main/resources/template/EN/ControllerTemplate.txt ================================================ package @controllerPackage@; import @handlerPackage@.@MoName@Handler; import @moPackage@.@MoName@Mo; import @swaggerMoPackage@.@MoName@Vo; import com.alibaba.fastjson.JSONObject; import com.github.pagehelper.PageInfo; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSort; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.util.ArrayList; import java.util.List; /** * @MoName@MoController * * @author @d8Author@ */ @RestController @Api(tags = {"@MoName@Mo-ModuleAPI"}) @ApiSort(0) @Slf4j public class @MoName@Controller { @Resource private @MoName@Handler @uncapitallizeMoName@Handler; @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/add") @ApiOperationSupport(order = 1) @ApiOperation(value = "@MoName@Mo-AddRecord") public Object add(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // convert Vo to Mo @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); @uncapitallizeMoName@Handler.add(@uncapitallizeMoName@Mo); return @uncapitallizeMoName@Mo.getId(); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchAdd") @ApiOperationSupport(order = 2) @ApiOperation(value = "@MoName@Mo-BatchAddRecords") public Object batchAdd(@Valid @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) { List<@MoName@Mo> @uncapitallizeMoName@MoList = new ArrayList<>(@uncapitallizeMoName@VoList.size()); for (@MoName@Vo @uncapitallizeMoName@Vo : @uncapitallizeMoName@VoList) { @uncapitallizeMoName@MoList.add(JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class)); } return @uncapitallizeMoName@Handler.batchAdd(@uncapitallizeMoName@MoList); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoList") @ApiOperationSupport(order = 3) @ApiOperation(value = "@MoName@Mo-QueryList") public Object query@MoName@MoList(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // convert Vo to Mo @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); return @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/query@MoName@MoPage") @ApiOperationSupport(order = 4) @ApiOperation(value = "@MoName@Mo-QueryListWithPaging") public Object query@MoName@MoPage(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // convert Vo to Mo @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); List<@MoName@Mo> result@MoName@MoList = @uncapitallizeMoName@Handler.query@MoName@MoList(@uncapitallizeMoName@Mo, @uncapitallizeMoName@Vo.getPageNum(), @uncapitallizeMoName@Vo.getPageSize()); return PageInfo.of(result@MoName@MoList); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "@MoName@Mo-UpdateRecord") public Object update(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { // convert Vo to Mo @MoName@Mo @uncapitallizeMoName@Mo = JSONObject.parseObject(JSONObject.toJSONString(@uncapitallizeMoName@Vo), @MoName@Mo.class); return @uncapitallizeMoName@Handler.updateSelectiveById(@uncapitallizeMoName@Mo); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/batchUpdate") @ApiOperationSupport(order = 5) @ApiOperation(value = "@MoName@Mo-BatchUpdateRecords") public Object batchUpdate(@NotEmpty @RequestBody List<@MoName@Vo> @uncapitallizeMoName@VoList) { // convert Vo to Mo List<@MoName@Mo> @uncapitallizeMoName@List = new ArrayList<>(@uncapitallizeMoName@VoList.size()); @uncapitallizeMoName@VoList.forEach(item -> @uncapitallizeMoName@List.add(JSONObject.parseObject(JSONObject.toJSONString(item), @MoName@Mo.class))); return @uncapitallizeMoName@Handler.batchUpdateSelectiveById(@uncapitallizeMoName@List); } @PostMapping(value = "@apiUrlPrefix@/@uncapitallizeMoName@Mo/delete") @ApiOperationSupport(order = 6) @ApiOperation(value = "@MoName@Mo-DeleteRecord") public Object delete(@Valid @RequestBody @MoName@Vo @uncapitallizeMoName@Vo) { return @uncapitallizeMoName@Handler.delete(@uncapitallizeMoName@Vo.getId()); } } ================================================ FILE: src/main/resources/template/EN/D8GER.txt ================================================ # The default author called 'D8ger', but it's highly recommended to modify author=D8ger #### Basic generate, support two item configs such as: #### autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo #### ATTENTION: if you config directory path, you should make sure it exists first #### WARNING: if you config error, the auto code file will put into the origin directory named 'D8AutoCode' #### THEN plugin will create Mo.java file #### AND put the file into 'com.xyz.caofancpu.d8ger.test.mo' directory #### UNDER current project source directory which include '/src/main/java' autoCreateMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mo autoCreateMapper=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper autoCreateExample=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Mapper/Example autoCreateXML=true, /src/main/resources/mybatis autoCreateDefinitionSQL=true, /doc #### Enhance generate, also support two item configs, please refer Basic generate autoCreateSwaggerMo=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Vo autoCreateHandler=true, /src/main/java/com/xyz/caofancpu/d8ger/test/handler autoCreateController=true, /src/main/java/com/xyz/caofancpu/d8ger/test/Controller #### Other normal binary config autoFormatStyle=true #### Api path prefix # apiUrlPrefix=/D8ger #### auto generating create_time and update_time SQL column definition autoDetectSQLTimeColumn=true #### if true then moMapper with annotation @Mapper, otherwise, with annotation @Repository mapperBatterThenRepository=true #### Language just for EN(English) and ZN(Chinese Simplified) # locale=ZN ================================================ FILE: src/main/resources/template/EN/DeletedServiceInterfaceTemplate.txt ================================================ package @serviceInterfacePackage@; import @moPackage@.@MoName@Mo; import java.util.List; /** * @MoName@MoService Interface Definition * * @author @d8Author@ */ public interface @MoName@Service { /** * Insert a record * * @param @uncapitallizeMoName@Mo * @return */ int add(@MoName@Mo @uncapitallizeMoName@Mo); /** * Batch insert records * * @param @uncapitallizeMoName@MoList * @return */ int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * Query list, if the paging parameter is carried, return the list after paging * * @param @uncapitallizeMoName@Mo * @param pageParams Optional paging parameters * @return */ List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams); /** * Update non-null fields by ID for a record * * @param @uncapitallizeMoName@Mo * @return */ int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo); /** * Batch Update non-nulls field by ID for multi-records * * @param @uncapitallizeMoName@MoList * @return */ int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * Delete a record by ID * * @param id * @return */ int delete(T id); } ================================================ FILE: src/main/resources/template/EN/ExampleTemplate.txt ================================================ package @moExamplePackage@; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @MoName@Mo with multi-conditions object, Example * * @author @d8Author@ */ public class @MoName@Example { protected String orderByClause; protected Integer limit; protected boolean distinct; protected List conditionCriteria; public @MoName@Example() { conditionCriteria = new ArrayList<>(); } public @MoName@Example andOrderByClause(String orderByClause) { this.orderByClause = orderByClause; return this; } public String getOrderByClause() { return orderByClause; } public @MoName@Example andLimit(Integer limit) { if (limit != null && limit > 0) { this.limit = limit; } return this; } public Integer getLimit() { return limit; } public @MoName@Example andDistinct(boolean distinct) { this.distinct = distinct; return this; } public boolean isDistinct() { return distinct; } public List getConditionCriteria() { return conditionCriteria; } public void or(Criteria criteria) { conditionCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); conditionCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (conditionCriteria.size() == 0) { conditionCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { return new Criteria(); } public void clear() { conditionCriteria.clear(); orderByClause = null; distinct = false; } protected abstract static class GeneratedCriteria { protected List criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList<>(); } public boolean isValid() { return criteria.size() > 0; } public List getAllCriteria() { return criteria; } public List getCriteria() { return criteria; } protected void addCriterion(String condition) { if (condition == null) { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); } @ExampleDefinitionMethod@ } public static class Criteria extends GeneratedCriteria { protected Criteria() { super(); } } public static class Criterion { private String condition; private Object value; private Object secondValue; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; public String getCondition() { return condition; } public Object getValue() { return value; } public Object getSecondValue() { return secondValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public String getTypeHandler() { return typeHandler; } protected Criterion(String condition) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; } protected Criterion(String condition, Object value, String typeHandler) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; if (value instanceof List) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value) { this(condition, value, null); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null); } } } ================================================ FILE: src/main/resources/template/EN/HandlerTemplate.txt ================================================ package @handlerPackage@; import @mapperPackage@.@MoName@Mapper; import @moPackage@.@MoName@Mo; import com.github.pagehelper.PageHelper; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; import javax.annotation.Resource; import java.util.List; import java.util.Objects; /** * @MoName@Handler * * @author @d8Author@ */ @Service @Slf4j public class @MoName@Handler { @Resource private @MoName@Mapper @uncapitallizeMoName@Mapper; /** * Insert a record * * @param @uncapitallizeMoName@Mo * @return */ public int add(@MoName@Mo @uncapitallizeMoName@Mo) { return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo); } /** * Batch insert records * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database * * @param @uncapitallizeMoName@MoList * @return */ public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) { return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList); } /** * Query list, if the paging parameter is carried, return the list after paging * * @param @uncapitallizeMoName@Mo * @param pageParams Optional paging parameters * @return */ public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) { if (Objects.nonNull(pageParams) && pageParams.length > 0) { int pageNum = pageParams[0]; int pageSize = pageParams.length > 1 ? pageParams[1] : 10; PageHelper.startPage(pageNum, pageSize); } return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo); } /** * Update non-null fields by ID for a single record * * @param @uncapitallizeMoName@Mo * @return */ public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) { return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo); } /** * Batch Update non-nulls field by ID for multi-records * * @param @uncapitallizeMoName@MoList * @return */ public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) { return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList); } /** * Delete a record by ID * * @param id * @return */ public int delete(T id) { return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id); } /** * Select a record by ID * * @param id * @return */ public @MoName@Mo selectByPrimaryKey(T id) { return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id); } } ================================================ FILE: src/main/resources/template/EN/MapperTemplate.txt ================================================ package @mapperPackage@; import @moExamplePackage@.@MoName@Example; import @moPackage@.@MoName@Mo; import org.apache.ibatis.annotations.Param; import @MapperAnnotationPackage@; import java.util.List; /** * @MoName@Mo Database Mapper * * @author @d8Author@ */ @MapperAnnotation@ public interface @MoName@Mapper { /** * Query list by criteria, supporting all conditions for querying a single table * * @param @uncapitallizeMoName@Example * @return */ List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example); /** * Batch update non-null fields by ID for multi-records * * @param @uncapitallizeMoName@MoList * @return */ int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * Update non-null fields by ID for a single record * * @param @uncapitallizeMoName@Mo * @param @uncapitallizeMoName@Example * @return */ int updateByExampleSelective(@Param("record") @MoName@Mo @uncapitallizeMoName@Mo, @Param("example") @MoName@Example @uncapitallizeMoName@Example); /** * Delete a single record by condition * * @param @uncapitallizeMoName@Example * @return */ int deleteByExample(@MoName@Example @uncapitallizeMoName@Example); /** * Statistical records by query conditions * * @param @uncapitallizeMoName@Example * @return Number of records */ int countByExample(@MoName@Example @uncapitallizeMoName@Example); /** * Add a single record, and set the ID for the input Mo parameter * * @param @uncapitallizeMoName@Mo * @return */ int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo); /** * Batch add records, and set the ID for the input MoList parameters * Attention: `id` | `createTime` | `updateTime` fields will be ignored cause these should according to the Database * * @param @uncapitallizeMoName@MoList * @return */ int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * @MoName@ query list * * @param @uncapitallizeMoName@Mo * @return */ List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo); /** * Query just one record by ID * * @param id * @return */ @MoName@Mo selectByPrimaryKey(T id); /** * Update non-null fields by ID for a single record * * @param @uncapitallizeMoName@Mo * @return */ int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo); /** * Delete a record by ID * * @param id * @return */ int deleteByPrimaryKey(T id); /** * Query just one record by criteria, supporting all conditions for querying a single table * * @param @uncapitallizeMoName@Example * @return */ @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example); /** * Add a single record with nonNull field, and set the ID for the input Mo parameter * * @param @uncapitallizeMoName@Mo * @return */ int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo); } ================================================ FILE: src/main/resources/template/EN/MapperXMLTemplate.txt ================================================ AND ${criterion.condition} AND ${criterion.condition} #{criterion.value} AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue} AND ${criterion.condition} #{listItem} AND ${criterion.condition} AND ${criterion.condition} #{criterion.value} AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue} AND ${criterion.condition} #{listItem} UPDATE `@mo_table_name@` @BatchUpdateNonNullFieldByID@ WHERE `id` = #{item.id} UPDATE `@mo_table_name@` @UpdateNonNullFieldByExample@ DELETE FROM `@mo_table_name@` INSERT INTO `@mo_table_name@` ( @BaseColumnList@ ) values ( @InsertField@ ) INSERT INTO `@mo_table_name@` ( @BaseColumnList@ ) VALUES @BatchInsertField@ UPDATE `@mo_table_name@` @UpdateNonNullFieldByID@ WHERE `id` = #{id} DELETE FROM `@mo_table_name@` WHERE `id` = #{id} INSERT INTO `@mo_table_name@` @NonNullColumnList@ @NonNullInsertField@ ================================================ FILE: src/main/resources/template/EN/MoTemplate.txt ================================================ package @moPackage@; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; /** * @MoName@Mo * * @author @d8Author@ */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class @MoName@Mo { @field@ } ================================================ FILE: src/main/resources/template/EN/SQLTemplate.txt ================================================ -- ---------------------------- -- D8ger-Sql-Auto-Generated -- Table structure for `@mo_table_name@` -- @author @d8Author@ -- ---------------------------- -- DROP TABLE IF EXISTS `@mo_table_name@`; CREATE TABLE `@mo_table_name@` ( @sql_column@ ) comment '@MoName@' charset = utf8mb4; ================================================ FILE: src/main/resources/template/EN/SwaggerMoTemplate.txt ================================================ package @swaggerMoPackage@; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; /** * @MoName@Mo with SwaggerApi Enhance Vo * * @author @d8Author@ */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @ApiModel public class @MoName@Vo { @swaggerField@ } ================================================ FILE: src/main/resources/template/END.txt ================================================ =========================================END========================================= Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text, which these context included will be ignored; 2.Considering compatibility separator, Multi-lines to be handled must include ',' or line break or ',' as the split keyword. 3.config example: - @@ , LEFT(default) and you can config CENTER, RIGHT too - @@ , 1(default) as 'AES' and 2 as 'PinYin' - @@ , 1 as encrypt, 2 as decrypt and 0(default) is encrypt + decrypt for complete 4.As example below, one handled what you will find like this: When algorithmType=1 && operateType = 0 MyName -->(first AES encryption) d8gerX== -->(then AES decryption) MyName When algorithmType=2 && operateType = 0 帝八哥 -->(first Fetch Chinese PinYin) dibage -->(then PinYin encryption) d8gerY== -->(last PinYin decryption) dibage Other case, just refer the two above. =========================================END========================================= The next line is very import below, do not modify anything or you'll get nothing @D8ger-END@ AName ================================================ FILE: src/main/resources/template/ExampleTemplate.txt ================================================ package @moExamplePackage@; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @MoName@Mo对应的Example单表操作对象 * * @author @d8Author@ */ public class @MoName@Example { protected String orderByClause; protected Integer limit; protected boolean distinct; protected List conditionCriteria; public @MoName@Example() { conditionCriteria = new ArrayList<>(); } public @MoName@Example andOrderByClause(String orderByClause) { this.orderByClause = orderByClause; return this; } public String getOrderByClause() { return orderByClause; } public @MoName@Example andLimit(Integer limit) { if (limit != null && limit > 0) { this.limit = limit; } return this; } public Integer getLimit() { return limit; } public @MoName@Example andDistinct(boolean distinct) { this.distinct = distinct; return this; } public boolean isDistinct() { return distinct; } public List getConditionCriteria() { return conditionCriteria; } public void or(Criteria criteria) { conditionCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); conditionCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if (conditionCriteria.size() == 0) { conditionCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { return new Criteria(); } public void clear() { conditionCriteria.clear(); orderByClause = null; distinct = false; } protected abstract static class GeneratedCriteria { protected List criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList<>(); } public boolean isValid() { return criteria.size() > 0; } public List getAllCriteria() { return criteria; } public List getCriteria() { return criteria; } protected void addCriterion(String condition) { if (condition == null) { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); } protected void addCriterion(String condition, Object value, String property) { if (value == null) { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); } protected void addCriterion(String condition, Object value1, Object value2, String property) { if (value1 == null || value2 == null) { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); } @ExampleDefinitionMethod@ } public static class Criteria extends GeneratedCriteria { protected Criteria() { super(); } } public static class Criterion { private String condition; private Object value; private Object secondValue; private boolean noValue; private boolean singleValue; private boolean betweenValue; private boolean listValue; private String typeHandler; public String getCondition() { return condition; } public Object getValue() { return value; } public Object getSecondValue() { return secondValue; } public boolean isNoValue() { return noValue; } public boolean isSingleValue() { return singleValue; } public boolean isBetweenValue() { return betweenValue; } public boolean isListValue() { return listValue; } public String getTypeHandler() { return typeHandler; } protected Criterion(String condition) { super(); this.condition = condition; this.typeHandler = null; this.noValue = true; } protected Criterion(String condition, Object value, String typeHandler) { super(); this.condition = condition; this.value = value; this.typeHandler = typeHandler; if (value instanceof List) { this.listValue = true; } else { this.singleValue = true; } } protected Criterion(String condition, Object value) { this(condition, value, null); } protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { super(); this.condition = condition; this.value = value; this.secondValue = secondValue; this.typeHandler = typeHandler; this.betweenValue = true; } protected Criterion(String condition, Object value, Object secondValue) { this(condition, value, secondValue, null); } } } ================================================ FILE: src/main/resources/template/HandlerTemplate.txt ================================================ package @handlerPackage@; import @mapperPackage@.@MoName@Mapper; import @moPackage@.@MoName@Mo; import com.github.pagehelper.PageHelper; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; import javax.annotation.Resource; import java.util.List; import java.util.Objects; /** * @MoName@Mo对应的Handler * * @author @d8Author@ */ @Service @Slf4j public class @MoName@Handler { @Resource private @MoName@Mapper @uncapitallizeMoName@Mapper; /** * 插入单条记录 * * @param @uncapitallizeMoName@Mo * @return */ public int add(@MoName@Mo @uncapitallizeMoName@Mo) { return @uncapitallizeMoName@Mapper.insertSelectiveWithId(@uncapitallizeMoName@Mo); } /** * 批量插入 * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准 * * @param @uncapitallizeMoName@MoList * @return */ public int batchAdd(List<@MoName@Mo> @uncapitallizeMoName@MoList) { return @uncapitallizeMoName@Mapper.insertBatchWithId(@uncapitallizeMoName@MoList); } /** * 查询列表, 如果携带分页参数则返回分页后的列表 * * @param @uncapitallizeMoName@Mo * @param pageParams 可选分页参数 * @return */ public List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo, Integer... pageParams) { if (Objects.nonNull(pageParams) && pageParams.length > 0) { int pageNum = pageParams[0]; int pageSize = pageParams.length > 1 ? pageParams[1] : 10; PageHelper.startPage(pageNum, pageSize); } return @uncapitallizeMoName@Mapper.query@MoName@MoList(@uncapitallizeMoName@Mo); } /** * 根据id更新非null字段 * * @param @uncapitallizeMoName@Mo * @return */ public int updateSelectiveById(@MoName@Mo @uncapitallizeMoName@Mo) { return @uncapitallizeMoName@Mapper.updateByPrimaryKeySelective(@uncapitallizeMoName@Mo); } /** * 批量根据id更新非null字段 * * @param @uncapitallizeMoName@MoList * @return */ public int batchUpdateSelectiveById(List<@MoName@Mo> @uncapitallizeMoName@MoList) { return @uncapitallizeMoName@Mapper.updateBatchByPrimaryKeySelective(@uncapitallizeMoName@MoList); } /** * 根据id物理删除 * * @param id * @return */ public int delete(T id) { return @uncapitallizeMoName@Mapper.deleteByPrimaryKey(id); } /** * 根据id查询单条记录 * * @param id * @return */ public @MoName@Mo selectByPrimaryKey(T id) { return @uncapitallizeMoName@Mapper.selectByPrimaryKey(id); } } ================================================ FILE: src/main/resources/template/MapperTemplate.txt ================================================ package @mapperPackage@; import @moExamplePackage@.@MoName@Example; import @moPackage@.@MoName@Mo; import org.apache.ibatis.annotations.Param; import @MapperAnnotationPackage@; import java.util.List; /** * @MoName@Mo对应的Mapper * * @author @d8Author@ */ @MapperAnnotation@ public interface @MoName@Mapper { /** * 根据条件查询列表 * * @param @uncapitallizeMoName@Example * @return */ List<@MoName@Mo> selectByExample(@MoName@Example @uncapitallizeMoName@Example); /** * 批量更新, 根据主键更新非null字段 * * @param @uncapitallizeMoName@MoList * @return */ int updateBatchByPrimaryKeySelective(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * 根据条件更新非null字段 * * @param @uncapitallizeMoName@Mo * @param @uncapitallizeMoName@Example * @return */ int updateByExampleSelective(@Param("record") @MoName@Mo @uncapitallizeMoName@Mo, @Param("example") @MoName@Example @uncapitallizeMoName@Example); /** * 根据条件删除记录 * * @param @uncapitallizeMoName@Example * @return */ int deleteByExample(@MoName@Example @uncapitallizeMoName@Example); /** * 根据条件统计记录 * * @param @uncapitallizeMoName@Example * @return 记录条数 */ int countByExample(@MoName@Example @uncapitallizeMoName@Example); /** * 增加单条记录, 并为入参设置ID * * @param @uncapitallizeMoName@Mo * @return */ int insertWithId(@MoName@Mo @uncapitallizeMoName@Mo); /** * 批量增加记录, 并为入参设置ID * 注意: `id` | `createTime` | `updateTime`字段将被忽略, 以数据库为准 * * @param @uncapitallizeMoName@MoList * @return */ int insertBatchWithId(List<@MoName@Mo> @uncapitallizeMoName@MoList); /** * @MoName@列表查询 * * @param @uncapitallizeMoName@Mo * @return */ List<@MoName@Mo> query@MoName@MoList(@MoName@Mo @uncapitallizeMoName@Mo); /** * 根据ID查询对象 * * @param id * @return */ @MoName@Mo selectByPrimaryKey(T id); /** * 根据主键只更新非null字段 * * @param @uncapitallizeMoName@Mo * @return */ int updateByPrimaryKeySelective(@MoName@Mo @uncapitallizeMoName@Mo); /** * 根据ID删除记录 * * @param id * @return */ int deleteByPrimaryKey(T id); /** * 根据条件查询单个对象 * * @param @uncapitallizeMoName@Example * @return */ @MoName@Mo selectOneByExample(@MoName@Example @uncapitallizeMoName@Example); /** * 增加单条非空字段记录, 并为入参设置ID * * @param @uncapitallizeMoName@Mo * @return */ int insertSelectiveWithId(@MoName@Mo @uncapitallizeMoName@Mo); } ================================================ FILE: src/main/resources/template/MapperXMLTemplate.txt ================================================ AND ${criterion.condition} AND ${criterion.condition} #{criterion.value} AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue} AND ${criterion.condition} #{listItem} AND ${criterion.condition} AND ${criterion.condition} #{criterion.value} AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue} AND ${criterion.condition} #{listItem} UPDATE `@mo_table_name@` @BatchUpdateNonNullFieldByID@ WHERE `id` = #{item.id} UPDATE `@mo_table_name@` @UpdateNonNullFieldByExample@ DELETE FROM `@mo_table_name@` INSERT INTO `@mo_table_name@` ( @BaseColumnList@ ) values ( @InsertField@ ) INSERT INTO `@mo_table_name@` ( @BaseColumnList@ ) VALUES @BatchInsertField@ UPDATE `@mo_table_name@` @UpdateNonNullFieldByID@ WHERE `id` = #{id} DELETE FROM `@mo_table_name@` WHERE `id` = #{id} INSERT INTO `@mo_table_name@` @NonNullColumnList@ @NonNullInsertField@ ================================================ FILE: src/main/resources/template/MoTemplate.txt ================================================ package @moPackage@; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; /** * @MoName@Mo * * @author @d8Author@ */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class @MoName@Mo { @field@ } ================================================ FILE: src/main/resources/template/NASA.txt ================================================ =========================================NASA========================================= Note: 1.D8ger-ALIGN(included by character '@') is the config keyword of this text, which these context included will be ignored; 2.Multi-lines to be handled must include ',' as the split keyword 3.config example: - @@ , add 'D8(' before the start of each line - @@ , add ')' after the end of each line - @@ , you can config CENTER, RIGHT too - @@ , if config SQL then it will append 'AS' alias name - @@ , special for SQL column alias camel name 4.As example below, one handled what you will find like this: first_name, --> D8(first_name) AS firstName, current_age, --> D8(current_age) AS currentAge, blog_url, --> D8(blog_url) AS blogUrl, graduated_school, --> D8(graduated_school) AS graduatedSchool, total_assets --> D8(total_assets) AS totalAssets =========================================NASA========================================= The next line is very import below, do not modify anything or you'll get nothing @D8ger-ALIGN@ first_name, current_age, blog_url, graduated_school, total_assets ================================================ FILE: src/main/resources/template/PLAN.txt ================================================ - Redis 1.Redis常用数据结构: 理论+实践 2.Redis锁: 理论+实践 3.Redis缓存、队列、雪崩、击穿、热点、布隆过滤器, LRU, 单线程IO多路复用, 了解 - RocketMQ 1.设计架构 2.部署架构 3.常见描述 4.实践问题 - Kafka 1.原理 - 工具 1.CollectionUtil, Stream底层原理, Fork/Join框架 2.DateUtil, LocalDateTime 3.WrapTreeUtil, 万能无侵入性, 平铺列表<->树形化 4.SpringBoot-Start - 算法 1.SkipList, TreeMap原理 2.Tarjan鉴环算法, 背景及代码示例 3.其他 - 项目 1.用户系统重构, 拆分SSO 2.数据报告系统, 多线程任务计算框架 3.供应链金融 4.开源插件(软件命令初始化提示集成) ================================================ FILE: src/main/resources/template/Regex.txt ================================================ 0.About details, please refer https://github.com/caofanCPU/JavaVerbalExpressions Usage, static pattern can improve performance in regex searching: public static final Pattern XXX_REGEX = Pattern.compile("...Regex string..."); 1.Whitespace Regex ((?:\s)+) 2.One or more newlines Regex (?:\\n|(?:\\r\\n))+ 3.Phone validate Regex ^1[0-9]{10}$ 4.Email validate Regex ^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$ 5.Password validate, rules: digital, uppercase, lowercase, special character >= 3 species ^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,30}$ 6.Keyword detect Regex, for example, position[may be have space]=[may be have space][may be have digital] (?:position)(?:\\s)*(?:\\=)(?:\\s)*(?:\\d)* 7.No '_' and begin with [A-Z] in word Regex ^(?!_)(?:[A-Z])[a-zA-Z0-9\\W]+$ 8.No upper case in word Regex ^(?![A-Z])[a-z0-9\\W_]+$ 9.No lower case in word Regex ^(?![a-z])[A-Z0-9\\W_]+$ 10.'www' Url detect Regex ^(?:http)(?:s)?(?:\:\/\/)(?:www\.)?(?:[^\ ]*)$ 11.IDEA Skills - 11.1 For multi-lines, how to add some same fix characters? ResearchRegex@ (?:\n|(?:\r\n))+ ReplaceString@ ,\r\n - 11.2 For multi-lines, especially for SQL batch replacing, such as: - zcy_cf, --> WE'RE(zcy_cf) AS zcy_cf, - cf_zcy --> WE'RE(cf_zcy) AS cf_zcy - note: WE'RE is just a function I.Clear the character ',' ResearchRegex@ (?:,)+ ReplaceString@ [EMPTY] II.Batch replace ResearchRegex@ ((?:\w+)+) ReplaceString@ WE'RE($0) AS $0, III.Clear the rare character ',' at the last line - 11.3 For multi-lines, especially for SQL batch reduce-replacing, such as: - WE'RE(zcy_cf) AS zcy_cf, --> zcy_cf, - WE'RE(cf_zcy) AS cf_zcy --> cf_zcy - note: WE'RE is just a function I.Handle prefix ResearchRegex@ (?:WE'RE\()+ ReplaceString@ [EMPTY] II.Handle suffix ResearchRegex@ (?:\))(?:[^\,]*) ReplaceString@ [EMPTY] III.Watch out whether need to clear the rare character ',' at the last line 12. Cron Expression 每隔5秒执行一次: */5 * * * * ? 每隔5分钟执行一次: 0 */5 * * * ? 每天23点执行一次: 0 0 23 * * ? 每天凌晨2点执行一次: 0 0 2 * * ? 每月2号凌晨4点执行一次: 0 0 2 4 * ? 每月最后一天23点执行一次: 0 0 23 L * ? 每周星期天凌晨2点实行一次: 0 0 2 ? * L 在26分、29分、33分执行一次: 0 26,29,33 * * * ? 每天的0点、22点、23点都执行一次: 0 0 0 0,22,23 * * ? ================================================ FILE: src/main/resources/template/SQLTemplate.txt ================================================ -- ---------------------------- -- D8ger-Sql-Auto-Generated -- Table structure for `@mo_table_name@` -- @author @d8Author@ -- ---------------------------- -- DROP TABLE IF EXISTS `@mo_table_name@`; CREATE TABLE `@mo_table_name@` ( @sql_column@ ) comment '@MoName@表' charset = utf8mb4; ================================================ FILE: src/main/resources/template/SwaggerMoTemplate.txt ================================================ package @swaggerMoPackage@; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; /** * @MoName@Mo对应的SwaggerApi增强Vo对象 * * @author @d8Author@ */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @ApiModel public class @MoName@Vo { @swaggerField@ } ================================================ FILE: src/main/resources/template/caofan.txt ================================================ ==== iTerm2快捷键 ==== # 高亮光标位置 cmd + / # 窗口弹出历史命令 cmd + sft + h # 删除当前行 ^ + u # 跳到行首 ^ + a # 跳到行尾 ^ + e # 删除光标所在字符(向后删除) ^ + d # 删除光标前一个字符(向前删除) ^ + h <==> delete # 交换光标最近前两个字符 ^ + t # 单词向左跳跃(回去) Esc + b ==> 自定义关联 ^ + b # 单词向右跳跃(前进) Esc + f ==> 自定义关联 ^ + f ==== vim快捷键 ==== - 非INSERT预览模式 - # 单词向右跳跃 e ==> 向右跳跃2个单词 2 + e # 单词向左跳跃 b ==> 向左跳跃2个单词 2 + b # 向下移动2行 2 + j # 向上移动2行 2 + k # 跳到第一行行首 gg # 跳到最后一行行首 G # 跳到当前行行首 O # 跳到当前行非空白字符行首 ^ # 跳到当前行行尾 $ # 删除当前字符 x # 替换当前字符(每次只能替换一个字符) r # 删除一行 dd # 从当前行开始复制并粘贴2行 2 + yy + p # 撤销上一次操作 u # 还原上一次撤销 ^ + r ==== mac OS快捷键 ==== ==== IDEA快捷键 ==== ================================================ FILE: src/main/resources/template/d8ger-util-list.txt ================================================ 🌟 autojump 🌟 dart 🌟 ffmpeg 🌟 gource 🌟 gradle 🌟 httpie 🌟 keystone 🌟 lrzsz 🌟 openssl 🌟 python@3.8 🌟 rename 🌟 sshpass 🌟 thefuck 🌟 tree 🌟 youtube🌟dl 🌟 zsh aom boost cairo capstone flac fontconfig freetype frei0r fribidi gdbm gettext giflib glew glib gmp gnutls graphite2 harfbuzz icu4c jpeg lame leptonica libass libbluray libevent libffi libidn2 libogg libplist libpng libsamplerate libsndfile libsoxr libtasn1 libtiff libunistring libvidstab libvorbis libvpx little-cms2 lzo ncurses nettle opencore-amr openjpeg openssl@1.1 opus p11-kit pcre pixman python rapidjson readline rtmpdump rubberband sdl2 sdl2_image snappy speex sqlite tesseract tesseract🌟lang theora unbound webp wget x264 x265 xvid xz ================================================ FILE: src/main/resources/template/javaShorts.txt ================================================ /apim : SwaggerModel字段属性模板 oin : 对象为null ==> Objects.isNull() onn : 对象不为null ==> Objects.nonNull() o2e : 两对象相等 ==> Objects.equals(, ) one : 两对象不相等 ==> !Objects.equals(, ) foin : 判断对象为null ==> if (Objects.isNull()) {} fonn : 判断对象不为null ==> if (Objects.nonNull()) {} fo2e : 判断两对象相等 ==> if (Objects.equals(, )) {} fone : 判断两对象不相等 ==> if (!Objects.equals(, )) {} cie : 集合为空 ==> CollectionUtil.isEmpty() cne : 集合不为空 ==> CollectionUtil.isNotEmpty() sib : 字符串为空 ==> StringUtils.isBlank() snb : 字符串不为空 ==> StringUtils.isNotBlank() fcie : 判断集合为空 ==> if (CollectionUtil.isEmpty()){} fcne : 判断集合不为空 ==> if (CollectionUtil.isNotEmpty()){} fsib : 判断字符串为空 ==> if (StringUtils.isBlank()) {} fsnb : 判断字符串不为空 ==> if (StringUtils.isNotBlank()) {} ================================================ FILE: src/main/resources/template/normal.command ================================================ # mvn编译检查详细未检查异常信息 mcf compile -Xlint:unchecked http --verify=no -v -f POST https://1.d8ger.com/uploadFile param1:=1 file@~/tmpUploadFile/xxx.png # 使用chrome的插件下载cookies.txt youtube-dl --cookies cookies.txt --proxy http://127.0.0.1:1087/ -F 网址 youtube-dl --cookies cookies.txt --proxy http://127.0.0.1:1087/ https://www.youtube.com/watch\?v\=Y4WgD0FljKU -x --audio-format mp3 # AsciiDoc转markdown brew install asciidoc brew install pandoc asciidoc -b docbook acm.adoc iconv -t utf-8 acm.xml | pandoc -f docbook -t markdown_strict --wrap=none | iconv -f utf-8 > acm.md ================================================ FILE: src/main/resources/template/ohmyd8ger.command ================================================ alias searchPID='searchPID' alias killPID='killPID' alias searchPortOccupy='searchPortOccupy' alias https-downLoadResponse='downLoadResponse' alias 'showssh=ps -ef | grep ssh' alias https-show='show' alias https-downLoadExcel='downLoadExcel' alias https-downloadD8ger='downloadD8ger' alias 'xDev=xDev' alias 'xDevNormal=xDevNormal' alias 'xDevSSO=xDevSSO' alias 'refreshDevAccount=refreshDevAccount' alias 'rh=reportHelp' alias 'logo=logo' alias 'hison=history | grep "https.*willclass\.com" | tail -n 8' alias 'tsm=teacherChangeSchool' alias 'ip=ifconfig | grep 172' alias 'arthas-start=java -jar /Users/D8GER/Desktop/CAOFAN/Arthas/arthas-boot.jar' alias 'jsh=cat ~/javaShorts.txt' alias 'fkgrep=cat ~/fk-grep.d8ger' alias 'dev=cat ~/DEV.properties' alias 'devShow=cat ~/dev.yml' alias 'phelp=cat ~/pad.command' alias 'chelp=cat ~/normal.command' alias 'arthasHelp=cat ~/althas-help.command' alias 'logSH=cat ~/project-log-help.command' ================================================ FILE: src/test/java/d8ger/D8T.java ================================================ package d8ger; import org.junit.Test; /** * This is a Test Demo showing how to execute a test case by junit. * * @author D8GER */ public class D8T { @Test public void hello() { } } ================================================ FILE: src/test/resources/MyJSON.txt ================================================