feat: implement Dataset XML generation and Action Models V3
- Added 'Generate Dataset XML' feature to automate table definitions from database schema. - Implemented intelligent label generation (prioritizing comments) and automatic type mapping for XML. - Added 'Generate Action Models V3' supporting the new sdk.db package structure. - Updated release notes and bumped version to 2.1.0. - Registered new actions with keyboard shortcuts in plugin.xml.
This commit is contained in:
@@ -48,13 +48,13 @@ public class GenerateBeanAction extends AnAction {
|
||||
}
|
||||
|
||||
private void runGenerator(Project project,ArrayList<DbTable> tables, String packageName) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Generate Database Action Models ...") {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Generate database action models ...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
ApplicationManager.getApplication().invokeLater(() ->
|
||||
WriteCommandAction.runWriteCommandAction(project, () -> {
|
||||
try {
|
||||
new GeneratorServices(project,tables,packageName).execute(indicator);
|
||||
new GeneratorServices(project,tables,packageName, GeneratorServices.Version.V2).execute(indicator);
|
||||
} catch (Exception ex) {
|
||||
GUtils.showError(project, "An error occurred during code generation: " + ex.getMessage());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.sdk.generators.actionmodels;
|
||||
|
||||
import com.intellij.database.psi.DbTable;
|
||||
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.command.WriteCommandAction;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.fileChooser.PathChooserDialog;
|
||||
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.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.sdk.generators.GUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GenerateBeanActionV3 extends AnAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY);
|
||||
if (project == null || psiElements == null || psiElements.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileChooserDescriptor descriptor = new FileChooserDescriptor(false,true,false,false,false,false);
|
||||
PathChooserDialog pathChooser = FileChooserFactory.getInstance().createPathChooser(descriptor, project, null);
|
||||
VirtualFile baseDir = GUtils.findSourceRoot(project);
|
||||
|
||||
pathChooser.choose(baseDir, virtualFiles -> {
|
||||
String packageName = GUtils.getSelectedPackage(project, virtualFiles.getFirst());
|
||||
|
||||
ArrayList<DbTable> tables = new ArrayList<>();
|
||||
for (PsiElement psiElement : psiElements) {
|
||||
if (psiElement instanceof DbTable) {
|
||||
tables.add((DbTable) psiElement);
|
||||
}
|
||||
}
|
||||
runGenerator(project, tables, packageName,"V3");
|
||||
});
|
||||
}
|
||||
|
||||
private void runGenerator(Project project,ArrayList<DbTable> tables, String packageName, String version) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Generate database action models ...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
ApplicationManager.getApplication().invokeLater(() ->
|
||||
WriteCommandAction.runWriteCommandAction(project, () -> {
|
||||
try {
|
||||
new GeneratorServices(project,tables,packageName, GeneratorServices.Version.V3).execute(indicator);
|
||||
} catch (Exception ex) {
|
||||
GUtils.showError(project, "An error occurred during code generation: " + ex.getMessage());
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.sdk.generators.actionmodels;
|
||||
|
||||
import com.intellij.database.psi.DbTable;
|
||||
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.command.WriteCommandAction;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.fileChooser.PathChooserDialog;
|
||||
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.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.sdk.generators.GUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GenerateDatasetAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY);
|
||||
if (project == null || psiElements == null || psiElements.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, false, false, false, false);
|
||||
descriptor.setTitle("Select Target Directory for Dataset XML");
|
||||
PathChooserDialog pathChooser = FileChooserFactory.getInstance().createPathChooser(descriptor, project, null);
|
||||
|
||||
//VirtualFile baseDir = GUtils.findSourceRoot(project);
|
||||
VirtualFile baseDir = project.getBaseDir();
|
||||
|
||||
pathChooser.choose(baseDir, virtualFiles -> {
|
||||
VirtualFile targetDir = virtualFiles.getFirst();
|
||||
|
||||
ArrayList<DbTable> tables = new ArrayList<>();
|
||||
for (PsiElement psiElement : psiElements) {
|
||||
if (psiElement instanceof DbTable) {
|
||||
tables.add((DbTable) psiElement);
|
||||
}
|
||||
}
|
||||
runGenerator(project, tables, targetDir);
|
||||
});
|
||||
}
|
||||
|
||||
private void runGenerator(Project project, ArrayList<DbTable> tables, VirtualFile targetDir) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Generate Dataset XML ...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
ApplicationManager.getApplication().invokeLater(() ->
|
||||
WriteCommandAction.runWriteCommandAction(project, () -> {
|
||||
try {
|
||||
new GeneratorServices(project, tables, "", GeneratorServices.Version.V2).executeDataset(targetDir, indicator);
|
||||
} catch (Exception ex) {
|
||||
GUtils.showError(project, "An error occurred during code generation: " + ex.getMessage());
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,15 @@ public class GeneratorServices {
|
||||
private final String basePackage;
|
||||
private final Project project;
|
||||
private final ArrayList<DbTable> tables;
|
||||
private final Version version;
|
||||
|
||||
public GeneratorServices(Project project, ArrayList<DbTable> tables, String basePackage) {
|
||||
public enum Version {V2,V3}
|
||||
|
||||
public GeneratorServices(Project project, ArrayList<DbTable> tables, String basePackage, Version version) {
|
||||
this.tables = tables;
|
||||
this.project = project;
|
||||
this.basePackage = basePackage;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
private void genDataModel(Template template, Map<String, Object> model, VirtualFile targetDir, String classFile, ProgressIndicator indicator) {
|
||||
@@ -111,6 +115,33 @@ public class GeneratorServices {
|
||||
}
|
||||
}
|
||||
|
||||
public void executeDataset(VirtualFile targetDir, @NotNull ProgressIndicator indicator) {
|
||||
AtomicInteger fileCount = new AtomicInteger(0);
|
||||
try {
|
||||
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
|
||||
cfg.setClassForTemplateLoading(this.getClass(), "/templates");
|
||||
cfg.setDefaultEncoding("UTF-8");
|
||||
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
|
||||
Template tmpDataset = cfg.getTemplate("dataset.ftl");
|
||||
|
||||
tables.forEach(table -> {
|
||||
Map<String, Object> model = createModelForTable(table);
|
||||
String tableName = model.get("tableName").toString();
|
||||
String fileName = GUtils.capitalize(tableName) + ".xml";
|
||||
|
||||
genDataModel(tmpDataset, model, targetDir, fileName, indicator);
|
||||
fileCount.getAndIncrement();
|
||||
});
|
||||
|
||||
String message = String.format("Generated %d dataset XML files successfully.", fileCount.get());
|
||||
GUtils.showInfo(project, "Dataset XML Generation Complete", message);
|
||||
|
||||
} catch (Exception ex) {
|
||||
GUtils.showError(project, "Generation Failed \n" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> createModelForTable(DbTable table) {
|
||||
String tableName = table.getName().toUpperCase();
|
||||
String dbSchema = table.getParent() != null ? table.getParent().getName() : "";
|
||||
@@ -123,6 +154,16 @@ public class GeneratorServices {
|
||||
model.put("className", tableName);
|
||||
model.put("dbSchema", dbSchema);
|
||||
|
||||
if (version == Version.V2) {
|
||||
model.put("db_connector", "sdk.dbutils.*");
|
||||
model.put("db_dataset", "sdk.dbutils.*");
|
||||
model.put("db_dto", "sdk.dbutils.*");
|
||||
} else {
|
||||
model.put("db_connector", "sdk.db.connector.*");
|
||||
model.put("db_dataset", "sdk.db.dataset.*");
|
||||
model.put("db_dto", "sdk.db.dto.*");
|
||||
}
|
||||
|
||||
List<Map<String, Object>> columns = new ArrayList<>();
|
||||
Set<String> primaryKeys = new HashSet<>();
|
||||
JBIterable<? extends DasTableKey> dasKeys = DasUtil.getTableKeys(table);
|
||||
@@ -133,6 +174,15 @@ public class GeneratorServices {
|
||||
}
|
||||
});
|
||||
|
||||
String entityName = tableName.toLowerCase();
|
||||
if (entityName.endsWith("_m")) {
|
||||
entityName = entityName.substring(0, entityName.length() - 2);
|
||||
} else if (entityName.endsWith("s")) {
|
||||
entityName = entityName.substring(0, entityName.length() - 1);
|
||||
}
|
||||
|
||||
final String finalEntityName = entityName;
|
||||
|
||||
JBIterable<? extends DasColumn> dasColumns = DasUtil.getColumns(table);
|
||||
dasColumns.forEach(column -> {
|
||||
Map<String, Object> colModel = new HashMap<>();
|
||||
@@ -141,6 +191,28 @@ public class GeneratorServices {
|
||||
colModel.put("name", colName);
|
||||
colModel.put("isPk", primaryKeys.contains(colName));
|
||||
colModel.put("customType", dataType);
|
||||
|
||||
// XML Specific fields
|
||||
String xmlType = "TEXT";
|
||||
if ("NUMBER".equals(dataType)) {
|
||||
xmlType = "NUMBER";
|
||||
} else if ("DATE".equals(dataType)) {
|
||||
xmlType = "DATE";
|
||||
}
|
||||
colModel.put("xmlType", xmlType);
|
||||
|
||||
int width = column.getDasType().toDataType().getLength();
|
||||
colModel.put("width", Math.max(width, 0));
|
||||
|
||||
// Label generation: Use field comment if available, otherwise fallback to generated key
|
||||
String comment = column.getComment();
|
||||
if (comment != null && !comment.isEmpty()) {
|
||||
colModel.put("label", comment);
|
||||
} else {
|
||||
String fieldPart = colName.toLowerCase();
|
||||
colModel.put("label", fieldPart);
|
||||
}
|
||||
|
||||
columns.add(colModel);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user