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:
2025-09-23 23:07:19 +07:00
parent 1ac54a0d5d
commit c9147b069e
47 changed files with 946 additions and 305 deletions

View File

@@ -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);
}
}