refactor: Restructure project, enhance ActionField and DTOField generation
This commit refactors the project structure by moving generator-related classes to a new package (`com.sdk.generators.actionmodels`) and standardizing template directory names (`src/main/resources/templates`). It introduces new FreeMarker templates (`actionDTO.ftl`, `actionDTO.extend.ftl`) and corresponding logic in `GeneratorServices.java` to support the generation of Data Transfer Object (DTO) classes alongside ActionBeans. The changes also involve enhancements related to `ActionField` and `DTOField` generation. Updates to `build.gradle.kts`, `plugin.xml`, and Gradle wrapper files reflect these structural and functional enhancements.
This commit is contained in:
@@ -1,4 +1,149 @@
|
||||
package com.sdk.generators;
|
||||
|
||||
import com.intellij.database.model.DasColumn;
|
||||
import com.intellij.database.model.ObjectKind;
|
||||
import com.intellij.database.psi.DbObject;
|
||||
import com.intellij.database.psi.DbTable;
|
||||
import com.intellij.database.util.DasUtil;
|
||||
import com.intellij.notification.NotificationGroupManager;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.PackageIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GUtils {
|
||||
|
||||
private static final LinkedHashMap<String, String> TYPE_MAPPING = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
TYPE_MAPPING.put("bigint", "NUMBER");
|
||||
TYPE_MAPPING.put("bit", "STRING");
|
||||
TYPE_MAPPING.put("boolean", "STRING");
|
||||
TYPE_MAPPING.put("date", "DATE");
|
||||
TYPE_MAPPING.put("decimal", "NUMBER");
|
||||
TYPE_MAPPING.put("double", "NUMBER");
|
||||
TYPE_MAPPING.put("float", "NUMBER");
|
||||
TYPE_MAPPING.put("integer", "NUMBER");
|
||||
TYPE_MAPPING.put("numeric", "NUMBER");
|
||||
TYPE_MAPPING.put("smallint", "NUMBER");
|
||||
TYPE_MAPPING.put("timestamp", "DATE");
|
||||
TYPE_MAPPING.put("text", "STRING");
|
||||
TYPE_MAPPING.put("time", "DATE");
|
||||
TYPE_MAPPING.put("tinyint", "NUMBER");
|
||||
TYPE_MAPPING.put("varchar2", "STRING");
|
||||
TYPE_MAPPING.put("varchar", "STRING");
|
||||
TYPE_MAPPING.put("char", "STRING");
|
||||
}
|
||||
|
||||
private static final Map<String, String> userDefType = new HashMap<>();
|
||||
|
||||
private static String getRawType(String columnDefinition) {
|
||||
String columnScript = columnDefinition.replaceAll("\s","#");
|
||||
for (String rawType : TYPE_MAPPING.keySet()) {
|
||||
if (columnScript.contains("#"+rawType)) {
|
||||
return rawType;
|
||||
}
|
||||
if (columnScript.contains("#"+rawType+"(")) {
|
||||
return rawType;
|
||||
}
|
||||
if (columnScript.contains("#"+rawType+"#(")) {
|
||||
return rawType;
|
||||
}
|
||||
}
|
||||
return "varchar";
|
||||
}
|
||||
|
||||
public static void createUserDefineType(DbTable table) {
|
||||
String schemaName = table.getParent() != null ? table.getParent().getName() : "";
|
||||
DasUtil.getCatalogObject(table).getDasChildren(ObjectKind.SCHEMA).forEach(schema -> {
|
||||
if (schema.getName().equals("public") || schema.getName().equals(schemaName)) {
|
||||
schema.getDasChildren(ObjectKind.OBJECT_TYPE).forEach(domain -> {
|
||||
String domainName = domain.getName();
|
||||
String domainScript = ((DbObject) domain).getText();
|
||||
userDefType.put(domainName, getRawType(domainScript));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String getFieldType(DasColumn column) {
|
||||
String columnType = column.getDasType().toDataType().typeName;
|
||||
String fieldType = TYPE_MAPPING.get(columnType);
|
||||
if (fieldType == null) {
|
||||
fieldType = TYPE_MAPPING.getOrDefault(userDefType.getOrDefault(columnType, "varchar"), "Object");
|
||||
}
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
public static String toCamelCase(String s, boolean capitalizeFirst) {
|
||||
String[] parts = s.split("_");
|
||||
StringBuilder camelCaseString = new StringBuilder();
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i];
|
||||
if (i == 0 && !capitalizeFirst) {
|
||||
camelCaseString.append(part.toLowerCase());
|
||||
} else {
|
||||
camelCaseString.append(capitalize(part));
|
||||
}
|
||||
}
|
||||
return camelCaseString.toString();
|
||||
}
|
||||
|
||||
public static String capitalize(String s) {
|
||||
if (s == null || s.isEmpty()) {
|
||||
return s;
|
||||
}
|
||||
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
public static String getSelectedPackage(Project project, VirtualFile selectDirectory) {
|
||||
if (selectDirectory == null) return "";
|
||||
return PackageIndex.getInstance(project).getPackageNameByDirectory(selectDirectory);
|
||||
}
|
||||
|
||||
public static VirtualFile findSourceRoot(Project project) {
|
||||
for (VirtualFile root : ProjectRootManager.getInstance(project).getContentSourceRoots()) {
|
||||
if (root.isDirectory() && !root.getName().equals("resources")) {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static VirtualFile createPackageDirs(Object requestor, VirtualFile sourceRoot, String path) throws IOException {
|
||||
VirtualFile current = sourceRoot;
|
||||
for (String part : path.split("/")) {
|
||||
VirtualFile child = current.findChild(part);
|
||||
if (child == null) {
|
||||
child = current.createChildDirectory(requestor, part);
|
||||
}
|
||||
current = child;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
public static void showError(Project project, String message) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> Messages.showErrorDialog(project, message, "Generation Failed"));
|
||||
NotificationGroupManager.getInstance()
|
||||
// This ID should be registered in your plugin.xml
|
||||
.getNotificationGroup("Action-Models-Generator-Notification")
|
||||
.createNotification("ActionModels Generator", message, NotificationType.ERROR)
|
||||
.notify(project);
|
||||
}
|
||||
|
||||
public static void showInfo(Project project, String title, String content) {
|
||||
NotificationGroupManager.getInstance()
|
||||
// This ID should be registered in your plugin.xml
|
||||
.getNotificationGroup("Action-Models-Generator-Notification")
|
||||
.createNotification(title, content, NotificationType.INFORMATION)
|
||||
.notify(project);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
package com.sdk.actionbean.generator;
|
||||
package com.sdk.generators.actionmodels;
|
||||
|
||||
import com.intellij.database.model.*;
|
||||
import com.intellij.database.psi.*;
|
||||
import com.intellij.database.util.*;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.fileChooser.*;
|
||||
import com.intellij.openapi.project.*;
|
||||
import com.intellij.openapi.ui.*;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.containers.*;
|
||||
import org.jetbrains.annotations.*;
|
||||
import com.intellij.database.model.DasColumn;
|
||||
import com.intellij.database.model.ObjectKind;
|
||||
import com.intellij.database.psi.DbObject;
|
||||
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.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDialog;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWrapper;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import com.sdk.generators.GUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GenerateAction extends AnAction {
|
||||
|
||||
@@ -44,7 +54,7 @@ public class GenerateAction extends AnAction {
|
||||
|
||||
private static final Map<String,String> userDefType = new HashMap<>();
|
||||
|
||||
private String getRawType(String columnDefinition ) {
|
||||
private static String getRawType(String columnDefinition ) {
|
||||
for (String rawType : TYPE_MAPPING.keySet()) {
|
||||
if (columnDefinition.contains(rawType)) {
|
||||
return rawType;
|
||||
@@ -53,7 +63,7 @@ public class GenerateAction extends AnAction {
|
||||
return "varchar";
|
||||
}
|
||||
|
||||
private void createUserDefineType(DbTable table) {
|
||||
private static void createUserDefineType(DbTable table) {
|
||||
if (userDefType.isEmpty()) {
|
||||
String schemaName = table.getParent() != null ? table.getParent().getName() : "";
|
||||
DasUtil.getCatalogObject(table).getDasChildren(ObjectKind.SCHEMA).forEach(schema -> {
|
||||
@@ -68,7 +78,7 @@ public class GenerateAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldType(String columnType) {
|
||||
public static String getFieldType(String columnType) {
|
||||
columnType = columnType.toLowerCase();
|
||||
String fieldType = TYPE_MAPPING.get(columnType );
|
||||
if (fieldType == null) {
|
||||
@@ -96,22 +106,22 @@ public class GenerateAction extends AnAction {
|
||||
createUserDefineType(table);
|
||||
}
|
||||
|
||||
String className = toCamelCase(table.getName(), true);
|
||||
String className = GUtils.toCamelCase(table.getName(), true);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("public class ").append(className).append(" {\n\n");
|
||||
|
||||
JBIterable<? extends DasColumn> columns = DasUtil.getColumns(table);
|
||||
for (DasColumn column : columns) {
|
||||
String fieldName = toCamelCase(column.getName(), false);
|
||||
String fieldName = GUtils.toCamelCase(column.getName(), false);
|
||||
String fieldType = getFieldType(column.getDasType().toDataType().typeName);
|
||||
builder.append(" private ").append(fieldType).append(" ").append(fieldName).append(";\n");
|
||||
}
|
||||
builder.append("\n");
|
||||
|
||||
for (DasColumn column : columns) {
|
||||
String fieldName = toCamelCase(column.getName(), false);
|
||||
String fieldName = GUtils.toCamelCase(column.getName(), false);
|
||||
String fieldType = getFieldType(column.getDasType().toDataType().typeName);
|
||||
String capitalizedFieldName = capitalize(fieldName);
|
||||
String capitalizedFieldName = GUtils.capitalize(fieldName);
|
||||
|
||||
builder.append(" public ").append(fieldType).append(" get").append(capitalizedFieldName).append("() {\n");
|
||||
builder.append(" return ").append(fieldName).append(";\n");
|
||||
@@ -139,25 +149,4 @@ public class GenerateAction extends AnAction {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String toCamelCase(String s, boolean capitalizeFirst) {
|
||||
String[] parts = s.split("_");
|
||||
StringBuilder camelCaseString = new StringBuilder();
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i];
|
||||
if (i == 0 && !capitalizeFirst) {
|
||||
camelCaseString.append(part.toLowerCase());
|
||||
} else {
|
||||
camelCaseString.append(capitalize(part));
|
||||
}
|
||||
}
|
||||
return camelCaseString.toString();
|
||||
}
|
||||
|
||||
private String capitalize(String s) {
|
||||
if (s == null || s.isEmpty()) {
|
||||
return s;
|
||||
}
|
||||
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sdk.actionbean.generator;
|
||||
package com.sdk.generators.actionmodels;
|
||||
|
||||
import com.intellij.database.psi.DbTable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
@@ -13,12 +13,9 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.openapi.roots.PackageIndex;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.sdk.generators.GUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,9 +32,10 @@ public class GenerateBeanAction extends AnAction {
|
||||
|
||||
FileChooserDescriptor descriptor = new FileChooserDescriptor(false,true,false,false,false,false);
|
||||
PathChooserDialog pathChooser = FileChooserFactory.getInstance().createPathChooser(descriptor, project, null);
|
||||
VirtualFile baseDir = ProjectUtil.guessProjectDir(project);
|
||||
VirtualFile baseDir = GUtils.findSourceRoot(project);
|
||||
|
||||
pathChooser.choose(baseDir, virtualFiles -> {
|
||||
String packageName = getSelectedPackage(project, virtualFiles.getFirst());
|
||||
String packageName = GUtils.getSelectedPackage(project, virtualFiles.getFirst());
|
||||
|
||||
ArrayList<DbTable> tables = new ArrayList<>();
|
||||
for (PsiElement psiElement : psiElements) {
|
||||
@@ -58,30 +56,11 @@ public class GenerateBeanAction extends AnAction {
|
||||
try {
|
||||
new GeneratorServices(project,tables,packageName).execute(indicator);
|
||||
} catch (Exception ex) {
|
||||
showError(project, "An error occurred during code generation: " + ex.getMessage());
|
||||
GUtils.showError(project, "An error occurred during code generation: " + ex.getMessage());
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showError(Project project, String message) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> Messages.showErrorDialog(project, message, "Generation Failed"));
|
||||
}
|
||||
|
||||
private String getSelectedPackage(Project project, VirtualFile selectDirectory) {
|
||||
if (selectDirectory == null) return "";
|
||||
String packageName = PackageIndex.getInstance(project).getPackageNameByDirectory(selectDirectory);
|
||||
return packageName;
|
||||
}
|
||||
|
||||
private VirtualFile findSourceRoot(Project project, String packageName) {
|
||||
for (VirtualFile root : ProjectRootManager.getInstance(project).getContentSourceRoots()) {
|
||||
if (root.isDirectory() && !root.getName().equals("resources")) {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +1,148 @@
|
||||
package com.sdk.actionbean.generator;
|
||||
package com.sdk.generators.actionmodels;
|
||||
|
||||
import com.intellij.database.model.DasColumn;
|
||||
import com.intellij.database.model.DasTableKey;
|
||||
import com.intellij.database.psi.DbTable;
|
||||
import com.intellij.database.util.DasUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import com.sdk.generators.GUtils;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GeneratorServices {
|
||||
|
||||
private final String packageName;
|
||||
private final String basePackage;
|
||||
private final Project project;
|
||||
private final ArrayList<DbTable> tables;
|
||||
|
||||
public GeneratorServices(Project project, ArrayList<DbTable> tables, String packageName) {
|
||||
public GeneratorServices(Project project, ArrayList<DbTable> tables, String basePackage) {
|
||||
this.tables = tables;
|
||||
this.project = project;
|
||||
this.packageName = packageName;
|
||||
this.basePackage = basePackage;
|
||||
}
|
||||
|
||||
private void genDataModel(Template template, Map<String, Object> model, VirtualFile targetDir, String classFile, ProgressIndicator indicator) {
|
||||
try {
|
||||
VirtualFile outputFile = targetDir.findOrCreateChildData(this, classFile);
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try (Writer writer = new OutputStreamWriter(outputFile.getOutputStream(this))) {
|
||||
template.process(model, writer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
indicator.setText2("Generated " + outputFile.getName());
|
||||
GUtils.showInfo(project, "ActionModels Generator", "Generated " + outputFile.getName());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void execute(@NotNull ProgressIndicator indicator) {
|
||||
// String packagePath = packageName.replace('.', '/');
|
||||
// VirtualFile packageDir = createPackageDirs(sourceRoot, packagePath);
|
||||
//
|
||||
// Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
|
||||
// cfg.setClassForTemplateLoading(this.getClass(), "/templates");
|
||||
// cfg.setDefaultEncoding("UTF-8");
|
||||
// cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
// Template template = cfg.getTemplate("actionBean.ftl");
|
||||
//
|
||||
// DatabaseMetaData metaData = conn.getMetaData();
|
||||
// try (ResultSet tables = metaData.getTables(null, dbSchema.toUpperCase(), tablePattern, new String[]{"TABLE"})) {
|
||||
// while (tables.next()) {
|
||||
// String tableName = tables.getString("TABLE_NAME");
|
||||
// indicator.setText("Processing table: " + tableName);
|
||||
//
|
||||
// Map<String, Object> model = createModelForTable(metaData, tableName, dbSchema);
|
||||
//
|
||||
// VirtualFile outputFile = packageDir.findOrCreateChildData(this, model.get("className") + ".java");
|
||||
// try (Writer writer = new OutputStreamWriter(outputFile.getOutputStream(this))) {
|
||||
// template.process(model, writer);
|
||||
// }
|
||||
// indicator.setText2("Generated " + outputFile.getName());
|
||||
// }
|
||||
// }
|
||||
// Use AtomicInteger to safely count files within the lambda expression
|
||||
AtomicInteger fileCount = new AtomicInteger(0);
|
||||
try {
|
||||
|
||||
VirtualFile sourceRoot = GUtils.findSourceRoot(project);
|
||||
String packagePath = basePackage.replace('.', '/');
|
||||
|
||||
|
||||
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
|
||||
cfg.setClassForTemplateLoading(this.getClass(), "/templates");
|
||||
cfg.setDefaultEncoding("UTF-8");
|
||||
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
|
||||
|
||||
VirtualFile beanExtDir = GUtils.createPackageDirs(this, sourceRoot, Path.of(packagePath, "/bean").toString());
|
||||
VirtualFile beanDir = GUtils.createPackageDirs(this, sourceRoot, Path.of(packagePath, "/bean/base").toString());
|
||||
Template tmpBean = cfg.getTemplate("actionBean.ftl");
|
||||
Template tmpBeanExt = cfg.getTemplate("actionBean.extend.ftl");
|
||||
|
||||
VirtualFile DTOExtDir = GUtils.createPackageDirs(this, sourceRoot, Path.of(packagePath, "/dto").toString());
|
||||
VirtualFile DTODir = GUtils.createPackageDirs(this, sourceRoot, Path.of(packagePath, "/dto/base").toString());
|
||||
Template tmpDTO = cfg.getTemplate("actionDTO.ftl");
|
||||
Template tmpDTOExt = cfg.getTemplate("actionDTO.extend.ftl");
|
||||
|
||||
tables.forEach(table -> {
|
||||
Map<String, Object> model = createModelForTable(table);
|
||||
|
||||
String className = model.get("className").toString();
|
||||
String classFile = className + ".java";
|
||||
|
||||
genDataModel(tmpBean, model, beanDir, classFile, indicator);
|
||||
fileCount.getAndIncrement();
|
||||
|
||||
if (!Files.exists(Path.of(beanExtDir.toNioPath().toString(), classFile))) {
|
||||
genDataModel(tmpBeanExt, model, beanExtDir, classFile, indicator);
|
||||
fileCount.getAndIncrement();
|
||||
}
|
||||
|
||||
// FIX: Use a separate variable for the DTO filename to avoid overwriting the wrong file.
|
||||
String dtoClassFile = "DTO_" + className + ".java";
|
||||
genDataModel(tmpDTO, model, DTODir, dtoClassFile, indicator);
|
||||
fileCount.getAndIncrement();
|
||||
|
||||
if (!Files.exists(Path.of(DTOExtDir.toNioPath().toString(), dtoClassFile))) {
|
||||
genDataModel(tmpDTOExt, model, DTOExtDir, dtoClassFile, indicator);
|
||||
fileCount.getAndIncrement();
|
||||
}
|
||||
});
|
||||
|
||||
// After the loop finishes, show a single, helpful summary notification.
|
||||
String message = String.format("Generated %d files for %d tables successfully.", fileCount.get(), tables.size());
|
||||
GUtils.showInfo(project, "ActionModels Generation Complete", message);
|
||||
|
||||
} catch (Exception ex) {
|
||||
GUtils.showError(project, "Generation Failed \n" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> createModelForTable(DatabaseMetaData metaData, String tableName, String dbSchema) throws SQLException {
|
||||
private Map<String, Object> createModelForTable(DbTable table) {
|
||||
String tableName = table.getName().toUpperCase();
|
||||
String dbSchema = table.getParent() != null ? table.getParent().getName() : "";
|
||||
|
||||
GUtils.createUserDefineType(table);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put("packageName", packageName);
|
||||
model.put("basePackage", basePackage);
|
||||
model.put("tableName", tableName);
|
||||
model.put("className", tableName);
|
||||
model.put("dbSchema", dbSchema);
|
||||
|
||||
List<Map<String, Object>> columns = new ArrayList<>();
|
||||
Set<String> primaryKeys = new HashSet<>();
|
||||
try (ResultSet pks = metaData.getPrimaryKeys(null, dbSchema.toUpperCase(), tableName)) {
|
||||
while (pks.next()) {
|
||||
primaryKeys.add(pks.getString("COLUMN_NAME"));
|
||||
}
|
||||
}
|
||||
JBIterable<? extends DasTableKey> dasKeys = DasUtil.getTableKeys(table);
|
||||
|
||||
try (ResultSet cols = metaData.getColumns(null, dbSchema.toUpperCase(), tableName, "%")) {
|
||||
while (cols.next()) {
|
||||
Map<String, Object> colModel = new HashMap<>();
|
||||
String colName = cols.getString("COLUMN_NAME");
|
||||
int dataType = cols.getInt("DATA_TYPE");
|
||||
|
||||
colModel.put("name", colName);
|
||||
colModel.put("isPk", primaryKeys.contains(colName));
|
||||
colModel.put("customType", mapJdbcType(dataType));
|
||||
columns.add(colModel);
|
||||
dasKeys.forEach(key -> {
|
||||
if (key.isPrimary()) {
|
||||
DasUtil.getColumns(key).forEach(column -> primaryKeys.add(column.getName().toUpperCase()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JBIterable<? extends DasColumn> dasColumns = DasUtil.getColumns(table);
|
||||
dasColumns.forEach(column -> {
|
||||
Map<String, Object> colModel = new HashMap<>();
|
||||
String colName = column.getName().toUpperCase();
|
||||
String dataType = GUtils.getFieldType(column);
|
||||
colModel.put("name", colName);
|
||||
colModel.put("isPk", primaryKeys.contains(colName));
|
||||
colModel.put("customType", dataType);
|
||||
columns.add(colModel);
|
||||
});
|
||||
|
||||
model.put("columns", columns);
|
||||
model.put("fieldList", columns.stream().map(c -> (String) c.get("name")).collect(Collectors.joining(",")));
|
||||
@@ -86,25 +150,4 @@ public class GeneratorServices {
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private VirtualFile createPackageDirs(VirtualFile sourceRoot, String path) throws java.io.IOException {
|
||||
VirtualFile current = sourceRoot;
|
||||
for (String part : path.split("/")) {
|
||||
VirtualFile child = current.findChild(part);
|
||||
if (child == null) {
|
||||
child = current.createChildDirectory(this, part);
|
||||
}
|
||||
current = child;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
private String mapJdbcType(int jdbcType) {
|
||||
return switch (jdbcType) {
|
||||
case Types.NUMERIC, Types.DECIMAL, Types.INTEGER, Types.BIGINT, Types.SMALLINT, Types.TINYINT, Types.FLOAT, Types.DOUBLE -> "NUMBER";
|
||||
case Types.DATE, Types.TIMESTAMP, Types.TIMESTAMP_WITH_TIMEZONE -> "DATE";
|
||||
default -> "STRING";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
|
||||
<idea-plugin>
|
||||
<!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
|
||||
<id>com.sdk.actionbean.generator</id>
|
||||
<id>com.sdk.generators.actionmodels</id>
|
||||
<name>Database Action Models Generator</name>
|
||||
<vendor>Sakda Sakprapakorn</vendor>
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
<actions>
|
||||
<!-- Defines an action that will appear in the context menu for project directories -->
|
||||
<action id="ActionModelGenerator.GenerateAction"
|
||||
class="com.sdk.actionbean.generator.GenerateBeanAction"
|
||||
text="Generate Database Action Models"
|
||||
<action id="com.sdk.generators.actionmodels.GenerateBeanAction"
|
||||
class="com.sdk.generators.actionmodels.GenerateBeanAction"
|
||||
text="Generate Action Models"
|
||||
description="Generates ActionBean classes from a database schema.">
|
||||
<add-to-group group-id="GenerateGroup" anchor="first"/>
|
||||
<!-- This makes the action visible only when right-clicking a source package -->
|
||||
<add-to-group group-id="DatabaseViewPopupMenu" anchor="first"/>
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt G"/>
|
||||
</action>
|
||||
</actions>
|
||||
|
||||
<!-- in plugin.xml, inside the <extensions defaultExtensionNs="com.intellij"> tag -->
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<notificationGroup id="Action-Models-Generator-Notification" displayType="BALLOON" isLogByDefault="true"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,13 +1,13 @@
|
||||
package ${packageName}.bean;
|
||||
package ${basePackage}.bean;
|
||||
|
||||
/**
|
||||
* Generated by IntelliJ ActionBean Generator
|
||||
* Table: ${tableName}
|
||||
/*
|
||||
Generated by ActionBean Generator
|
||||
For Table : ${tableName}
|
||||
*/
|
||||
|
||||
import sdk.dbutils.*;
|
||||
|
||||
public class ${tableName} extends ${packageName}.bean.base.${tableName} {
|
||||
public class ${tableName} extends ${basePackage}.bean.base.${tableName} {
|
||||
public ${tableName}(DBConnector connector) { //class construction
|
||||
super(connector);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package ${packageName}.bean.base;
|
||||
package ${basePackage}.bean.base;
|
||||
|
||||
/**
|
||||
* Generated by IntelliJ ActionBean Generator
|
||||
* Table: ${tableName}
|
||||
/*
|
||||
Generated by ActionBean Generator
|
||||
For Table : ${tableName}
|
||||
*/
|
||||
|
||||
import sdk.dbutils.*;
|
||||
@@ -16,12 +16,22 @@ public class ${className} extends ActionBean {
|
||||
public static final String fullTableName = "${tableName}";
|
||||
private DTO_${tableName} myDTO;
|
||||
|
||||
<#list columns as col>
|
||||
public final ActionField afx${col.name};
|
||||
</#list>
|
||||
|
||||
public ${className}(DBConnector dbConnector) { //class construction
|
||||
super(dbConnector, fullTableName);
|
||||
myDTO = new DTO_${tableName}();
|
||||
initFieldDefs();
|
||||
fieldList = "${fieldList}";
|
||||
keyList = "${keyList}";
|
||||
|
||||
// Create ActionField Instant (afx) for each field
|
||||
<#list columns as col>
|
||||
afx${col.name} = new ActionField(this,${col.name});
|
||||
</#list>
|
||||
|
||||
}
|
||||
|
||||
public ${className}() { //class construction
|
||||
@@ -30,6 +40,11 @@ public class ${className} extends ActionBean {
|
||||
initFieldDefs();
|
||||
fieldList = "${fieldList}";
|
||||
keyList = "${keyList}";
|
||||
|
||||
// Create ActionField Instant (afx) for each field
|
||||
<#list columns as col>
|
||||
afx${col.name} = new ActionField(this,${col.name});
|
||||
</#list>
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,10 +73,24 @@ public class ${className} extends ActionBean {
|
||||
</#list>
|
||||
Sql.append(" FROM ${tableName}\n");
|
||||
Sql.append(" WHERE 0=0 \n");
|
||||
|
||||
sqlSelect = new StringBuilder(Sql);
|
||||
}
|
||||
|
||||
<#-- Generate Field Constants -->
|
||||
<#list columns as col>
|
||||
public static final String ${col.name} = "${col.name}";
|
||||
</#list>
|
||||
|
||||
<#-- Generate Getter -->
|
||||
<#list columns as col>
|
||||
public String get${col.name}() {
|
||||
return getValue(${col.name});
|
||||
}
|
||||
public String get${col.name}(String defValue) {
|
||||
return getValue(${col.name}, defValue);
|
||||
}
|
||||
</#list>
|
||||
|
||||
<#-- Generate Setters -->
|
||||
<#list columns as col>
|
||||
public void set${col.name}(String value) {
|
||||
@@ -70,34 +99,34 @@ public class ${className} extends ActionBean {
|
||||
setKeyField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
} else {
|
||||
<#if col.customType == "NUMBER">
|
||||
setKeyField(${col.name}, JUtils.cleanUpNumber(value));
|
||||
fieldByName(${col.name}).setAsString(JUtils.cleanUpNumber(value));
|
||||
<#elseif col.customType == "DATE">
|
||||
setKeyField(${col.name}, DateUtils.strToSqlDate(value));
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
<#else>
|
||||
setKeyField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
</#if>
|
||||
}
|
||||
<#elseif col.customType == "DATE">
|
||||
<#else>
|
||||
if (JUtils.isMacro(value)) {
|
||||
setField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
} else {
|
||||
<#if col.customType == "NUMBER">
|
||||
setField(${col.name}, JUtils.cleanUpNumber(value));
|
||||
fieldByName(${col.name}).setAsString(JUtils.cleanUpNumber(value));
|
||||
<#elseif col.customType == "DATE">
|
||||
setField(${col.name}, DateUtils.strToSqlDate(value));
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
<#else>
|
||||
setField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
</#if>
|
||||
}
|
||||
<#else>
|
||||
setField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
</#if>
|
||||
}
|
||||
|
||||
</#list>
|
||||
|
||||
<#-- Generate Getters and Constants -->
|
||||
<#list columns as col>
|
||||
public static final String ${col.name} = "${col.name}";
|
||||
public String get${col.name}() {
|
||||
return getValue(${col.name});
|
||||
}
|
||||
public String get${col.name}(String defValue) {
|
||||
return getValue(${col.name}, defValue);
|
||||
}
|
||||
|
||||
</#list>
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
package ${basePackage}.bean;
|
||||
package ${basePackage}.dto;
|
||||
|
||||
/**
|
||||
* Generated by IntelliJ ActionBean Generator
|
||||
* For Table : ${tableName}
|
||||
/*
|
||||
Generated by ActionBean Generator
|
||||
For Table : ${tableName}
|
||||
*/
|
||||
|
||||
import sdk.dbutils.*;
|
||||
|
||||
public class ${tableName} extends ${basePackage}.bean.base.${tableName} {
|
||||
public ${tableName}(DBConnector connector) { //class construction
|
||||
super(connector);
|
||||
public class DTO_${tableName} extends ${basePackage}.dto.base.DTO_${tableName} {
|
||||
public DTO_${tableName}(DTO dto) { //class construction
|
||||
super(dto);
|
||||
}
|
||||
|
||||
public ${tableName}() { //class construction
|
||||
public DTO_${tableName}() { //class construction
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +1,59 @@
|
||||
package ${basePackage}.bean.base;
|
||||
package ${basePackage}.dto.base;
|
||||
|
||||
/**
|
||||
* Generated by IntelliJ ActionBean Generator
|
||||
* For Table: ${tableName}
|
||||
/*
|
||||
Generated by ActionBean Generator
|
||||
For Table : ${tableName}
|
||||
*/
|
||||
|
||||
import sdk.dbutils.*;
|
||||
import sdk.utils.*;
|
||||
import ${basePackage}.dto.*;
|
||||
|
||||
public class ${className} extends ActionBean {
|
||||
public class DTO_${className} extends DTO {
|
||||
|
||||
public static final String tableName = "${tableName}";
|
||||
public static final String schemaName = "${dbSchema}";
|
||||
public static final String fullTableName = "${tableName}";
|
||||
private DTO_${tableName} myDTO;
|
||||
|
||||
public ${className}(DBConnector dbConnector) { //class construction
|
||||
super(dbConnector, fullTableName);
|
||||
myDTO = new DTO_${tableName}();
|
||||
initFieldDefs();
|
||||
fieldList = "${fieldList}";
|
||||
keyList = "${keyList}";
|
||||
}
|
||||
|
||||
public ${className}() { //class construction
|
||||
super();
|
||||
myDTO = new DTO_${tableName}();
|
||||
initFieldDefs();
|
||||
fieldList = "${fieldList}";
|
||||
keyList = "${keyList}";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initFieldDefs() {
|
||||
fieldDefs.clear();
|
||||
<#list columns as col>
|
||||
fieldDefs.put("${col.name}", "${col.customType}<#if col.isPk>:KEY</#if>");
|
||||
</#list>
|
||||
}
|
||||
|
||||
public DTO_${tableName} getInstanceDTO() {
|
||||
myDTO.setDTO(this.getDTO());
|
||||
return myDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initSqlSelect() {
|
||||
StringBuilder Sql = new StringBuilder();
|
||||
Sql.append("SELECT ");
|
||||
<#list columns as col>
|
||||
<#if col?is_first>
|
||||
Sql.append(" <#if col.customType == 'DATE'>JDTOET(${col.name}) ${col.name}, ${col.name} AS DT_${col.name}<#else> ${col.name}</#if>\n");
|
||||
<#else>
|
||||
Sql.append(" ,<#if col.customType == 'DATE'>JDTOET(${col.name}) ${col.name}, ${col.name} AS DT_${col.name}<#else>${col.name}</#if>\n");
|
||||
</#if>
|
||||
</#list>
|
||||
Sql.append(" FROM ${tableName}\n");
|
||||
Sql.append(" WHERE 0=0 \n");
|
||||
|
||||
sqlSelect = new StringBuilder(Sql);
|
||||
}
|
||||
|
||||
<#-- Generate Setters -->
|
||||
<#list columns as col>
|
||||
public void set${col.name}(String value) {
|
||||
<#if col.isPk>
|
||||
if (JUtils.isMacro(value)) {
|
||||
setKeyField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
} else {
|
||||
setKeyField(${col.name}, JUtils.cleanUpNumber(value));
|
||||
fieldByName(${col.name}).setAsString(JUtils.cleanUpNumber(value));
|
||||
}
|
||||
<#elseif col.customType == "DATE">
|
||||
if (JUtils.isMacro(value)) {
|
||||
setField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
} else {
|
||||
setField(${col.name}, DateUtils.strToSqlDate(value));
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
}
|
||||
<#else>
|
||||
setField(${col.name}, value);
|
||||
fieldByName(${col.name}).setAsString(value);
|
||||
</#if>
|
||||
}
|
||||
|
||||
public final DTOField dfx${col.name};
|
||||
</#list>
|
||||
|
||||
<#-- Generate Getters and Constants -->
|
||||
public DTO_${className}() { //class construction
|
||||
super();
|
||||
setFieldList("${fieldList}");
|
||||
|
||||
// Create DTOField Instant (dfx) for each field
|
||||
<#list columns as col>
|
||||
dfx${col.name} = new DTOField(this,${col.name});
|
||||
</#list>
|
||||
}
|
||||
|
||||
public DTO_${className}(DTO dto) { //class construction
|
||||
super();
|
||||
setFieldList("${fieldList}");
|
||||
this.data = dto.getData();
|
||||
|
||||
// Create DTOField Instant (dfx) for each field
|
||||
<#list columns as col>
|
||||
dfx${col.name} = new DTOField(this,${col.name});
|
||||
</#list>
|
||||
}
|
||||
|
||||
public void setDTO(DTO dto) {
|
||||
this.data = dto.getData();
|
||||
}
|
||||
|
||||
<#-- Generate Field Constants -->
|
||||
<#list columns as col>
|
||||
public static final String ${col.name} = "${col.name}";
|
||||
</#list>
|
||||
|
||||
<#-- Generate Getters and Setter -->
|
||||
<#list columns as col>
|
||||
public String get${col.name}() {
|
||||
return getValue(${col.name});
|
||||
}
|
||||
public String get${col.name}(String defValue) {
|
||||
return getValue(${col.name}, defValue);
|
||||
}
|
||||
|
||||
public void set${col.name}(String value) {
|
||||
setValue(${col.name}, value);
|
||||
}
|
||||
</#list>
|
||||
}
|
||||
Reference in New Issue
Block a user