diff --git a/.gitignore b/.gitignore index c8ea253d..d3448df7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ .gradle/ *.iml +gradle.properties + ##忽略输出文件夹 out/ build/ diff --git a/README.md b/README.md index b8702079..73f4ad55 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,6 @@ > 3. 不要解压zip包,安装时直接选zip包即可。 > ``` -#### QQ群:[373603580](https://shang.qq.com/wpa/qunwpa?idkey=4d495321e527ec2ce459c0d0d6320414cd9677d92d5287df831d4e1c4ec09740) +#### QQ群1:[373603580](https://shang.qq.com/wpa/qunwpa?idkey=4d495321e527ec2ce459c0d0d6320414cd9677d92d5287df831d4e1c4ec09740) +#### QQ群2:[167490920](https://qm.qq.com/cgi-bin/qm/qr?k=r0emWZbPZIb6BqxpLM4Z4jo2mHoC0zZK&jump_from=webapi) +#### Telegram:[https://t.me/gotoeasycode](https://t.me/gotoeasycode) diff --git a/build.gradle b/build.gradle index 2ac16e85..ec91ef30 100644 --- a/build.gradle +++ b/build.gradle @@ -1,37 +1,33 @@ buildscript { repositories { - jcenter() - maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' } mavenCentral() + maven { url 'https://plugins.gradle.org/m2/' } + maven { url 'https://oss.sonatype.org/content/repositories/releases/' } } } +//2.1 插件配置 +// 这两个插件是必备 plugins { id 'java' - id 'org.jetbrains.intellij' version '0.3.5' + id 'org.jetbrains.intellij' version '0.7.3' } -//2.1 插件配置 -// 这两个插件是必备 -apply plugin: 'idea' -apply plugin: 'org.jetbrains.intellij' group 'com.sjhy' -version '1.2.2-RELEASE' +version '1.2.9-java.RELEASE' -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 +sourceCompatibility = JavaVersion.VERSION_11 +targetCompatibility = JavaVersion.VERSION_11 +compileJava.options.encoding = "UTF-8" +compileTestJava.options.encoding = "UTF-8" repositories { - jcenter() mavenCentral() } -dependencies { - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.6' - testCompile group: 'junit', name: 'junit', version: '4.12' - compileOnly "org.projectlombok:lombok:1.18.0" -} +// http://www.jetbrains.org/intellij/sdk/docs/tutorials/build_system/prerequisites.html +// https://plugins.jetbrains.com/docs/intellij/gradle-guide.html 官网gradle构建教程 intellij { // 插件名称 @@ -39,14 +35,38 @@ intellij { // 沙箱目录位置,用于保存IDEA的设置,默认在build文件下面,防止clean,放在根目录下。 sandboxDirectory = "${rootProject.rootDir}/idea-sandbox" // 开发环境运行时使用的版本 - version '2018.1.5' + version '2021.2.2' + // 社区版 +// type 'IC' + // 企业版 type 'IU' + // 各种IDEA版本去这里找 + // https://www.jetbrains.com/intellij-repository/releases // 依赖的插件 - plugins = ['DatabaseTools', 'Velocity'] + plugins = ['com.intellij.java', 'com.intellij.database'] //Disables updating since-build attribute in plugin.xml updateSinceUntilBuild false + downloadSources = true } -tasks.withType(JavaCompile) { - options.encoding = "UTF-8" +dependencies { + // jackson工具 + compile 'com.fasterxml.jackson.core:jackson-databind:2.9.6' + // guava工具 +// compile 'com.google.guava:guava:29.0-jre' + // velocity支持 +// compile 'org.apache.velocity:velocity:1.7' + // groovy支持 +// compile 'org.codehaus.groovy:groovy:3.0.2' + // beetl支持 +// compile 'com.ibeetl:beetl:3.3.0.RELEASE' + // freemarker支持 +// compile 'org.freemarker:freemarker:2.3.30' + // lombok 支持 + compileOnly 'org.projectlombok:lombok:1.18.2' + annotationProcessor 'org.projectlombok:lombok:1.18.2' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.2' + // 测试用例 + testCompile 'junit:junit:4.12' } + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 01b8bf6b..7454180f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a9ebca12..59d220e3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Tue Jul 17 15:13:01 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://downloads.gradle.org/distributions/gradle-6.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip diff --git a/settings.gradle b/settings.gradle index a88462c1..585dcfdf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'EasyCode' \ No newline at end of file +rootProject.name = 'EasyCode' diff --git a/src/main/java/com/sjhy/plugin/actions/ConfigAction.java b/src/main/java/com/sjhy/plugin/actions/ConfigAction.java index 65380e5f..0af09b03 100644 --- a/src/main/java/com/sjhy/plugin/actions/ConfigAction.java +++ b/src/main/java/com/sjhy/plugin/actions/ConfigAction.java @@ -4,6 +4,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.Project; import com.sjhy.plugin.ui.ConfigTableDialog; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -29,11 +30,11 @@ public class ConfigAction extends AnAction { * @param event 事件对象 */ @Override - public void actionPerformed(AnActionEvent event) { + public void actionPerformed(@NotNull AnActionEvent event) { Project project = event.getProject(); if (project == null) { return; } - new ConfigTableDialog(project).open(); + new ConfigTableDialog().show(); } } diff --git a/src/main/java/com/sjhy/plugin/actions/EasyCodeEntityAction.java b/src/main/java/com/sjhy/plugin/actions/EasyCodeEntityAction.java new file mode 100644 index 00000000..4ed3049a --- /dev/null +++ b/src/main/java/com/sjhy/plugin/actions/EasyCodeEntityAction.java @@ -0,0 +1,98 @@ +package com.sjhy.plugin.actions; + +import com.google.common.collect.Lists; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; +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.PsiJavaFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiModifier; +import com.sjhy.plugin.tool.CacheDataUtils; +import com.sjhy.plugin.ui.SelectSavePath; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 从Java类生成代码菜单 + * + * @author Mario Luo + */ +public class EasyCodeEntityAction extends AnAction { + + private final CacheDataUtils cacheDataUtils = CacheDataUtils.getInstance(); + + @Override + public void actionPerformed(@NotNull AnActionEvent event) { + Project project = event.getProject(); + if (project == null) { + return; + } + + // 过滤选择Java文件 + VirtualFile[] psiFiles = event.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY); + if (psiFiles == null) { + return; + } + PsiManager psiManager = PsiManager.getInstance(project); + List psiJavaFiles = Arrays.stream(psiFiles) + .map(psiManager::findFile) + .filter(f -> f instanceof PsiJavaFile) + .map(f -> (PsiJavaFile) f) + .collect(Collectors.toList()); + if (psiJavaFiles.size() == 0) { + return; + } + + // 获取选中的类 + List psiClassList = resolvePsiClassByFile(psiJavaFiles); + if (psiClassList.size() == 0) { + return; + } + + // 缓存选中值 + cacheDataUtils.setSelectPsiClass(psiClassList.get(0)); + cacheDataUtils.setPsiClassList(psiClassList); + new SelectSavePath(project, true).show(); + } + + /** + * 解析类 + */ + private List resolvePsiClassByFile(List psiJavaFiles) { + List psiClassList = Lists.newArrayListWithCapacity(psiJavaFiles.size()); + for (PsiJavaFile psiJavaFile : psiJavaFiles) { + Arrays.stream(psiJavaFile.getClasses()) + .filter(o -> o.getModifierList() != null && o.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) + .findFirst().ifPresent(psiClassList::add); + } + return psiClassList; + } + + @Override + public void update(@NotNull AnActionEvent event) { + // 不存在模块不展示:选择多个模块 + Project project = event.getData(CommonDataKeys.PROJECT); + Module module = event.getData(LangDataKeys.MODULE); + if (project == null || module == null) { + event.getPresentation().setVisible(false); + return; + } + + // 非java的文件不显示 + VirtualFile file = event.getDataContext().getData(CommonDataKeys.VIRTUAL_FILE); + if (file != null && !file.isDirectory() && !"java".equals(file.getExtension())) { + event.getPresentation().setVisible(false); + return; + } + } + + +} diff --git a/src/main/java/com/sjhy/plugin/actions/MainAction.java b/src/main/java/com/sjhy/plugin/actions/MainAction.java index e1976b5e..8ea9ceb6 100644 --- a/src/main/java/com/sjhy/plugin/actions/MainAction.java +++ b/src/main/java/com/sjhy/plugin/actions/MainAction.java @@ -1,13 +1,35 @@ package com.sjhy.plugin.actions; +import com.intellij.database.model.DasColumn; +import com.intellij.database.psi.DbTable; +import com.intellij.database.util.DasUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.Project; -import com.sjhy.plugin.service.TableInfoService; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.util.containers.JBIterable; +import com.intellij.util.ui.JBUI; +import com.sjhy.plugin.dict.GlobalDict; +import com.sjhy.plugin.entity.TypeMapper; +import com.sjhy.plugin.enums.MatchType; import com.sjhy.plugin.tool.CacheDataUtils; +import com.sjhy.plugin.tool.CompatibleUtils; +import com.sjhy.plugin.tool.CurrGroupUtils; +import com.sjhy.plugin.tool.StringUtils; import com.sjhy.plugin.ui.SelectSavePath; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import java.awt.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + /** * 代码生成菜单 * @@ -31,18 +53,110 @@ public class MainAction extends AnAction { * @param event 事件对象 */ @Override - public void actionPerformed(AnActionEvent event) { + public void actionPerformed(@NotNull AnActionEvent event) { Project project = event.getProject(); if (project == null) { return; } // 校验类型映射 - if (!TableInfoService.getInstance(project).typeValidator(CacheDataUtils.getInstance().getSelectDbTable())) { + if (!typeValidator(project, CacheDataUtils.getInstance().getSelectDbTable())) { // 没通过不打开窗口 return; } //开始处理 - new SelectSavePath(event.getProject()).open(); + new SelectSavePath(event.getProject()).show(); + } + + + /** + * 类型校验,如果存在未知类型则引导用于去条件类型 + * + * @param dbTable 原始表对象 + * @return 是否验证通过 + */ + private boolean typeValidator(Project project, DbTable dbTable) { + // 处理所有列 + JBIterable columns = DasUtil.getColumns(dbTable); + List typeMapperList = CurrGroupUtils.getCurrTypeMapperGroup().getElementList(); + + // 简单的记录报错弹窗次数,避免重复报错 + Set errorCount = new HashSet(); + + FLAG: + for (DasColumn column : columns) { + String typeName = CompatibleUtils.getDataType(column).getSpecification(); + for (TypeMapper typeMapper : typeMapperList) { + try { + if (typeMapper.getMatchType() == MatchType.ORDINARY) { + if (typeName.equalsIgnoreCase(typeMapper.getColumnType())) { + continue FLAG; + } + } else { + // 不区分大小写的正则匹配模式 + if (Pattern.compile(typeMapper.getColumnType(), Pattern.CASE_INSENSITIVE).matcher(typeName).matches()) { + continue FLAG; + } + } + } catch (PatternSyntaxException e) { + if (!errorCount.contains(typeMapper.getColumnType())) { + Messages.showWarningDialog( + "类型映射《" + typeMapper.getColumnType() + "》存在语法错误,请及时修正。报错信息:" + e.getMessage(), + GlobalDict.TITLE_INFO); + errorCount.add(typeMapper.getColumnType()); + } + } + } + // 没找到类型,提示用户选择输入类型 + new Dialog(project, typeName).showAndGet(); + } + return true; + } + + public static class Dialog extends DialogWrapper { + + private final String typeName; + + private JPanel mainPanel; + + private ComboBox comboBox; + + protected Dialog(@Nullable Project project, String typeName) { + super(project); + this.typeName = typeName; + this.initPanel(); + } + + private void initPanel() { + setTitle(GlobalDict.TITLE_INFO); + String msg = String.format("数据库类型%s,没有找到映射关系,请输入想转换的类型?", typeName); + JLabel label = new JLabel(msg); + this.mainPanel = new JPanel(new BorderLayout()); + this.mainPanel.setBorder(JBUI.Borders.empty(5, 10, 7, 10)); + mainPanel.add(label, BorderLayout.NORTH); + this.comboBox = new ComboBox(GlobalDict.DEFAULT_JAVA_TYPE_LIST); + this.comboBox.setEditable(true); + this.mainPanel.add(this.comboBox, BorderLayout.CENTER); + init(); + } + + @Override + protected @Nullable JComponent createCenterPanel() { + return this.mainPanel; + } + + @Override + protected void doOKAction() { + super.doOKAction(); + String selectedItem = (String) this.comboBox.getSelectedItem(); + if (StringUtils.isEmpty(selectedItem)) { + return; + } + TypeMapper typeMapper = new TypeMapper(); + typeMapper.setMatchType(MatchType.ORDINARY); + typeMapper.setJavaType(selectedItem); + typeMapper.setColumnType(typeName); + CurrGroupUtils.getCurrTypeMapperGroup().getElementList().add(typeMapper); + } } } diff --git a/src/main/java/com/sjhy/plugin/actions/MainActionGroup.java b/src/main/java/com/sjhy/plugin/actions/MainActionGroup.java index 04842043..0aa37ce7 100644 --- a/src/main/java/com/sjhy/plugin/actions/MainActionGroup.java +++ b/src/main/java/com/sjhy/plugin/actions/MainActionGroup.java @@ -3,7 +3,10 @@ import com.intellij.database.psi.DbTable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiElement; +import com.sjhy.plugin.dict.GlobalDict; +import com.sjhy.plugin.service.TableInfoSettingsService; import com.sjhy.plugin.tool.CacheDataUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,22 +25,7 @@ public class MainActionGroup extends ActionGroup { /** * 缓存数据工具类 */ - private CacheDataUtils cacheDataUtils = CacheDataUtils.getInstance(); - - /** - * 是否不存在子菜单 - */ - private boolean notExistsChildren; - - /** - * 是否分组按钮 - * - * @return 是否隐藏 - */ - @Override - public boolean hideIfNoVisibleChildren() { - return this.notExistsChildren; - } + private final CacheDataUtils cacheDataUtils = CacheDataUtils.getInstance(); /** @@ -61,9 +49,6 @@ public AnAction[] getChildren(@Nullable AnActionEvent event) { if (psiElement instanceof DbTable) { selectDbTable = (DbTable) psiElement; } - if (selectDbTable == null) { - return getEmptyAnAction(); - } //获取选中的所有表 PsiElement[] psiElements = event.getData(LangDataKeys.PSI_ELEMENT_ARRAY); if (psiElements == null || psiElements.length == 0) { @@ -80,11 +65,13 @@ public AnAction[] getChildren(@Nullable AnActionEvent event) { if (dbTableList.isEmpty()) { return getEmptyAnAction(); } + if (selectDbTable == null) { + selectDbTable = dbTableList.get(0); + } //保存数据到缓存 cacheDataUtils.setDbTableList(dbTableList); cacheDataUtils.setSelectDbTable(selectDbTable); - this.notExistsChildren = false; return getMenuList(); } @@ -109,8 +96,19 @@ private AnAction[] getMenuList() { configAction = new ConfigAction("Config Table"); actionManager.registerAction(configActionId, configAction); } + AnAction clearConfigAction = new AnAction("Clear Config") { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + DbTable dbTable = CacheDataUtils.getInstance().getSelectDbTable(); + if (dbTable == null) { + return; + } + TableInfoSettingsService.getInstance().removeTableInfo(dbTable); + Messages.showInfoMessage(dbTable.getName() + "表配置信息已重置成功", GlobalDict.TITLE_INFO); + } + }; // 返回所有菜单 - return new AnAction[]{mainAction, configAction}; + return new AnAction[]{mainAction, configAction, clearConfigAction}; } @@ -120,7 +118,6 @@ private AnAction[] getMenuList() { * @return 空菜单组 */ private AnAction[] getEmptyAnAction() { - this.notExistsChildren = true; return AnAction.EMPTY_ARRAY; } } diff --git a/src/main/java/com/sjhy/plugin/comm/AbstractTableModel.java b/src/main/java/com/sjhy/plugin/comm/AbstractTableModel.java deleted file mode 100644 index f88d40ee..00000000 --- a/src/main/java/com/sjhy/plugin/comm/AbstractTableModel.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.sjhy.plugin.comm; - -import com.sjhy.plugin.tool.CollectionUtil; - -import javax.swing.table.DefaultTableModel; -import java.util.List; - -/** - * 抽象的表模型 - * - * @author makejava - * @version 1.0.0 - * @since 2018年07月17日 13:10 - */ -public abstract class AbstractTableModel extends DefaultTableModel { - /** - * 数据 - */ - private List data; - - /** - * 构造方法 - */ - public AbstractTableModel() { - for (String columnName : initColumnName()) { - super.addColumn(columnName); - } - } - - /** - * 初始化方法 - * - * @param data 数据 - */ - public void init(List data) { - if (CollectionUtil.isEmpty(data)) { - return; - } - // 先移除后赋值,修复复制分组后无数据展示问题 - removeAllRow(); - this.data = data; - data.forEach(item -> super.addRow(toObj(item))); - } - - - /** - * 移除所有行 - */ - private void removeAllRow() { - int rowCount = getRowCount(); - if (rowCount> 0) { - for (int i = 0; i < rowCount; i++) { - // 只移除行数据,不移除储存数据,修复切换分组数据自动清空BUG - super.removeRow(0); - } - } - } - - /** - * 移除指定行数据 - * - * @param row 行号 - */ - @Override - public void removeRow(int row) { - super.removeRow(row); - this.data.remove(row); - } - - /** - * 设置值到指定行指定列 - * - * @param aValue 值 - * @param row 行号 - * @param column 列号 - */ - @Override - public void setValueAt(Object aValue, int row, int column) { - super.setValueAt(aValue, row, column); - T obj = data.get(row); - setVal(obj, column, aValue); - } - - /** - * 添加一行数据 - * - * @param entity 实体数据 - */ - public void addRow(T entity) { - super.addRow(toObj(entity)); - this.data.add(entity); - } - - /** - * 抽象初始化列名 - * - * @return 列名 - */ - protected abstract String[] initColumnName(); - - /** - * 实体类转数据数组 - * - * @param entity 实体类 - * @return 数据数组 - */ - protected abstract Object[] toObj(T entity); - - /** - * 设置实体类的值 - * - * @param obj 实体类 - * @param columnIndex 列索引 - * @param val 值 - */ - protected abstract void setVal(T obj, int columnIndex, Object val); -} diff --git a/src/main/java/com/sjhy/plugin/config/Settings.java b/src/main/java/com/sjhy/plugin/config/Settings.java deleted file mode 100644 index 6f052891..00000000 --- a/src/main/java/com/sjhy/plugin/config/Settings.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.sjhy.plugin.config; - -import com.intellij.ide.fileTemplates.impl.UrlUtil; -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.ExceptionUtil; -import com.intellij.util.xmlb.XmlSerializerUtil; -import com.intellij.util.xmlb.annotations.Transient; -import com.sjhy.plugin.entity.*; -import lombok.Data; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.util.*; - -/** - * 全局配置信息 - * - * @author makejava - * @version 1.0.0 - * @since 2018/07/18 09:33 - */ -@Data -@State(name = "EasyCodeSetting", storages = @Storage("easy-code-setting.xml")) -public class Settings implements PersistentStateComponent { - /** - * 默认名称 - */ - @Transient - public static final String DEFAULT_NAME = "Default"; - - /** - * 版本号 - */ - private String version; - /** - * 当前类型映射组名 - */ - private String currTypeMapperGroupName; - /** - * 类型映射组 - */ - private Map typeMapperGroupMap; - /** - * 当前模板组名 - */ - private String currTemplateGroupName; - /** - * 模板组 - */ - private Map templateGroupMap; - /** - * 当前配置表组名 - */ - private String currColumnConfigGroupName; - /** - * 配置表组 - */ - private Map columnConfigGroupMap; - /** - * 当前全局配置组名 - */ - private String currGlobalConfigGroupName; - /** - * 全局配置组 - */ - private Map globalConfigGroupMap; - /** - * 默认编码 - */ - private String encode; - /** - * 作者 - */ - private String author; - - /** - * 获取单例实例对象 - * - * @return 实例对象 - */ - public static Settings getInstance() { - return ServiceManager.getService(Settings.class); - } - - /** - * 默认构造方法 - */ - @SuppressWarnings("unused") - public Settings() { - initDefault(); - } - - /** - * 初始化默认设置 - */ - public void initDefault() { - // 版本号 - this.version = "1.2.0"; - // 默认编码 - this.encode = "UTF-8"; - // 作者名称 - this.author = "makejava"; - // 当前各项分组名称 - this.currTemplateGroupName = DEFAULT_NAME; - this.currTypeMapperGroupName = DEFAULT_NAME; - this.currColumnConfigGroupName = DEFAULT_NAME; - this.currGlobalConfigGroupName = DEFAULT_NAME; - //配置默认模板 - if (this.templateGroupMap == null) { - this.templateGroupMap = new LinkedHashMap(); - } - this.templateGroupMap.put(DEFAULT_NAME, loadTemplateGroup(DEFAULT_NAME, "entity.java", "dao.java", "service.java", "serviceImpl.java", "controller.java", "mapper.xml", "debug.json")); - this.templateGroupMap.put("MybatisPlus", loadTemplateGroup("MybatisPlus", "entity", "dao", "service", "serviceImpl", "controller")); - - //配置默认类型映射 - if (this.typeMapperGroupMap == null) { - this.typeMapperGroupMap = new LinkedHashMap(); - } - TypeMapperGroup typeMapperGroup = new TypeMapperGroup(); - List typeMapperList = new ArrayList(); - typeMapperList.add(new TypeMapper("varchar(\\(\\d+\\))?", "java.lang.String")); - typeMapperList.add(new TypeMapper("char(\\(\\d+\\))?", "java.lang.String")); - typeMapperList.add(new TypeMapper("text", "java.lang.String")); - typeMapperList.add(new TypeMapper("decimal(\\(\\d+\\))?", "java.lang.Double")); - typeMapperList.add(new TypeMapper("decimal(\\(\\d+,\\d+\\))?", "java.lang.Double")); - typeMapperList.add(new TypeMapper("integer", "java.lang.Integer")); - typeMapperList.add(new TypeMapper("int(\\(\\d+\\))?", "java.lang.Integer")); - typeMapperList.add(new TypeMapper("int4", "java.lang.Integer")); - typeMapperList.add(new TypeMapper("int8", "java.lang.Long")); - typeMapperList.add(new TypeMapper("bigint(\\(\\d+\\))?", "java.lang.Long")); - typeMapperList.add(new TypeMapper("datetime", "java.util.Date")); - typeMapperList.add(new TypeMapper("timestamp", "java.util.Date")); - typeMapperList.add(new TypeMapper("boolean", "java.lang.Boolean")); - typeMapperGroup.setName(DEFAULT_NAME); - typeMapperGroup.setElementList(typeMapperList); - typeMapperGroupMap.put(DEFAULT_NAME, typeMapperGroup); - - //初始化表配置 - if (this.columnConfigGroupMap == null) { - this.columnConfigGroupMap = new LinkedHashMap(); - } - ColumnConfigGroup columnConfigGroup = new ColumnConfigGroup(); - List columnConfigList = new ArrayList(); - columnConfigList.add(new ColumnConfig("disable", ColumnConfigType.BOOLEAN)); - columnConfigGroup.setName(DEFAULT_NAME); - columnConfigGroup.setElementList(columnConfigList); - columnConfigGroupMap.put(DEFAULT_NAME, columnConfigGroup); - - //初始化全局配置 - if (this.globalConfigGroupMap == null) { - this.globalConfigGroupMap = new LinkedHashMap(); - } - this.globalConfigGroupMap.put(DEFAULT_NAME, loadGlobalConfigGroup(DEFAULT_NAME, "init", "define", "autoImport", "mybatisSupport")); - } - - /** - * 加载模板文件 - * - * @param filePath 模板路径 - * @return 模板文件内容 - */ - private static String loadTemplate(String filePath) { - try { - return UrlUtil.loadText(Settings.class.getResource(filePath)).replace("\r", ""); - } catch (IOException e) { - ExceptionUtil.rethrow(e); - } - return ""; - } - - /** - * 加载模板组 - * - * @param groupName 组名 - * @param templateNames 模板名称 - * @return 模板组 - */ - private static TemplateGroup loadTemplateGroup(String groupName, String... templateNames) { - TemplateGroup templateGroup = new TemplateGroup(); - templateGroup.setName(groupName); - templateGroup.setElementList(new ArrayList()); - for (String templateName : templateNames) { - String path = "/template/" + groupName + "/" + templateName + ".vm"; - templateGroup.getElementList().add(new Template(templateName, loadTemplate(path))); - } - return templateGroup; - } - - /** - * 加载全局配置组 - * - * @param groupName 组名 - * @param templateNames 模板名称 - * @return 模板组 - */ - private static GlobalConfigGroup loadGlobalConfigGroup(String groupName, String... templateNames) { - GlobalConfigGroup globalConfigGroup = new GlobalConfigGroup(); - globalConfigGroup.setName(groupName); - globalConfigGroup.setElementList(new ArrayList()); - for (String templateName : templateNames) { - String path = "/globalConfig/" + groupName + "/" + templateName + ".vm"; - globalConfigGroup.getElementList().add(new GlobalConfig(templateName, loadTemplate(path))); - } - return globalConfigGroup; - } - - @Nullable - @Override - public Settings getState() { - return this; - } - - @Override - public void loadState(@NotNull Settings settings) { - // 备份初始配置 - Map templateGroupMap = this.getTemplateGroupMap(); - Map globalConfigGroupMap = this.getGlobalConfigGroupMap(); - String version = this.getVersion(); - // 覆盖初始配置 - XmlSerializerUtil.copyBean(settings, this); - - // 已经合并不再重复合并 - if (Objects.equals(settings.getVersion(), version)) { - return; - } - - // 模板备份 - TemplateGroup oldTemplateGroup = settings.getTemplateGroupMap().get(DEFAULT_NAME); - String newName = oldTemplateGroup.getName() + "Bak"; - int i = 0; - while (settings.getTemplateGroupMap().containsKey(newName)) { - newName = newName + i++; - } - oldTemplateGroup.setName(newName); - // 保存 - settings.getTemplateGroupMap().put(newName, oldTemplateGroup); - // 覆盖 - settings.getTemplateGroupMap().replace(DEFAULT_NAME, templateGroupMap.get(DEFAULT_NAME)); - - - - // 全局配置备份 - GlobalConfigGroup oldGlobalConfigGroup = settings.getGlobalConfigGroupMap().get(DEFAULT_NAME); - newName = oldGlobalConfigGroup.getName() + "Bak"; - i = 0; - while (settings.getGlobalConfigGroupMap().containsKey(newName)) { - newName = newName + i++; - } - oldGlobalConfigGroup.setName(newName); - // 保存 - settings.getGlobalConfigGroupMap().put(newName, oldGlobalConfigGroup); - // 覆盖 - settings.getGlobalConfigGroupMap().replace(DEFAULT_NAME, globalConfigGroupMap.get(DEFAULT_NAME)); - } -} diff --git a/src/main/java/com/sjhy/plugin/constants/MsgValue.java b/src/main/java/com/sjhy/plugin/constants/MsgValue.java deleted file mode 100644 index 007d9b1e..00000000 --- a/src/main/java/com/sjhy/plugin/constants/MsgValue.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.sjhy.plugin.constants; - -/** - * 消息常量值 - * - * @author makejava - * @version 1.0.0 - * @since 2018年08月02日 11:55 - */ -public class MsgValue { - /** - * 提示信息 - */ - public static final String TITLE_INFO = "EasyCode Title Info"; - - /** - * 删除分组二次确认信息 - */ - public static final String CONFIRM_DELETE_GROUP = "确认删除%s分组?"; - - /** - * 删除二次确认信息 - */ - public static final String CONFIRM_DELETE_MESSAGE = "确认删除%s?"; - - /** - * 分组名称标题 - */ - public static final String GROUP_NAME_LABEL = "分组名称:"; - - /** - * 模板名称标题 - */ - public static final String ITEM_NAME_LABEL = "新名称:"; - - /** - * 重置默认设置提示信息 - */ - public static final String RESET_DEFAULT_SETTING_MSG = "确认重置默认配置?\n重置默认配置只会还原插件自带分组配置信息,不会删除用户新增分组信息。"; -} diff --git a/src/main/java/com/sjhy/plugin/constants/StrState.java b/src/main/java/com/sjhy/plugin/constants/StrState.java index 8580182a..ae0167a3 100644 --- a/src/main/java/com/sjhy/plugin/constants/StrState.java +++ b/src/main/java/com/sjhy/plugin/constants/StrState.java @@ -12,24 +12,4 @@ public class StrState { * 相对路径常量 */ public static final String RELATIVE_PATH = "./"; - - /** - * 类型映射 - */ - public static final String TYPE_MAPPER = "typeMapper"; - - /** - * 全局配置 - */ - public static final String GLOBAL_CONFIG = "globalConfig"; - - /** - * 模板 - */ - public static final String TEMPLATE = "template"; - - /** - * 列配置 - */ - public static final String COLUMN_CONFIG = "columnConfig"; } diff --git a/src/main/java/com/sjhy/plugin/dict/GlobalDict.java b/src/main/java/com/sjhy/plugin/dict/GlobalDict.java new file mode 100644 index 00000000..7c43f57d --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dict/GlobalDict.java @@ -0,0 +1,51 @@ +package com.sjhy.plugin.dict; + +/** + * 全局字典 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月07日 11:41 + */ +public interface GlobalDict { + /** + * 提示信息 + */ + String TITLE_INFO = "EasyCode Title Info"; + /** + * 版本号 + */ + String VERSION = "1.2.9"; + /** + * 作者名称 + */ + String AUTHOR = "makejava"; + /** + * 默认分组名称 + */ + String DEFAULT_GROUP_NAME = "Default"; + /** + * 默认的Java类型列表 + */ + String[] DEFAULT_JAVA_TYPE_LIST = new String[]{ + "java.lang.String", + "java.lang.Integer", + "java.lang.Long", + "java.util.Boolean", + "java.util.Date", + "java.time.LocalDateTime", + "java.time.LocalDate", + "java.time.LocalTime", + "java.lang.Short", + "java.lang.Byte", + "java.lang.Character", + "java.math.BigDecimal", + "java.math.BigInteger", + "java.lang.Double", + "java.lang.Float", + "java.lang.String[]", + "java.util.List", + "java.util.Set", + "java.util.Map", + }; +} diff --git a/src/main/java/com/sjhy/plugin/dto/ColumnInfoDTO.java b/src/main/java/com/sjhy/plugin/dto/ColumnInfoDTO.java new file mode 100644 index 00000000..494d99e6 --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dto/ColumnInfoDTO.java @@ -0,0 +1,79 @@ +package com.sjhy.plugin.dto; + +import com.intellij.database.model.DasColumn; +import com.intellij.psi.PsiField; +import com.sjhy.plugin.entity.TypeMapper; +import com.sjhy.plugin.enums.MatchType; +import com.sjhy.plugin.tool.CompatibleUtils; +import com.sjhy.plugin.tool.CurrGroupUtils; +import com.sjhy.plugin.tool.DocCommentUtils; +import com.sjhy.plugin.tool.NameUtils; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.regex.Pattern; + +/** + * 列信息传输对象 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月14日 17:29 + */ +@Data +@NoArgsConstructor +public class ColumnInfoDTO { + + public ColumnInfoDTO(PsiField field) { + this.name = field.getName(); + this.comment = DocCommentUtils.getComment(field.getDocComment()); + this.type = field.getType().getCanonicalText(); + this.custom = false; + this.ext = "{}"; + } + + public ColumnInfoDTO(DasColumn column) { + this.name = NameUtils.getInstance().getJavaName(column.getName()); + this.comment = column.getComment(); + this.type = getJavaType(CompatibleUtils.getDataType(column).toString()); + this.custom = false; + this.ext = "{}"; + } + + private String getJavaType(String dbType) { + for (TypeMapper typeMapper : CurrGroupUtils.getCurrTypeMapperGroup().getElementList()) { + if (typeMapper.getMatchType() == MatchType.ORDINARY) { + if (dbType.equalsIgnoreCase(typeMapper.getColumnType())) { + return typeMapper.getJavaType(); + } + } else { + // 不区分大小写的正则匹配模式 + if (Pattern.compile(typeMapper.getColumnType(), Pattern.CASE_INSENSITIVE).matcher(dbType).matches()) { + return typeMapper.getJavaType(); + } + } + } + return "java.lang.Object"; + } + + /** + * 名称 + */ + private String name; + /** + * 注释 + */ + private String comment; + /** + * 全类型 + */ + private String type; + /** + * 标记是否为自定义附加列 + */ + private Boolean custom; + /** + * 扩展数据(JSON字符串) + */ + private String ext; +} diff --git a/src/main/java/com/sjhy/plugin/dto/GenerateOptions.java b/src/main/java/com/sjhy/plugin/dto/GenerateOptions.java new file mode 100644 index 00000000..1f1d5b4b --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dto/GenerateOptions.java @@ -0,0 +1,36 @@ +package com.sjhy.plugin.dto; + +import lombok.Builder; +import lombok.Data; + +/** + * 生成选项 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月17日 09:08 + */ +@Data +@Builder +public class GenerateOptions { + /** + * 实体类模式 + */ + private Boolean entityModel; + /** + * 统一配置 + */ + private Boolean unifiedConfig; + /** + * 重新格式化代码 + */ + private Boolean reFormat; + /** + * 提示选是 + */ + private Boolean titleSure; + /** + * 提示选否 + */ + private Boolean titleRefuse; +} diff --git a/src/main/java/com/sjhy/plugin/dto/SettingsStorageDTO.java b/src/main/java/com/sjhy/plugin/dto/SettingsStorageDTO.java new file mode 100644 index 00000000..a786e1bc --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dto/SettingsStorageDTO.java @@ -0,0 +1,213 @@ +package com.sjhy.plugin.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.intellij.ide.fileTemplates.impl.UrlUtil; +import com.intellij.util.ExceptionUtil; +import com.sjhy.plugin.dict.GlobalDict; +import com.sjhy.plugin.entity.*; +import com.sjhy.plugin.enums.ColumnConfigType; +import com.sjhy.plugin.tool.CollectionUtil; +import com.sjhy.plugin.tool.JSON; +import com.sjhy.plugin.tool.StringUtils; +import lombok.Data; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * 设置储存传输对象 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月07日 11:35 + */ +@Data +public class SettingsStorageDTO { + /** + * 返回默认值,不使用静态常量,防止默认值别篡改 + * + * @return 储存对象 + */ + public static SettingsStorageDTO defaultVal() { + try { + // 从配置文件中加载配置 + String json = UrlUtil.loadText(SettingsStorageDTO.class.getResource("/defaultConfig.json")); + return JSON.parse(json, SettingsStorageDTO.class); + } catch (Exception e) { + ExceptionUtil.rethrow(e); + } + // 配置文件加载失败,直接创建配置 + SettingsStorageDTO storage = new SettingsStorageDTO(); + storage.author = GlobalDict.AUTHOR; + storage.version = GlobalDict.VERSION; + storage.userSecure = ""; + // 默认分组名称 + storage.currTypeMapperGroupName = GlobalDict.DEFAULT_GROUP_NAME; + storage.currTemplateGroupName = GlobalDict.DEFAULT_GROUP_NAME; + storage.currColumnConfigGroupName = GlobalDict.DEFAULT_GROUP_NAME; + storage.currGlobalConfigGroupName = GlobalDict.DEFAULT_GROUP_NAME; + // 默认配置信息 + storage.typeMapperGroupMap = new HashMap(16); + TypeMapperGroup typeMapperGroup = new TypeMapperGroup(); + typeMapperGroup.setName(GlobalDict.DEFAULT_GROUP_NAME); + typeMapperGroup.setElementList(Arrays.asList(new TypeMapper("varchar", "java.lang.String"), new TypeMapper("varchar\\(\\)", "java.lang.String"))); + storage.typeMapperGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, typeMapperGroup); + + ColumnConfigGroup columnConfigGroup = new ColumnConfigGroup(); + columnConfigGroup.setName(GlobalDict.DEFAULT_GROUP_NAME); + columnConfigGroup.setElementList(Arrays.asList(new ColumnConfig("disable", ColumnConfigType.BOOLEAN), new ColumnConfig("operator", ColumnConfigType.SELECT, "insert,update,delete,select"))); + storage.columnConfigGroupMap = new HashMap(16); + storage.columnConfigGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, columnConfigGroup); + + TemplateGroup templateGroup = new TemplateGroup(); + templateGroup.setName(GlobalDict.DEFAULT_GROUP_NAME); + templateGroup.setElementList(Arrays.asList(new Template("demo", "template"), new Template("entity.java", "public"))); + storage.templateGroupMap = new HashMap(16); + storage.templateGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, templateGroup); + + GlobalConfigGroup globalConfigGroup = new GlobalConfigGroup(); + globalConfigGroup.setName(GlobalDict.DEFAULT_GROUP_NAME); + globalConfigGroup.setElementList(Arrays.asList(new GlobalConfig("test", "abc"), new GlobalConfig("demo", "value"))); + storage.globalConfigGroupMap = new HashMap(16); + storage.globalConfigGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, globalConfigGroup); + return storage; + } + + /** + * 重置为默认值 + */ + public void resetDefaultVal() { + SettingsStorageDTO defaultVal = defaultVal(); + this.setAuthor(defaultVal.getAuthor()); + this.setVersion(defaultVal.getVersion()); + this.setCurrColumnConfigGroupName(GlobalDict.DEFAULT_GROUP_NAME); + this.getColumnConfigGroupMap().put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getColumnConfigGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + this.setCurrTemplateGroupName(GlobalDict.DEFAULT_GROUP_NAME); + this.getTemplateGroupMap().put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getTemplateGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + this.setCurrGlobalConfigGroupName(GlobalDict.DEFAULT_GROUP_NAME); + this.getGlobalConfigGroupMap().put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getGlobalConfigGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + this.setCurrTypeMapperGroupName(GlobalDict.DEFAULT_GROUP_NAME); + this.getTypeMapperGroupMap().put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getTypeMapperGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + // 恢复已被删除的分组 + defaultVal.getTemplateGroupMap().forEach((k, v) -> { + if (!getTemplateGroupMap().containsKey(k)) { + getTemplateGroupMap().put(k,v ); + } + }); + defaultVal.getGlobalConfigGroupMap().forEach((k, v) -> { + if (!getGlobalConfigGroupMap().containsKey(k)) { + getGlobalConfigGroupMap().put(k,v ); + } + }); + defaultVal.getColumnConfigGroupMap().forEach((k, v) -> { + if (!getColumnConfigGroupMap().containsKey(k)) { + getColumnConfigGroupMap().put(k,v ); + } + }); + defaultVal.getTypeMapperGroupMap().forEach((k, v) -> { + if (!getTypeMapperGroupMap().containsKey(k)) { + getTypeMapperGroupMap().put(k,v ); + } + }); + } + + /** + * 作者 + */ + private String author; + /** + * 版本号 + */ + private String version; + /** + * 用户密钥 + */ + private String userSecure; + /** + * 当前类型映射组名 + */ + private String currTypeMapperGroupName; + /** + * 类型映射组 + */ + @JsonProperty("typeMapper") + private Map typeMapperGroupMap; + /** + * 当前模板组名 + */ + private String currTemplateGroupName; + /** + * 模板组 + */ + @JsonProperty("template") + private Map templateGroupMap; + /** + * 当前配置表组名 + */ + private String currColumnConfigGroupName; + /** + * 配置表组 + */ + @JsonProperty("columnConfig") + private Map columnConfigGroupMap; + /** + * 当前全局配置组名 + */ + private String currGlobalConfigGroupName; + /** + * 全局配置组 + */ + @JsonProperty("globalConfig") + private Map globalConfigGroupMap; + + public void fillDefaultVal() { + SettingsStorageDTO defaultVal = defaultVal(); + if (CollectionUtil.isEmpty(this.typeMapperGroupMap)) { + this.typeMapperGroupMap = defaultVal.getTypeMapperGroupMap(); + } + if (!this.typeMapperGroupMap.containsKey(GlobalDict.DEFAULT_GROUP_NAME)) { + this.typeMapperGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getTypeMapperGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + } + if (StringUtils.isEmpty(this.currTypeMapperGroupName)) { + this.setCurrTypeMapperGroupName(GlobalDict.DEFAULT_GROUP_NAME); + } + + + if (CollectionUtil.isEmpty(this.templateGroupMap)) { + this.templateGroupMap = defaultVal.getTemplateGroupMap(); + } + if (!this.templateGroupMap.containsKey(GlobalDict.DEFAULT_GROUP_NAME)) { + this.templateGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getTemplateGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + } + if (StringUtils.isEmpty(this.currTemplateGroupName)) { + this.setCurrTemplateGroupName(GlobalDict.DEFAULT_GROUP_NAME); + } + + + if (CollectionUtil.isEmpty(this.columnConfigGroupMap)) { + this.columnConfigGroupMap = defaultVal.getColumnConfigGroupMap(); + } + if (!this.columnConfigGroupMap.containsKey(GlobalDict.DEFAULT_GROUP_NAME)) { + this.columnConfigGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getColumnConfigGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + } + if (StringUtils.isEmpty(this.currColumnConfigGroupName)) { + this.setCurrColumnConfigGroupName(GlobalDict.DEFAULT_GROUP_NAME); + } + + + if (CollectionUtil.isEmpty(this.globalConfigGroupMap)) { + this.globalConfigGroupMap = defaultVal.getGlobalConfigGroupMap(); + } + if (!this.globalConfigGroupMap.containsKey(GlobalDict.DEFAULT_GROUP_NAME)) { + this.globalConfigGroupMap.put(GlobalDict.DEFAULT_GROUP_NAME, defaultVal.getGlobalConfigGroupMap().get(GlobalDict.DEFAULT_GROUP_NAME)); + } + if (StringUtils.isEmpty(this.currGlobalConfigGroupName)) { + this.setCurrGlobalConfigGroupName(GlobalDict.DEFAULT_GROUP_NAME); + } + + if (StringUtils.isEmpty(this.version)) { + this.setVersion(defaultVal.getVersion()); + } + } +} diff --git a/src/main/java/com/sjhy/plugin/dto/TableInfoDTO.java b/src/main/java/com/sjhy/plugin/dto/TableInfoDTO.java new file mode 100644 index 00000000..ec77edeb --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dto/TableInfoDTO.java @@ -0,0 +1,287 @@ +package com.sjhy.plugin.dto; + +import com.intellij.database.model.DasColumn; +import com.intellij.database.psi.DbTable; +import com.intellij.database.util.DasUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; +import com.intellij.util.containers.JBIterable; +import com.sjhy.plugin.entity.ColumnInfo; +import com.sjhy.plugin.entity.TableInfo; +import com.sjhy.plugin.tool.*; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 表格信息传输对象 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月14日 17:28 + */ +@Data +@NoArgsConstructor +public class TableInfoDTO { + + public TableInfoDTO(TableInfoDTO dto, DbTable dbTable) { + this(dbTable); + merge(dto, this); + } + + public TableInfoDTO(TableInfoDTO dto, PsiClass psiClass) { + this(psiClass); + merge(dto, this); + } + + private TableInfoDTO(PsiClass psiClass) { + this.name = psiClass.getName(); + this.preName = ""; + this.comment = DocCommentUtils.getComment(psiClass.getDocComment()); + this.templateGroupName = ""; + this.savePackageName = ""; + this.savePath = ""; + this.saveModelName = ""; + this.fullColumn = new ArrayList(); + for (PsiField field : psiClass.getAllFields()) { + this.fullColumn.add(new ColumnInfoDTO(field)); + } + } + + private TableInfoDTO(DbTable dbTable) { + this.name = NameUtils.getInstance().getClassName(dbTable.getName()); + this.preName = ""; + this.comment = dbTable.getComment(); + this.templateGroupName = ""; + this.savePackageName = ""; + this.savePath = ""; + this.saveModelName = ""; + this.fullColumn = new ArrayList(); + // 处理所有列 + JBIterable columns = DasUtil.getColumns(dbTable); + for (DasColumn column : columns) { + this.fullColumn.add(new ColumnInfoDTO(column)); + } + } + + private static void merge(TableInfoDTO oldData, TableInfoDTO newData) { + if (oldData == null || CollectionUtil.isEmpty(oldData.getFullColumn())) { + return; + } + if (!StringUtils.isEmpty(oldData.getPreName())) { + newData.preName = oldData.getPreName(); + } + if (!StringUtils.isEmpty(oldData.getTemplateGroupName())) { + newData.templateGroupName = oldData.getTemplateGroupName(); + } + if (!StringUtils.isEmpty(oldData.getSavePackageName())) { + newData.savePackageName = oldData.getSavePackageName(); + } + if (!StringUtils.isEmpty(oldData.getSavePath())) { + newData.savePath = oldData.getSavePath(); + } + if (!StringUtils.isEmpty(oldData.getSaveModelName())) { + newData.saveModelName = oldData.getSaveModelName(); + } + List allNewColumnNames = newData.getFullColumn().stream().map(ColumnInfoDTO::getName).collect(Collectors.toList()); + // 列出旧的顺序,并删除已经不存在的列,不包括自定义列 + List oldSequenceColumn = oldData.getFullColumn().stream() + .filter(item -> allNewColumnNames.contains(item.getName()) || Boolean.TRUE.equals(item.getCustom())) + .collect(Collectors.toList()); + // 尽可能的保留原始顺序(把自定义列按原始位置插入) + Map nameMap = new HashMap(oldSequenceColumn.size()); + for (int i = 0; i < oldSequenceColumn.size(); i++) { + ColumnInfoDTO columnInfo = oldSequenceColumn.get(i); + if (columnInfo.getCustom()) { + // 如果原本是自定义列,现在变成了数据库列,则忽略调原本的自定义列 + if (allNewColumnNames.contains(columnInfo.getName())) { + continue; + } + // 获取当前自定义列的前一个名称 + String beforeName = ""; + if (i> 0) { + beforeName = oldSequenceColumn.get(i - 1).getName(); + } + nameMap.put(beforeName, columnInfo.getName()); + } + } + // 将自定义列按顺序插入到新表中 + nameMap.forEach((k, v) -> { + if (StringUtils.isEmpty(k)) { + allNewColumnNames.add(0, v); + } else { + for (int i = 0; i < allNewColumnNames.size(); i++) { + if (allNewColumnNames.get(i).equals(k)) { + allNewColumnNames.add(i + 1, v); + return; + } + } + } + }); + // 按顺序依次重写数据 + Map oldColumnMap = oldData.getFullColumn().stream().collect(Collectors.toMap(ColumnInfoDTO::getName, v -> v)); + Map newColumnMap = newData.getFullColumn().stream().collect(Collectors.toMap(ColumnInfoDTO::getName, v -> v)); + List tmpList = new ArrayList(); + for (String name : allNewColumnNames) { + ColumnInfoDTO newColumnInfo = newColumnMap.get(name); + if (newColumnInfo == null) { + newColumnInfo = oldColumnMap.get(name); + if (newColumnInfo == null) { + throw new NullPointerException("找不到列信息"); + } + tmpList.add(newColumnInfo); + continue; + } + ColumnInfoDTO oldColumnInfo = oldColumnMap.get(name); + if (oldColumnInfo == null) { + tmpList.add(newColumnInfo); + continue; + } + // 需要进行合并操作 + newColumnInfo.setExt(oldColumnInfo.getExt()); + if (StringUtils.isEmpty(newColumnInfo.getComment())) { + newColumnInfo.setComment(oldColumnInfo.getComment()); + } + tmpList.add(newColumnInfo); + } + // list数据替换 + newData.getFullColumn().clear(); + newData.getFullColumn().addAll(tmpList); + } + + + /** + * 表名(首字母大写) + */ + private String name; + /** + * 表名前缀 + */ + private String preName; + /** + * 注释 + */ + private String comment; + /** + * 模板组名称 + */ + private String templateGroupName; + /** + * 所有列 + */ + private List fullColumn; + /** + * 保存的包名称 + */ + private String savePackageName; + /** + * 保存路径 + */ + private String savePath; + /** + * 保存的model名称 + */ + private String saveModelName; + + public TableInfo toTableInfo(PsiClass psiClass) { + TableInfo tableInfo = new TableInfo(); + tableInfo.setPsiClassObj(psiClass); + tableInfo.setName(this.getName()); + tableInfo.setPreName(this.getPreName()); + tableInfo.setTemplateGroupName(this.getTemplateGroupName()); + tableInfo.setSavePackageName(this.getSavePackageName()); + tableInfo.setSavePath(this.getSavePath()); + tableInfo.setComment(this.getComment()); + tableInfo.setSaveModelName(this.getSaveModelName()); + tableInfo.setFullColumn(new ArrayList()); + tableInfo.setPkColumn(new ArrayList()); + tableInfo.setOtherColumn(new ArrayList()); + for (PsiField field : psiClass.getAllFields()) { + if (PsiClassGenerateUtils.isSkipField(field)) { + continue; + } + ColumnInfo columnInfo = new ColumnInfo(); + columnInfo.setName(field.getName()); + columnInfo.setShortType(field.getType().getPresentableText()); + columnInfo.setType(field.getType().getCanonicalText()); + columnInfo.setComment(DocCommentUtils.getComment(field.getDocComment())); + columnInfo.setCustom(false); + tableInfo.getFullColumn().add(columnInfo); + if (PsiClassGenerateUtils.isPkField(field)) { + tableInfo.getPkColumn().add(columnInfo); + } else { + tableInfo.getOtherColumn().add(columnInfo); + } + } + return tableInfo; + } + + @SuppressWarnings("unchecked") + public TableInfo toTableInfo(DbTable dbTable) { + TableInfo tableInfo = new TableInfo(); + tableInfo.setObj(dbTable); + tableInfo.setName(this.getName()); + tableInfo.setPreName(this.getPreName()); + tableInfo.setTemplateGroupName(this.getTemplateGroupName()); + tableInfo.setSavePackageName(this.getSavePackageName()); + tableInfo.setSavePath(this.getSavePath()); + tableInfo.setComment(this.getComment()); + tableInfo.setSaveModelName(this.getSaveModelName()); + tableInfo.setFullColumn(new ArrayList()); + tableInfo.setPkColumn(new ArrayList()); + tableInfo.setOtherColumn(new ArrayList()); + // 列 + JBIterable columns = DasUtil.getColumns(dbTable); + Map nameToObj = new HashMap(columns.size()); + for (DasColumn column : columns) { + nameToObj.put(NameUtils.getInstance().getJavaName(column.getName()), column); + } + for (ColumnInfoDTO dto : this.getFullColumn()) { + ColumnInfo columnInfo = new ColumnInfo(); + columnInfo.setObj(nameToObj.get(dto.getName())); + columnInfo.setName(dto.getName()); + columnInfo.setType(dto.getType()); + // 最后一节为短类型 + String[] split = dto.getType().split("\\."); + columnInfo.setShortType(split[split.length - 1]); + columnInfo.setComment(dto.getComment()); + columnInfo.setCustom(dto.getCustom()); + columnInfo.setExt(JSON.parse(dto.getExt(), HashMap.class)); + tableInfo.getFullColumn().add(columnInfo); + if (columnInfo.getObj() != null && DasUtil.isPrimary(columnInfo.getObj())) { + tableInfo.getPkColumn().add(columnInfo); + } else { + tableInfo.getOtherColumn().add(columnInfo); + } + } + return tableInfo; + } + + public static TableInfoDTO valueOf(TableInfo tableInfo) { + TableInfoDTO dto = new TableInfoDTO(); + dto.setName(tableInfo.getName()); + dto.setTemplateGroupName(tableInfo.getTemplateGroupName()); + dto.setSavePath(tableInfo.getSavePath()); + dto.setPreName(tableInfo.getPreName()); + dto.setComment(tableInfo.getComment()); + dto.setSavePackageName(tableInfo.getSavePackageName()); + dto.setSaveModelName(tableInfo.getSaveModelName()); + dto.setFullColumn(new ArrayList()); + // 处理列 + for (ColumnInfo columnInfo : tableInfo.getFullColumn()) { + ColumnInfoDTO columnInfoDTO = new ColumnInfoDTO(); + columnInfoDTO.setName(columnInfo.getName()); + columnInfoDTO.setType(columnInfo.getType()); + columnInfoDTO.setExt(JSON.toJson(columnInfo.getExt())); + columnInfoDTO.setCustom(columnInfo.getCustom()); + columnInfoDTO.setComment(columnInfo.getComment()); + dto.getFullColumn().add(columnInfoDTO); + } + return dto; + } +} diff --git a/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java b/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java new file mode 100644 index 00000000..4e4f94fc --- /dev/null +++ b/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java @@ -0,0 +1,150 @@ +package com.sjhy.plugin.dto; + +import com.intellij.database.model.DasNamespace; +import com.intellij.database.psi.DbElement; +import com.intellij.database.psi.DbTable; +import com.intellij.openapi.ui.Messages; +import com.intellij.psi.PsiClass; +import com.sjhy.plugin.dict.GlobalDict; +import com.sjhy.plugin.entity.TableInfo; +import com.sjhy.plugin.tool.JSON; +import com.sjhy.plugin.tool.ReflectionUtils; +import com.sjhy.plugin.tool.StringUtils; +import lombok.Data; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Base64; +import java.util.Map; +import java.util.TreeMap; + +/** + * 表格信息设置传输对象 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月14日 17:40 + */ +@Data +public class TableInfoSettingsDTO { + private Map tableInfoMap; + + public TableInfoSettingsDTO() { + this.tableInfoMap = new TreeMap(); + } + + private String generateKey(DbTable dbTable) { + // 递归添加3层名称作为key,第一层为表名、第二层为名命空间名称、第三层为数据库名 + StringBuilder builder = new StringBuilder(); + DbElement element = dbTable; + for (int i = 0; i < 3; i++) { + String name = element.getName(); + if (builder.length()> 0) { + // 添加分割符 + builder.insert(0, "."); + } + builder.insert(0, name); + try { + Method method = ReflectionUtils.getDeclaredMethod(element.getClass(), "getParent"); + if (method == null) { + break; + } + element = (DbElement) method.invoke(element); + } catch (IllegalAccessException | InvocationTargetException e) { + break; + } + // 未必所有的数据库都是存在三层,例如MySQL就只有两层。如果上次层不是Namespace,则不再继续获取 + if (!(element instanceof DasNamespace)) { + break; + } + } + return builder.toString(); + } + + private String generateKey(PsiClass psiClass) { + return psiClass.getQualifiedName(); + } + /** + * 读表信息 + * + * @param psiClass psi类 + * @return {@link TableInfo} + */ + @SuppressWarnings("Duplicates") + public TableInfo readTableInfo(PsiClass psiClass) { + String key = generateKey(psiClass); + TableInfoDTO dto = decode(this.tableInfoMap.get(key)); + dto = new TableInfoDTO(dto, psiClass); + this.tableInfoMap.put(key, encode(dto)); + return dto.toTableInfo(psiClass); + } + + /** + * 读表信息 + * + * @param dbTable 数据库表 + * @return {@link TableInfo} + */ + @SuppressWarnings("Duplicates") + public TableInfo readTableInfo(DbTable dbTable) { + String key = generateKey(dbTable); + TableInfoDTO dto = decode(this.tableInfoMap.get(key)); + // 表可能新增了字段,需要重新合并保存 + dto = new TableInfoDTO(dto, dbTable); + this.tableInfoMap.put(key, encode(dto)); + return dto.toTableInfo(dbTable); + } + + /** + * 保存表信息 + * + * @param tableInfo 表信息 + */ + public void saveTableInfo(TableInfo tableInfo) { + if (tableInfo == null) { + return; + } + DbTable dbTable = tableInfo.getObj(); + String key; + if (dbTable != null) { + key = generateKey(dbTable); + } else if (tableInfo.getPsiClassObj() != null) { + key = generateKey((PsiClass) tableInfo.getPsiClassObj()); + } else { + Messages.showInfoMessage(tableInfo.getName() + "表配置信息保存失败", GlobalDict.TITLE_INFO); + return; + } + this.tableInfoMap.put(key, encode(TableInfoDTO.valueOf(tableInfo))); + } + + /** + * 重置表信息 + * + * @param dbTable 数据库表 + */ + public void resetTableInfo(DbTable dbTable) { + String key = generateKey(dbTable); + this.tableInfoMap.put(key, encode(new TableInfoDTO(null, dbTable))); + } + + /** + * 删除表信息 + * + * @param dbTable 数据库表 + */ + public void removeTableInfo(DbTable dbTable) { + String key = generateKey(dbTable); + this.tableInfoMap.remove(key); + } + + private static String encode(TableInfoDTO tableInfo) { + return Base64.getEncoder().encodeToString(JSON.toJson(tableInfo).getBytes()); + } + + private static TableInfoDTO decode(String base64) { + if (StringUtils.isEmpty(base64)) { + return null; + } + return JSON.parse(new String(Base64.getDecoder().decode(base64)), TableInfoDTO.class); + } +} diff --git a/src/main/java/com/sjhy/plugin/entity/AbstractEditorItem.java b/src/main/java/com/sjhy/plugin/entity/AbstractEditorItem.java new file mode 100644 index 00000000..4f2e9990 --- /dev/null +++ b/src/main/java/com/sjhy/plugin/entity/AbstractEditorItem.java @@ -0,0 +1,38 @@ +package com.sjhy.plugin.entity; + +/** + * 抽象的可编辑元素 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月11日 13:45 + */ +public interface AbstractEditorItem extends AbstractItem { + /** + * 更改文件名称 + * + * @param name 文件名称 + */ + void changeFileName(String name); + + /** + * 获取文件名称 + * + * @return {@link String} + */ + String fileName(); + + /** + * 改变文件内容 + * + * @param content 内容 + */ + void changeFileContent(String content); + + /** + * 获取文件内容 + * + * @return {@link String} + */ + String fileContent(); +} diff --git a/src/main/java/com/sjhy/plugin/entity/AbstractGroup.java b/src/main/java/com/sjhy/plugin/entity/AbstractGroup.java index 8858c3c6..0cc93a50 100644 --- a/src/main/java/com/sjhy/plugin/entity/AbstractGroup.java +++ b/src/main/java/com/sjhy/plugin/entity/AbstractGroup.java @@ -1,5 +1,9 @@ package com.sjhy.plugin.entity; +import com.sjhy.plugin.factory.AbstractItemFactory; +import com.sjhy.plugin.tool.CloneUtils; +import com.sjhy.plugin.tool.ReflectionUtils; + import java.util.List; /** @@ -9,7 +13,7 @@ * @version 1.0.0 * @since 2018年07月17日 13:10 */ -public interface AbstractGroup { +public interface AbstractGroup> { /** * 获取分组名称 * @@ -37,4 +41,25 @@ public interface AbstractGroup { * @param elementList 元素集合 */ void setElementList(List elementList); + + /** + * 默认子元素 + * + * @return {@link E} + */ + @SuppressWarnings("unchecked") + default E defaultChild() { + Class cls = (Class) ReflectionUtils.getGenericClass(this, 1); + return AbstractItemFactory.createDefaultVal(cls); + } + + /** + * 克隆对象 + * + * @return {@link T} + */ + @SuppressWarnings("unchecked") + default T cloneObj() { + return (T) CloneUtils.cloneByJson(this); + } } diff --git a/src/main/java/com/sjhy/plugin/entity/AbstractItem.java b/src/main/java/com/sjhy/plugin/entity/AbstractItem.java new file mode 100644 index 00000000..310b2cf0 --- /dev/null +++ b/src/main/java/com/sjhy/plugin/entity/AbstractItem.java @@ -0,0 +1,29 @@ +package com.sjhy.plugin.entity; + +import com.sjhy.plugin.tool.CloneUtils; + +/** + * 抽象的项 + * + * @author makejava + * @version 1.0.0 + * @date 2021年08月11日 09:47 + */ +public interface AbstractItem { + /** + * 默认值 + * + * @return {@link T} + */ + T defaultVal(); + + /** + * 克隆对象 + * + * @return 克隆结果 + */ + @SuppressWarnings("unchecked") + default T cloneObj() { + return (T) CloneUtils.cloneByJson(this); + } +} diff --git a/src/main/java/com/sjhy/plugin/entity/Callback.java b/src/main/java/com/sjhy/plugin/entity/Callback.java index 230df454..25cbaea6 100644 --- a/src/main/java/com/sjhy/plugin/entity/Callback.java +++ b/src/main/java/com/sjhy/plugin/entity/Callback.java @@ -11,6 +11,20 @@ */ @Data public class Callback { + /** + * 文件名 + */ private String fileName; + /** + * 保存路径 + */ private String savePath; + /** + * 是否重新格式化代码 + */ + private Boolean reformat; + /** + * 是否写入文件,部分模块不需要写入文件。例如debug.json模板 + */ + private Boolean writeFile; } diff --git a/src/main/java/com/sjhy/plugin/entity/ColumnConfig.java b/src/main/java/com/sjhy/plugin/entity/ColumnConfig.java index 0771336a..370c79be 100644 --- a/src/main/java/com/sjhy/plugin/entity/ColumnConfig.java +++ b/src/main/java/com/sjhy/plugin/entity/ColumnConfig.java @@ -1,5 +1,6 @@ package com.sjhy.plugin.entity; +import com.sjhy.plugin.enums.ColumnConfigType; import lombok.Data; import lombok.NoArgsConstructor; @@ -12,7 +13,7 @@ */ @Data @NoArgsConstructor -public class ColumnConfig { +public class ColumnConfig implements AbstractItem { /** * 标题 */ @@ -36,4 +37,9 @@ public ColumnConfig(String title, ColumnConfigType type, String selectValue) { this.type = type; this.selectValue = selectValue; } + + @Override + public ColumnConfig defaultVal() { + return new ColumnConfig("demo", ColumnConfigType.TEXT); + } } diff --git a/src/main/java/com/sjhy/plugin/entity/ColumnConfigGroup.java b/src/main/java/com/sjhy/plugin/entity/ColumnConfigGroup.java index f5725c4c..f95d31a2 100644 --- a/src/main/java/com/sjhy/plugin/entity/ColumnConfigGroup.java +++ b/src/main/java/com/sjhy/plugin/entity/ColumnConfigGroup.java @@ -12,7 +12,7 @@ * @since 2018年07月18日 09:33 */ @Data -public class ColumnConfigGroup implements AbstractGroup { +public class ColumnConfigGroup implements AbstractGroup { /** * 分组名称 */ diff --git a/src/main/java/com/sjhy/plugin/entity/ColumnInfo.java b/src/main/java/com/sjhy/plugin/entity/ColumnInfo.java index eca48d81..1f9387b9 100644 --- a/src/main/java/com/sjhy/plugin/entity/ColumnInfo.java +++ b/src/main/java/com/sjhy/plugin/entity/ColumnInfo.java @@ -39,7 +39,7 @@ public class ColumnInfo { /** * 标记是否为自定义附加列 */ - private boolean custom; + private Boolean custom; /** * 扩展数据 */ diff --git a/src/main/java/com/sjhy/plugin/entity/GlobalConfig.java b/src/main/java/com/sjhy/plugin/entity/GlobalConfig.java index eaf7e1f3..dfb39f8e 100644 --- a/src/main/java/com/sjhy/plugin/entity/GlobalConfig.java +++ b/src/main/java/com/sjhy/plugin/entity/GlobalConfig.java @@ -1,6 +1,5 @@ package com.sjhy.plugin.entity; -import com.sjhy.plugin.ui.base.Item; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,7 +14,7 @@ @Data @NoArgsConstructor @AllArgsConstructor -public class GlobalConfig implements Item { +public class GlobalConfig implements AbstractEditorItem { /** * 名称 */ @@ -24,4 +23,29 @@ public class GlobalConfig implements Item { * 值 */ private String value; + + @Override + public GlobalConfig defaultVal() { + return new GlobalConfig("demo", "value"); + } + + @Override + public void changeFileName(String name) { + this.name = name; + } + + @Override + public String fileName() { + return this.name; + } + + @Override + public void changeFileContent(String content) { + this.value = content; + } + + @Override + public String fileContent() { + return this.value; + } } diff --git a/src/main/java/com/sjhy/plugin/entity/GlobalConfigGroup.java b/src/main/java/com/sjhy/plugin/entity/GlobalConfigGroup.java index 557a0ec7..1bf3b700 100644 --- a/src/main/java/com/sjhy/plugin/entity/GlobalConfigGroup.java +++ b/src/main/java/com/sjhy/plugin/entity/GlobalConfigGroup.java @@ -12,7 +12,7 @@ * @since 2018年07月27日 13:10 */ @Data -public class GlobalConfigGroup implements AbstractGroup { +public class GlobalConfigGroup implements AbstractGroup { /** * 分组名称 */ diff --git a/src/main/java/com/sjhy/plugin/entity/SaveFile.java b/src/main/java/com/sjhy/plugin/entity/SaveFile.java new file mode 100644 index 00000000..54467931 --- /dev/null +++ b/src/main/java/com/sjhy/plugin/entity/SaveFile.java @@ -0,0 +1,286 @@ +package com.sjhy.plugin.entity; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.testFramework.LightVirtualFile; +import com.sjhy.plugin.dto.GenerateOptions; +import com.sjhy.plugin.tool.CompareFileUtils; +import com.sjhy.plugin.tool.FileUtils; +import com.sjhy.plugin.tool.MessageDialogUtils; +import com.sjhy.plugin.tool.ProjectUtils; +import lombok.Data; +import lombok.NonNull; + +import java.io.File; + +/** + * 需要保存的文件 + *

+ * 如果文件保存在项目路径下,则使用idea提供的psi对象操作。如果文件保存在非项目路径下,则使用java原始IO流操作。 + * + * @author makejava + * @version 1.0.0 + * @since 2020年04月20日 22:54 + */ +@Data +public class SaveFile { + private static final Logger LOG = Logger.getInstance(SaveFile.class); + /** + * 所属项目 + */ + private Project project; + /** + * 文件内容 + */ + private String content; + /** + * 文件工具类 + */ + private FileUtils fileUtils = FileUtils.getInstance(); + /** + * 回调对象 + */ + private Callback callback; + /** + * 生成配置 + */ + private GenerateOptions generateOptions; + + /** + * 保存文件 + * + * @param project 项目 + * @param content 内容 + * @param callback 回调 + * @param generateOptions 生成选项 + */ + public SaveFile(@NonNull Project project, @NonNull String content, @NonNull Callback callback, @NonNull GenerateOptions generateOptions) { + this.project = project; + this.callback = callback; + this.content = content.replace("\r", ""); + this.generateOptions = generateOptions; + } + + /** + * 文件是否为项目文件 + * + * @return 是否为项目文件 + */ + private boolean isProjectFile() { + VirtualFile baseDir = ProjectUtils.getBaseDir(project); + // 无法获取到项目基本目录,可能是Default项目,直接返回非项目文件 + if (baseDir == null) { + return false; + } + // 路径对比,判断项目路径是否为文件保存路径的子路径 + String projectPath = handlerPath(baseDir.getPath()); + String tmpFilePath = handlerPath(callback.getSavePath()); + if (tmpFilePath.length()> projectPath.length()) { + if (!"/".equals(tmpFilePath.substring(projectPath.length(), projectPath.length() + 1))) { + return false; + } + } + return tmpFilePath.indexOf(projectPath) == 0; + } + + /** + * 处理路径,统一分割符并转小写 + * + * @param path 路径 + * @return 处理后的路径 + */ + private String handlerPath(String path) { + return handlerPath(path, true); + } + + /** + * 处理路径,统一分割符并转小写 + * + * @param path 路径 + * @param lowerCase 是否转小写 + * @return 处理后的路径 + */ + private String handlerPath(String path, boolean lowerCase) { + // 统一分割符 + path = path.replace("\\", "/"); + // 避免重复分割符 + path = path.replace("//", "/"); + // 统一小写 + return lowerCase ? path.toLowerCase() : path; + } + + /** + * 通过IDEA自带的Psi文件方式写入 + */ + public void write() { + if (!Boolean.TRUE.equals(callback.getWriteFile())) { + return; + } + // 判断目录是否存在 + VirtualFile baseDir = ProjectUtils.getBaseDir(project); + if (baseDir == null) { + throw new IllegalStateException("项目基本路径不存在"); + } + // 处理保存路径 + String savePath = handlerPath(callback.getSavePath(), false); + if (isProjectFile()) { + // 删除保存路径的前面部分 + savePath = savePath.substring(handlerPath(baseDir.getPath()).length()); + } else { + baseDir = null; + } + // 删除开头与结尾的/符号 + while (savePath.startsWith("/")) { + savePath = savePath.substring(1); + } + while (savePath.endsWith("/")) { + savePath = savePath.substring(0, savePath.length() - 1); + } + // 查找保存目录是否存在 + VirtualFile saveDir; + if (baseDir == null) { + saveDir = VfsUtil.findFileByIoFile(new File(savePath), false); + } else { + saveDir = VfsUtil.findRelativeFile(baseDir, savePath.split("/")); + } + // 提示创建目录 + VirtualFile directory = titleCreateDir(saveDir, baseDir, savePath); + if (directory == null) { + return; + } + VirtualFile psiFile = directory.findChild(callback.getFileName()); + // 保存或覆盖 + saveOrReplaceFile(psiFile, directory); + } + + /** + * 提示创建目录 + * + * @param saveDir 保存路径 + * @return 是否放弃执行 + */ + private VirtualFile titleCreateDir(VirtualFile saveDir, VirtualFile baseDir, String savePath) { + if (saveDir != null) { + return saveDir; + } + // 尝试创建目录 + String msg = String.format("Directory %s Not Found, Confirm Create?", callback.getSavePath()); + if (generateOptions.getTitleSure()) { + saveDir = fileUtils.createChildDirectory(project, baseDir, savePath); + return saveDir; + } else if (generateOptions.getTitleRefuse()) { + return null; + } else { + if (MessageDialogUtils.yesNo(project, msg)) { + saveDir = fileUtils.createChildDirectory(project, baseDir, savePath); + return saveDir; + } + } + return null; + } + + /** + * 保存或替换文件 + * + * @param file 文件 + * @param directory 目录 + */ + private void saveOrReplaceFile(VirtualFile file, VirtualFile directory) { + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); + Document document; + // 文件不存在直接创建 + if (file == null) { + file = fileUtils.createChildFile(project, directory, callback.getFileName()); + if (file == null) { + return; + } + document = coverFile(file); + } else { + // 提示覆盖文件 + if (generateOptions.getTitleSure()) { + // 默认选是 + document = coverFile(file); + } else if (generateOptions.getTitleRefuse()) { + // 默认选否 + return; + } else { + String msg = String.format("File %s Exists, Select Operate Mode?", file.getPath()); + int result = MessageDialogUtils.yesNoCancel(project, msg, "Convert", "Compare", "Cancel"); + switch (result) { + case Messages.YES: + // 覆盖文件 + document = coverFile(file); + break; + case Messages.NO: + // 对比代码时也格式化代码 + String newText = content; + if (Boolean.TRUE.equals(callback.getReformat())) { + // 保留旧文件内容,用新文件覆盖旧文件执行格式化,然后再还原旧文件内容 + String oldText = getFileText(file); + Document tmpDoc = coverFile(file); + // 格式化代码 + FileUtils.getInstance().reformatFile(project, file); + // 提交文档改动,并非VCS中的提交文件 + psiDocumentManager.commitDocument(tmpDoc); + // 获取新的文件内容 + newText = getFileText(file); + // 还原旧文件 + coverFile(file, oldText); + } + FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(callback.getFileName()); + CompareFileUtils.showCompareWindow(project, file, new LightVirtualFile(callback.getFileName(), fileType, newText)); + return; + case Messages.CANCEL: + default: + return; + } + } + } + // 执行代码格式化操作 + if (Boolean.TRUE.equals(callback.getReformat())) { + FileUtils.getInstance().reformatFile(project, file); + } + // 提交文档改动,并非VCS中的提交文件 + if (document != null) { + psiDocumentManager.commitDocument(document); + } + } + + private String getFileText(VirtualFile file) { + FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + Document document = fileDocumentManager.getDocument(file); + if (document == null) { + throw new IllegalStateException("virtual file to document failure"); + } + return document.getText(); + } + + /** + * 覆盖文件 + * + * @param file 文件 + * @return 覆盖后的文档对象 + */ + private Document coverFile(VirtualFile file) { + return coverFile(file, content); + } + + /** + * 覆盖文件 + * + * @param file 文件 + * @param text 文件内容 + * @return 覆盖后的文档对象 + */ + private Document coverFile(VirtualFile file, String text) { + return FileUtils.getInstance().writeFileContent(project, file, callback.getFileName(), text); + } +} diff --git a/src/main/java/com/sjhy/plugin/entity/TableInfo.java b/src/main/java/com/sjhy/plugin/entity/TableInfo.java index d4de05db..169ad13c 100644 --- a/src/main/java/com/sjhy/plugin/entity/TableInfo.java +++ b/src/main/java/com/sjhy/plugin/entity/TableInfo.java @@ -20,14 +20,31 @@ public class TableInfo { */ @JsonIgnore private DbTable obj; + + /** + * 原始对象(从实体生成) + * + * Note: 实际类型是com.intellij.psi.PsiClass,为了避免velocity反射出现ClassNotFound,写为Object类型 + */ + @JsonIgnore + private Object psiClassObj; + /** * 表名(首字母大写) */ private String name; + /** + * 表名前缀 + */ + private String preName; /** * 注释 */ private String comment; + /** + * 模板组名称 + */ + private String templateGroupName; /** * 所有列 */ diff --git a/src/main/java/com/sjhy/plugin/entity/Template.java b/src/main/java/com/sjhy/plugin/entity/Template.java index 6e425d4c..22cdc8f4 100644 --- a/src/main/java/com/sjhy/plugin/entity/Template.java +++ b/src/main/java/com/sjhy/plugin/entity/Template.java @@ -1,6 +1,5 @@ package com.sjhy.plugin.entity; -import com.sjhy.plugin.ui.base.Item; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,7 +14,7 @@ @Data @NoArgsConstructor @AllArgsConstructor -public class Template implements Item { +public class Template implements AbstractEditorItem