diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 68d16fd..440369f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,6 +12,8 @@ on:
jobs:
build:
runs-on: ubuntu-latest
+ env:
+ INTELLIJ_VERSION: '2024.2'
steps:
- name: Checkout repository
@@ -38,13 +40,9 @@ jobs:
- name: Build plugin
run: ./gradlew buildPlugin
- env:
- INTELLIJ_VERSION: '2023.1'
- name: Verify plugin
run: ./gradlew runPluginVerifier
- env:
- INTELLIJ_VERSION: '2023.1'
- name: Upload plugin artifact
uses: actions/upload-artifact@v4
diff --git a/build.gradle b/build.gradle
index 4648a28..0a48355 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,8 +3,8 @@ plugins {
id 'org.jetbrains.intellij' version '1.17.0'
}
-group 'com.github.tky0065'
-version '1.0.0'
+group = 'com.github.tky0065'
+version = '1.0.1'
repositories {
mavenCentral()
@@ -19,20 +19,51 @@ dependencies {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
}
+// Définition explicite de la version d'IntelliJ pour éviter toute confusion
+def intellijVersion = System.getenv("INTELLIJ_VERSION") ?: "2024.2"
+def intellijType = System.getenv("INTELLIJ_TYPE") ?: "IC" // IC pour Community, IU pour Ultimate
+
intellij {
- version = '2023.1'
- type = 'IC' // IntelliJ IDEA Community Edition
- plugins = ['java']
+ version.set(intellijVersion) // Utilisation de la méthode set() pour éviter les conflits
+ type.set(intellijType) // Configurable via variable d'environnement
+ plugins.set(['java'])
+ updateSinceUntilBuild.set(true)
+ downloadSources.set(true)
+}
+
+// Configuration pour supprimer les avertissements lors du build
+buildSearchableOptions {
+ enabled = false // Désactive la génération des options searchable qui produit des avertissements
+}
+
+runIde {
+ // Supprime les avertissements concernant JCEF en mode headless
+ systemProperty("ide.browser.jcef.headless.enabled", "true")
+
+ // Définit explicitement la version de JDK pour éviter les problèmes avec Java 25
+ jvmArgs("-Djdk.module.illegalAccess.silent=true")
+
+ // Ignorer les avertissements liés à la compatibilité Gradle
+ systemProperty("gradle.skip.compatibility.check", "true")
+
+ // Éviter les mises à jour automatiques qui peuvent causer des avertissements
+ systemProperty("ide.plugins.snapshot.on.unload.disable", "true")
+}
+
+// Configuration pour la publication du plugin
+publishPlugin {
+ token.set(System.getenv("PUBLISH_TOKEN") ?: "")
+ channels.set(System.getenv("PUBLISH_CHANNEL") ? [System.getenv("PUBLISH_CHANNEL")] : ["default"])
}
patchPluginXml {
changeNotes.set("""
- - 1.0.0 - Version initiale du générateur d'API
+ - 1.0.1 - Version initiale du générateur d'API
""")
- sinceBuild.set("231") // Compatible avec 2023.1+
- untilBuild.set("233.*") // Compatible jusqu'à 2023.3.x
+ sinceBuild.set("242") // Compatible depuis IntelliJ 2024.2
+ untilBuild.set("252.*") // Compatible jusqu'à 2025.2.x inclus
}
test {
diff --git a/src/main/java/com/github/tky0065/apigenerator/action/GenerateApiAction.java b/src/main/java/com/github/tky0065/apigenerator/action/GenerateApiAction.java
index ad03ae6..b75a466 100644
--- a/src/main/java/com/github/tky0065/apigenerator/action/GenerateApiAction.java
+++ b/src/main/java/com/github/tky0065/apigenerator/action/GenerateApiAction.java
@@ -26,6 +26,8 @@
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -54,6 +56,7 @@ public GenerateApiAction() {
this.existingFileService = new ExistingFileServiceImpl(loggingService);
}
+
@Override
public void update(@NotNull AnActionEvent e) {
// Active ou désactive l'action en fonction du contexte
@@ -469,8 +472,13 @@ private FileAction showFileExistsDialog(Project project, String packageName, Str
* Crée récursivement les répertoires nécessaires pour un package.
*/
private PsiDirectory createPackageDirectories(Project project, String packageName) {
- PsiDirectory baseDir = PsiManager.getInstance(project).findDirectory(
- project.getBaseDir());
+ // Utilisation de ProjectUtil.guessProjectDir au lieu de project.getBaseDir()
+ VirtualFile projectDir = com.intellij.openapi.project.ProjectUtil.guessProjectDir(project);
+ if (projectDir == null) {
+ throw new IllegalStateException("Impossible de trouver le répertoire de base du projet");
+ }
+
+ PsiDirectory baseDir = PsiManager.getInstance(project).findDirectory(projectDir);
if (baseDir == null) {
throw new IllegalStateException("Impossible de trouver le répertoire de base du projet");
}
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/ControllerGenerator.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/ControllerGenerator.java
index 31618e2..7b8b939 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/ControllerGenerator.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/ControllerGenerator.java
@@ -200,9 +200,7 @@ private void addGetAllMethod(TypeSpec.Builder classBuilder, TypeName entityType,
.addModifiers(Modifier.PUBLIC)
.addAnnotation(getMappingAnnotation)
.returns(returnType)
- .addStatement("List<$T> entities = service.findAll()", entityType)
- .addStatement("// Ici, vous devez convertir les entités en DTOs si nécessaire")
- .addStatement("return $T.ok(entities)", ClassName.get("org.springframework.http", "ResponseEntity"))
+ .addStatement("return $T.ok(service.findAll())", ClassName.get("org.springframework.http", "ResponseEntity"))
.build();
classBuilder.addMethod(getAllMethod);
@@ -222,7 +220,9 @@ private void addGetByIdMethod(TypeSpec.Builder classBuilder, TypeName entityType
.build();
ClassName pathVariable = ClassName.get("org.springframework.web.bind.annotation", "PathVariable");
+ ClassName responseEntityClass = ClassName.get("org.springframework.http", "ResponseEntity");
+ // Générer le code avec une seule instruction pour éviter les problèmes de formatage
MethodSpec getByIdMethod = MethodSpec.methodBuilder("getById")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(getMappingAnnotation)
@@ -230,9 +230,9 @@ private void addGetByIdMethod(TypeSpec.Builder classBuilder, TypeName entityType
.addAnnotation(pathVariable)
.build())
.returns(returnType)
- .addStatement("return service.findById(id)")
- .addStatement(" .map(entity -> $T.ok(entity))", ClassName.get("org.springframework.http", "ResponseEntity"))
- .addStatement(" .orElseGet(() -> $T.notFound().build())", ClassName.get("org.springframework.http", "ResponseEntity"))
+ .addCode("return service.findById(id)\n")
+ .addCode(" .map($T::ok)\n", responseEntityClass)
+ .addCode(" .orElseGet(() -> $T.notFound().build());\n", responseEntityClass)
.build();
classBuilder.addMethod(getByIdMethod);
@@ -256,11 +256,9 @@ private void addCreateMethod(TypeSpec.Builder classBuilder, TypeName entityType,
.addAnnotation(requestBody)
.build())
.returns(returnType)
- .addStatement("// Ici, vous devez convertir le DTO en entité si nécessaire")
- .addStatement("$T savedEntity = service.save(($T) dto)", entityType, entityType)
- .addStatement("// Puis reconvertir en DTO pour la réponse")
- .addStatement("return $T.created(null).body(($T) savedEntity)",
- ClassName.get("org.springframework.http", "ResponseEntity"), dtoType)
+ .addStatement("$T savedDto = service.save(dto)", dtoType)
+ .addStatement("return $T.created(null).body(savedDto)",
+ ClassName.get("org.springframework.http", "ResponseEntity"))
.build();
classBuilder.addMethod(createMethod);
@@ -281,7 +279,9 @@ private void addUpdateMethod(TypeSpec.Builder classBuilder, TypeName entityType,
ClassName pathVariable = ClassName.get("org.springframework.web.bind.annotation", "PathVariable");
ClassName requestBody = ClassName.get("org.springframework.web.bind.annotation", "RequestBody");
+ ClassName responseEntityClass = ClassName.get("org.springframework.http", "ResponseEntity");
+ // Générer le code avec une structure plus explicite pour éviter les problèmes de formatage
MethodSpec updateMethod = MethodSpec.methodBuilder("update")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(putMappingAnnotation)
@@ -292,15 +292,13 @@ private void addUpdateMethod(TypeSpec.Builder classBuilder, TypeName entityType,
.addAnnotation(requestBody)
.build())
.returns(returnType)
- .addStatement("return service.findById(id)")
- .addStatement(" .map(existingEntity -> {")
- .addStatement(" // Ici, mettre à jour l'entité existante avec les valeurs du DTO")
- .addStatement(" $T updatedEntity = service.save(existingEntity)", entityType)
- .addStatement(" return $T.ok(($T) updatedEntity)",
- ClassName.get("org.springframework.http", "ResponseEntity"), dtoType)
- .addStatement(" })")
- .addStatement(" .orElseGet(() -> $T.notFound().build())",
- ClassName.get("org.springframework.http", "ResponseEntity"))
+ .addCode("return service.findById(id)\n")
+ .addCode(" .map(existingDto -> {\n")
+ .addCode(" // Ici, vous pouvez copier les champs modifiables de dto vers existingDto si besoin\n")
+ .addCode(" $T updatedDto = service.save(dto);\n", dtoType)
+ .addCode(" return $T.ok(updatedDto);\n", responseEntityClass)
+ .addCode(" })\n")
+ .addCode(" .orElseGet(() -> $T.notFound().build());\n", responseEntityClass)
.build();
classBuilder.addMethod(updateMethod);
@@ -329,8 +327,7 @@ private void addDeleteMethod(TypeSpec.Builder classBuilder, TypeName idType) {
.build())
.returns(returnType)
.addStatement("service.deleteById(id)")
- .addStatement("return $T.noContent().build()",
- ClassName.get("org.springframework.http", "ResponseEntity"))
+ .addStatement("return $T.noContent().build()", ClassName.get("org.springframework.http", "ResponseEntity"))
.build();
classBuilder.addMethod(deleteMethod);
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/DependencyValidationServiceImpl.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/DependencyValidationServiceImpl.java
index 0f56ec6..f54ba59 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/DependencyValidationServiceImpl.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/DependencyValidationServiceImpl.java
@@ -38,7 +38,7 @@ public class DependencyValidationServiceImpl implements DependencyValidationServ
"JPA Entity", "\n jakarta.persistence\n jakarta.persistence-api\n 3.1.0\n",
"Spring Data JPA", "\n org.springframework.boot\n spring-boot-starter-data-jpa\n",
"Spring Web", "\n org.springframework.boot\n spring-boot-starter-web\n",
- "MapStruct", "\n org.mapstruct\n mapstruct\n 1.5.3.Final\n\n\n org.mapstruct\n mapstruct-processor\n 1.5.3.Final\n provided\n",
+ "MapStruct", "\n org.mapstruct\n mapstruct\n 1.6.3.Final\n\n\n org.mapstruct\n mapstruct-processor\n 1.6.3.Final\n provided\n",
"Lombok", "\n org.projectlombok\n lombok\n 1.18.28\n provided\n"
);
@@ -47,7 +47,7 @@ public class DependencyValidationServiceImpl implements DependencyValidationServ
"JPA Entity", "implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'",
"Spring Data JPA", "implementation 'org.springframework.boot:spring-boot-starter-data-jpa'",
"Spring Web", "implementation 'org.springframework.boot:spring-boot-starter-web'",
- "MapStruct", "implementation 'org.mapstruct:mapstruct:1.5.3.Final'\nannotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'",
+ "MapStruct", "implementation 'org.mapstruct:mapstruct:1.6.3'\nannotationProcessor 'org.mapstruct:mapstruct-processor:1.6.3'",
"Lombok", "compileOnly 'org.projectlombok:lombok:1.18.28'\nannotationProcessor 'org.projectlombok:lombok:1.18.28'"
);
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/DtoGenerator.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/DtoGenerator.java
index d200c4f..3050eeb 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/DtoGenerator.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/DtoGenerator.java
@@ -96,6 +96,13 @@ public String getGeneratedPackageName(EntityModel entityModel, ApiGeneratorConfi
}
private void addField(TypeSpec.Builder classBuilder, String name, TypeName typeName, boolean useLombok) {
+ // Vérifier si un champ avec ce nom existe déjà pour éviter les doublons
+ for (FieldSpec field : classBuilder.fieldSpecs) {
+ if (field.name.equals(name)) {
+ return; // Ne pas ajouter de doublons
+ }
+ }
+
FieldSpec.Builder fieldBuilder = FieldSpec.builder(typeName, name, Modifier.PRIVATE);
classBuilder.addField(fieldBuilder.build());
}
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/ExistingFileServiceImpl.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/ExistingFileServiceImpl.java
index c165f2b..d397a71 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/ExistingFileServiceImpl.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/ExistingFileServiceImpl.java
@@ -3,7 +3,6 @@
import com.github.tky0065.apigenerator.service.ExistingFileService;
import com.github.tky0065.apigenerator.service.LoggingService;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
@@ -11,9 +10,6 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -147,20 +143,24 @@ private String getFileKey(String packageName, String className) {
/**
* Trouve un fichier Java dans le projet.
*/
+
private PsiFile findFile(Project project, String packageName, String className) {
- // Convertir le package en chemin de répertoire
String packagePath = packageName.replace('.', '/');
-
- // Rechercher dans les répertoires sources du projet
PsiManager psiManager = PsiManager.getInstance(project);
- VirtualFile baseDir = project.getBaseDir();
+ // Récupérer le répertoire racine du projet
+ VirtualFile projectDir = com.intellij.openapi.project.ProjectUtil.guessProjectDir(project);
+ if (projectDir == null) {
+ return null;
+ }
+
+ PsiDirectory baseDir = psiManager.findDirectory(projectDir);
if (baseDir == null) {
return null;
}
// Chercher dans src/main/java
- VirtualFile srcDir = baseDir.findFileByRelativePath("src/main/java");
+ VirtualFile srcDir = projectDir.findFileByRelativePath("src/main/java");
if (srcDir != null) {
VirtualFile packageDir = srcDir.findFileByRelativePath(packagePath);
if (packageDir != null) {
@@ -174,6 +174,7 @@ private PsiFile findFile(Project project, String packageName, String className)
return null;
}
+
/**
* Ajoute une signature à un fichier généré.
*
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/RepositoryGenerator.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/RepositoryGenerator.java
index ea20570..a279d97 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/RepositoryGenerator.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/RepositoryGenerator.java
@@ -33,8 +33,8 @@ public String generateCode(Project project, EntityModel entityModel, ApiGenerato
ClassName repositoryAnnotation = ClassName.get("org.springframework.stereotype", "Repository");
interfaceBuilder.addAnnotation(repositoryAnnotation);
- // Ajouter des méthodes de recherche personnalisées basées sur les champs de l'entité
- addCustomQueryMethods(interfaceBuilder, entityModel);
+ // Ne pas générer de méthodes personnalisées pour éviter les doublons
+ // Spring Data JPA génère déjà automatiquement les méthodes de base
// Créer le fichier Java
JavaFile javaFile = JavaFile.builder(getGeneratedPackageName(entityModel, config), interfaceBuilder.build())
@@ -77,61 +77,6 @@ private TypeName getIdTypeName(EntityModel entityModel) {
return ClassName.get("java.lang", "Long");
}
- /**
- * Ajoute des méthodes de recherche personnalisées basées sur les champs de l'entité.
- */
- private void addCustomQueryMethods(TypeSpec.Builder interfaceBuilder, EntityModel entityModel) {
- // Ajouter findBy... pour les champs importants (non-collection, non-transient, etc.)
- for (EntityModel.EntityField field : entityModel.getFields()) {
- // Ignorer les champs qui ne sont pas adaptés pour les requêtes
- if (field.isTransient() || field.isCollection()) {
- continue;
- }
-
- // Si c'est un champ de type String, ajouter une méthode findByFieldContainingIgnoreCase
- if ("String".equals(field.getType())) {
- String methodName = "findBy" + capitalizeFirstLetter(field.getName()) + "ContainingIgnoreCase";
-
- TypeName returnType = ParameterizedTypeName.get(
- ClassName.get("java.util", "List"),
- ClassName.get(entityModel.getPackageName(), entityModel.getClassName())
- );
-
- MethodSpec method = MethodSpec.methodBuilder(methodName)
- .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
- .returns(returnType)
- .addParameter(String.class, field.getName())
- .build();
-
- interfaceBuilder.addMethod(method);
- }
- // Pour les autres types, ajouter une méthode findByField
- else {
- String methodName = "findBy" + capitalizeFirstLetter(field.getName());
-
- TypeName returnType = ParameterizedTypeName.get(
- ClassName.get("java.util", "List"),
- ClassName.get(entityModel.getPackageName(), entityModel.getClassName())
- );
-
- MethodSpec method = MethodSpec.methodBuilder(methodName)
- .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
- .returns(returnType)
- .addParameter(determineTypeName(field.getType()), field.getName())
- .build();
-
- interfaceBuilder.addMethod(method);
- }
- }
- }
-
- private String capitalizeFirstLetter(String input) {
- if (input == null || input.isEmpty()) {
- return input;
- }
- return input.substring(0, 1).toUpperCase() + input.substring(1);
- }
-
private TypeName determineTypeName(String type) {
switch (type) {
case "int": return TypeName.INT;
diff --git a/src/main/java/com/github/tky0065/apigenerator/service/impl/ServiceGenerator.java b/src/main/java/com/github/tky0065/apigenerator/service/impl/ServiceGenerator.java
index 970a3b4..c6de988 100644
--- a/src/main/java/com/github/tky0065/apigenerator/service/impl/ServiceGenerator.java
+++ b/src/main/java/com/github/tky0065/apigenerator/service/impl/ServiceGenerator.java
@@ -28,6 +28,22 @@ public String generateCode(Project project, EntityModel entityModel, ApiGenerato
String repositoryClassName = entityModel.getClassName() + config.getRepositorySuffix();
ClassName repositoryTypeName = ClassName.get(repositoryPackageName, repositoryClassName);
+ // Obtenir le nom complet de la classe DTO si elle est générée
+ TypeName dtoTypeName = null;
+ if (config.isGenerateDto()) {
+ String dtoPackageName = getDtoPackageName(entityModel, config);
+ String dtoClassName = entityModel.getClassName() + config.getDtoSuffix();
+ dtoTypeName = ClassName.get(dtoPackageName, dtoClassName);
+ }
+
+ // Obtenir le nom complet de la classe Mapper si elle est générée
+ ClassName mapperTypeName = null;
+ if (config.isGenerateDto() && config.isGenerateMapper()) {
+ String mapperPackageName = getMapperPackageName(entityModel, config);
+ String mapperClassName = entityModel.getClassName() + config.getMapperSuffix();
+ mapperTypeName = ClassName.get(mapperPackageName, mapperClassName);
+ }
+
// Créer la classe Service
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(getGeneratedClassName(entityModel, config))
.addModifiers(Modifier.PUBLIC);
@@ -41,19 +57,45 @@ public String generateCode(Project project, EntityModel entityModel, ApiGenerato
.build();
classBuilder.addField(repositoryField);
- // Ajouter un constructeur pour l'injection de dépendances
- MethodSpec constructor = MethodSpec.constructorBuilder()
- .addModifiers(Modifier.PUBLIC)
- .addParameter(repositoryTypeName, "repository")
- .addStatement("this.$N = $N", "repository", "repository")
- .build();
- classBuilder.addMethod(constructor);
+ // Ajouter l'injection du Mapper si nécessaire
+ if (mapperTypeName != null) {
+ FieldSpec mapperField = FieldSpec.builder(mapperTypeName, "mapper", Modifier.PRIVATE, Modifier.FINAL)
+ .build();
+ classBuilder.addField(mapperField);
+
+ // Modifier le constructeur pour injecter le mapper aussi
+ MethodSpec constructor = MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PUBLIC)
+ .addParameter(repositoryTypeName, "repository")
+ .addParameter(mapperTypeName, "mapper")
+ .addStatement("this.$N = $N", "repository", "repository")
+ .addStatement("this.$N = $N", "mapper", "mapper")
+ .build();
+ classBuilder.addMethod(constructor);
+ } else {
+ // Constructeur sans mapper
+ MethodSpec constructor = MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PUBLIC)
+ .addParameter(repositoryTypeName, "repository")
+ .addStatement("this.$N = $N", "repository", "repository")
+ .build();
+ classBuilder.addMethod(constructor);
+ }
- // Ajouter les méthodes CRUD
- addFindAllMethod(classBuilder, entityClassName);
- addFindByIdMethod(classBuilder, entityClassName, idType);
- addSaveMethod(classBuilder, entityClassName);
- addDeleteMethod(classBuilder, entityClassName, idType);
+ // Ajouter les méthodes CRUD en fonction de la configuration
+ if (config.isGenerateDto() && config.isGenerateMapper()) {
+ // Utiliser les mappers pour convertir entre entités et DTOs
+ addFindAllMethodWithMapper(classBuilder, entityClassName, dtoTypeName);
+ addFindByIdMethodWithMapper(classBuilder, entityClassName, dtoTypeName, idType);
+ addSaveMethodWithMapper(classBuilder, entityClassName, dtoTypeName);
+ addDeleteMethod(classBuilder, entityClassName, idType);
+ } else {
+ // Méthodes sans conversion DTO
+ addFindAllMethod(classBuilder, entityClassName);
+ addFindByIdMethod(classBuilder, entityClassName, idType);
+ addSaveMethod(classBuilder, entityClassName);
+ addDeleteMethod(classBuilder, entityClassName, idType);
+ }
// Créer le fichier Java
JavaFile javaFile = JavaFile.builder(getGeneratedPackageName(entityModel, config), classBuilder.build())
@@ -98,6 +140,38 @@ private String getRepositoryPackageName(EntityModel entityModel, ApiGeneratorCon
}
}
+ /**
+ * Obtient le nom du package pour les DTOs.
+ */
+ private String getDtoPackageName(EntityModel entityModel, ApiGeneratorConfig config) {
+ String basePackage = config.getBasePackage();
+ if (basePackage == null || basePackage.isEmpty()) {
+ basePackage = entityModel.getPackageName();
+ }
+
+ if (basePackage.endsWith(".")) {
+ return basePackage + config.getDtoPackage();
+ } else {
+ return basePackage + "." + config.getDtoPackage();
+ }
+ }
+
+ /**
+ * Obtient le nom du package pour les Mappers.
+ */
+ private String getMapperPackageName(EntityModel entityModel, ApiGeneratorConfig config) {
+ String basePackage = config.getBasePackage();
+ if (basePackage == null || basePackage.isEmpty()) {
+ basePackage = entityModel.getPackageName();
+ }
+
+ if (basePackage.endsWith(".")) {
+ return basePackage + config.getMapperPackage();
+ } else {
+ return basePackage + "." + config.getMapperPackage();
+ }
+ }
+
/**
* Détermine le type de la clé primaire de l'entité.
*/
@@ -214,4 +288,52 @@ private void addDeleteMethod(TypeSpec.Builder classBuilder, TypeName entityType,
classBuilder.addMethod(delete);
}
+
+ /**
+ * Ajoute la méthode pour récupérer toutes les entités en utilisant les mappers.
+ */
+ private void addFindAllMethodWithMapper(TypeSpec.Builder classBuilder, TypeName entityType, TypeName dtoType) {
+ TypeName returnType = ParameterizedTypeName.get(
+ ClassName.get(List.class), dtoType);
+
+ MethodSpec findAll = MethodSpec.methodBuilder("findAll")
+ .addModifiers(Modifier.PUBLIC)
+ .returns(returnType)
+ .addStatement("return repository.findAll().stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList())")
+ .build();
+
+ classBuilder.addMethod(findAll);
+ }
+
+ /**
+ * Ajoute la méthode pour trouver une entité par son ID en utilisant les mappers.
+ */
+ private void addFindByIdMethodWithMapper(TypeSpec.Builder classBuilder, TypeName entityType, TypeName dtoType, TypeName idType) {
+ TypeName returnType = ParameterizedTypeName.get(
+ ClassName.get(Optional.class), dtoType);
+
+ MethodSpec findById = MethodSpec.methodBuilder("findById")
+ .addModifiers(Modifier.PUBLIC)
+ .addParameter(idType, "id")
+ .returns(returnType)
+ .addStatement("return repository.findById(id).map(mapper::toDto)")
+ .build();
+
+ classBuilder.addMethod(findById);
+ }
+
+ /**
+ * Ajoute la méthode pour sauvegarder une entité en utilisant les mappers.
+ */
+ private void addSaveMethodWithMapper(TypeSpec.Builder classBuilder, TypeName entityType, TypeName dtoType) {
+ MethodSpec save = MethodSpec.methodBuilder("save")
+ .addModifiers(Modifier.PUBLIC)
+ .addParameter(dtoType, "dto")
+ .returns(dtoType)
+ .addStatement("$T entity = mapper.toEntity(dto)", entityType)
+ .addStatement("return mapper.toDto(repository.save(entity))", entityType)
+ .build();
+
+ classBuilder.addMethod(save);
+ }
}
diff --git a/src/main/java/com/github/tky0065/apigenerator/ui/CodePreviewComponent.java b/src/main/java/com/github/tky0065/apigenerator/ui/CodePreviewComponent.java
index 3182ed5..40dcd81 100644
--- a/src/main/java/com/github/tky0065/apigenerator/ui/CodePreviewComponent.java
+++ b/src/main/java/com/github/tky0065/apigenerator/ui/CodePreviewComponent.java
@@ -155,7 +155,7 @@ private void createControllerPreview() {
private void updateDtoPreview(ApiGeneratorConfig updatedConfig) {
CodeGenerator dtoGenerator = new DtoGenerator();
String code = dtoGenerator.generateCode(project, entityModel, updatedConfig);
- EditorFactory.getInstance().releaseEditor(dtoEditor);
+ // Suppression de l'appel redondant à releaseEditor ici, car updateEditor le fait déjà
dtoEditor = updateEditor(dtoEditor, code);
tabbedPane.setComponentAt(tabbedPane.indexOfTab("DTO"), createEditorPanel(dtoEditor));
}
@@ -166,7 +166,7 @@ private void updateDtoPreview(ApiGeneratorConfig updatedConfig) {
private void updateMapperPreview(ApiGeneratorConfig updatedConfig) {
CodeGenerator mapperGenerator = new MapperGenerator();
String code = mapperGenerator.generateCode(project, entityModel, updatedConfig);
- EditorFactory.getInstance().releaseEditor(mapperEditor);
+ // Suppression de l'appel redondant à releaseEditor
mapperEditor = updateEditor(mapperEditor, code);
tabbedPane.setComponentAt(tabbedPane.indexOfTab("Mapper"), createEditorPanel(mapperEditor));
}
@@ -177,7 +177,7 @@ private void updateMapperPreview(ApiGeneratorConfig updatedConfig) {
private void updateRepositoryPreview(ApiGeneratorConfig updatedConfig) {
CodeGenerator repositoryGenerator = new RepositoryGenerator();
String code = repositoryGenerator.generateCode(project, entityModel, updatedConfig);
- EditorFactory.getInstance().releaseEditor(repositoryEditor);
+ // Suppression de l'appel redondant à releaseEditor
repositoryEditor = updateEditor(repositoryEditor, code);
tabbedPane.setComponentAt(tabbedPane.indexOfTab("Repository"), createEditorPanel(repositoryEditor));
}
@@ -188,7 +188,7 @@ private void updateRepositoryPreview(ApiGeneratorConfig updatedConfig) {
private void updateServicePreview(ApiGeneratorConfig updatedConfig) {
CodeGenerator serviceGenerator = new ServiceGenerator();
String code = serviceGenerator.generateCode(project, entityModel, updatedConfig);
- EditorFactory.getInstance().releaseEditor(serviceEditor);
+ // Suppression de l'appel redondant à releaseEditor
serviceEditor = updateEditor(serviceEditor, code);
tabbedPane.setComponentAt(tabbedPane.indexOfTab("Service"), createEditorPanel(serviceEditor));
}
@@ -199,7 +199,7 @@ private void updateServicePreview(ApiGeneratorConfig updatedConfig) {
private void updateControllerPreview(ApiGeneratorConfig updatedConfig) {
CodeGenerator controllerGenerator = new ControllerGenerator();
String code = controllerGenerator.generateCode(project, entityModel, updatedConfig);
- EditorFactory.getInstance().releaseEditor(controllerEditor);
+ // Suppression de l'appel redondant à releaseEditor
controllerEditor = updateEditor(controllerEditor, code);
tabbedPane.setComponentAt(tabbedPane.indexOfTab("Controller"), createEditorPanel(controllerEditor));
}
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 8fbec1c..c8a41da 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -1,17 +1,23 @@
com.github.tky0065.apigenerator
- API Generator
+ Spring CRUD API Generator
tky0065
+ This plugin automatically generates a complete CRUD API from a JPA entity. It simplifies the development process by creating all necessary components for your Spring Boot application with a few clicks.
+
+ Features include:
- - Génération de DTO avec Lombok
- - Repository JPA
- - Service avec méthodes CRUD
- - Controller REST
- - Mappeurs entre entités et DTOs
+ - Generation of DTOs with Lombok annotations
+ - JPA Repository interfaces
+ - Service layer with complete CRUD methods
+ - RESTful Controllers with appropriate endpoints
+ - Entity-to-DTO mappers
+ - Custom exception handlers
+ - Basic validation setup
+
+ Save hours of boilerplate coding and focus on your business logic instead.
]]>
com.intellij.modules.platform
@@ -22,6 +28,12 @@
-
+
+
+
+