diff --git a/src/main/java/tech/jhipster/lite/module/domain/properties/JHipsterModuleProperties.java b/src/main/java/tech/jhipster/lite/module/domain/properties/JHipsterModuleProperties.java index cfb402e43f7..07a9e1ded1b 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/properties/JHipsterModuleProperties.java +++ b/src/main/java/tech/jhipster/lite/module/domain/properties/JHipsterModuleProperties.java @@ -2,8 +2,10 @@ import java.time.Instant; import java.time.format.DateTimeParseException; +import java.util.Collection; import java.util.Map; import tech.jhipster.lite.module.domain.Indentation; +import tech.jhipster.lite.module.domain.JHipsterModuleSlug; import tech.jhipster.lite.module.domain.javadependency.Version; import tech.jhipster.lite.shared.error.domain.Assert; @@ -21,6 +23,8 @@ public class JHipsterModuleProperties { private final JHipsterProjectFolder projectFolder; private final boolean commitModule; private final JHipsterModuleParameters parameters; + private final Collection newModules; + private final Collection alreadyApplied; private final Indentation indentation; private final JHipsterBasePackage basePackage; @@ -30,10 +34,18 @@ public class JHipsterModuleProperties { private final SpringConfigurationFormat springConfigurationFormat; private final Version javaVersion = new Version("21"); - public JHipsterModuleProperties(String projectFolder, boolean commitModule, Map parameters) { + public JHipsterModuleProperties( + String projectFolder, + boolean commitModule, + Map parameters, + Collection newModules, + Collection alreadyApplied + ) { this.projectFolder = new JHipsterProjectFolder(projectFolder); this.commitModule = commitModule; this.parameters = new JHipsterModuleParameters(parameters); + this.newModules = newModules; + this.alreadyApplied = alreadyApplied; indentation = Indentation.from(this.parameters.getOrDefault(INDENTATION_PARAMETER, null, Integer.class)); basePackage = new JHipsterBasePackage(this.parameters.getOrDefault(BASE_PACKAGE_PARAMETER, null, String.class)); @@ -61,6 +73,18 @@ public String getString(String key) { return parameters.get(key, String.class); } + public Collection getNewModules() { + return newModules; + } + + public Collection getAlreadyAppliedModules() { + return alreadyApplied; + } + + public boolean isAppliedOrBeingApplied(JHipsterModuleSlug name) { + return alreadyApplied.contains(name) || newModules.contains(name); + } + public String getOrDefaultString(String key, String defaultValue) { Assert.notBlank("defaultValue", defaultValue); diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/ModulesResource.java b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/ModulesResource.java index bd7a102419e..191ff26c5dc 100644 --- a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/ModulesResource.java +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/ModulesResource.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -15,7 +16,9 @@ import tech.jhipster.lite.module.domain.JHipsterModuleSlug; import tech.jhipster.lite.module.domain.JHipsterModuleToApply; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; +import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource; +import tech.jhipster.lite.project.application.ProjectsApplicationService; import tech.jhipster.lite.shared.projectfolder.domain.ProjectFolder; @RestController @@ -25,13 +28,19 @@ class ModulesResource { private final JHipsterModulesApplicationService modules; private final ProjectFolder projectFolder; + private final ProjectsApplicationService projectsApplicationService; private final RestJHipsterModules modulesList; private final RestJHipsterLandscape modulesLandscape; - public ModulesResource(JHipsterModulesApplicationService modules, ProjectFolder projectFolder) { + public ModulesResource( + JHipsterModulesApplicationService modules, + ProjectFolder projectFolder, + ProjectsApplicationService projectsApplicationService + ) { this.modules = modules; this.projectFolder = projectFolder; + this.projectsApplicationService = projectsApplicationService; modulesList = RestJHipsterModules.from(modules.resources()); modulesLandscape = RestJHipsterLandscape.from(modules.landscape()); @@ -52,14 +61,19 @@ public ResponseEntity modulesLandscape() { @PostMapping("apply-patches") @Operation(summary = "Apply multiple modules patches") public void applyPatches(@RequestBody @Validated RestJHipsterModulesToApply modulesToApply) { - modules.apply(modulesToApply.toDomain(projectFolder)); + var folder = create(modulesToApply.getProperties().getProjectFolder()); + var alreadyApplied = getAlreadyAppliedModules(folder); + modules.apply(modulesToApply.toDomain(projectFolder, alreadyApplied)); } @Hidden @PostMapping("modules/{slug}/apply-patch") public void applyPatch(@RequestBody @Validated RestJHipsterModuleProperties restProperties, @PathVariable("slug") String slug) { - JHipsterModuleProperties properties = restProperties.toDomain(projectFolder); - modules.apply(new JHipsterModuleToApply(new JHipsterModuleSlug(slug), properties)); + var module = new JHipsterModuleSlug(slug); + var folder = create(restProperties.getProjectFolder()); + var alreadyApplied = getAlreadyAppliedModules(folder); + JHipsterModuleProperties properties = restProperties.toDomain(projectFolder, List.of(module), alreadyApplied); + modules.apply(new JHipsterModuleToApply(module, properties)); } @Hidden @@ -68,4 +82,16 @@ public RestJHipsterModulePropertiesDefinition propertiesDefinition(@PathVariable JHipsterModuleResource module = modules.resources().get(new JHipsterModuleSlug(slug)); return RestJHipsterModulePropertiesDefinition.from(module.propertiesDefinition()); } + + private List getAlreadyAppliedModules(JHipsterProjectFolder userSpecifiedProjectFolder) { + var moduleNames = projectsApplicationService.getAppliedModules(userSpecifiedProjectFolder); + return moduleNames.stream().map(JHipsterModuleSlug::new).toList(); + } + + private JHipsterProjectFolder create(String folderPath) { + if (projectFolder.isInvalid(folderPath)) { + throw new InvalidProjectFolderException(); + } + return new JHipsterProjectFolder(folderPath); + } } diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModuleProperties.java b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModuleProperties.java index fa13677222b..bd9996e90f0 100644 --- a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModuleProperties.java +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModuleProperties.java @@ -3,7 +3,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; +import java.util.Collection; import java.util.Map; +import tech.jhipster.lite.module.domain.JHipsterModuleSlug; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; import tech.jhipster.lite.shared.error.domain.Assert; import tech.jhipster.lite.shared.projectfolder.domain.ProjectFolder; @@ -24,12 +26,18 @@ class RestJHipsterModuleProperties { this.parameters = parameters; } - public JHipsterModuleProperties toDomain(ProjectFolder jHipsterProjectFolderFactory) { + public JHipsterModuleProperties toDomain( + ProjectFolder jHipsterProjectFolderFactory, + Collection newModules, + Collection alreadyApplied + ) { Assert.notNull("jHipsterProjectFolderFactory", jHipsterProjectFolderFactory); + Assert.notNull("newModules", newModules); + Assert.notNull("alreadyApplied", alreadyApplied); assertValidProjectFolder(jHipsterProjectFolderFactory); - return new JHipsterModuleProperties(getProjectFolder(), isCommit(), getParameters()); + return new JHipsterModuleProperties(getProjectFolder(), isCommit(), getParameters(), newModules, alreadyApplied); } private void assertValidProjectFolder(ProjectFolder jHipsterProjectFolderFactory) { diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApply.java b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApply.java index 0c873c8cf08..f801f09c506 100644 --- a/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApply.java +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApply.java @@ -24,8 +24,9 @@ class RestJHipsterModulesToApply { this.properties = properties; } - public JHipsterModulesToApply toDomain(ProjectFolder projectFolder) { - return new JHipsterModulesToApply(getModules().stream().map(JHipsterModuleSlug::new).toList(), properties.toDomain(projectFolder)); + public JHipsterModulesToApply toDomain(ProjectFolder projectFolder, Collection alreadyApplied) { + var newModules = getModules().stream().map(JHipsterModuleSlug::new).toList(); + return new JHipsterModulesToApply(newModules, properties.toDomain(projectFolder, newModules, alreadyApplied)); } @NotEmpty diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/javadependency/gradle/GradleCommandHandler.java b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/javadependency/gradle/GradleCommandHandler.java index f455d38090d..756f1b133c1 100644 --- a/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/javadependency/gradle/GradleCommandHandler.java +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/javadependency/gradle/GradleCommandHandler.java @@ -420,7 +420,7 @@ private void addFileToProject(JHipsterSource source, JHipsterDestination destina } private JHipsterModuleContext context() { - JHipsterModuleProperties properties = new JHipsterModuleProperties(projectFolder.get(), false, null); + JHipsterModuleProperties properties = new JHipsterModuleProperties(projectFolder.get(), false, null, List.of(), List.of()); return JHipsterModuleContext.builder(moduleBuilder(properties)).build(); } diff --git a/src/main/java/tech/jhipster/lite/project/application/ProjectsApplicationService.java b/src/main/java/tech/jhipster/lite/project/application/ProjectsApplicationService.java index 75fa74ddbf1..765beed2614 100644 --- a/src/main/java/tech/jhipster/lite/project/application/ProjectsApplicationService.java +++ b/src/main/java/tech/jhipster/lite/project/application/ProjectsApplicationService.java @@ -1,6 +1,8 @@ package tech.jhipster.lite.project.application; +import java.util.Collection; import org.springframework.stereotype.Service; +import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; import tech.jhipster.lite.project.domain.ProjectPath; import tech.jhipster.lite.project.domain.ProjectsRepository; import tech.jhipster.lite.project.domain.download.Project; @@ -39,4 +41,8 @@ public void append(ProjectActionToAppend actionToAppend) { public ProjectHistory getHistory(ProjectPath path) { return projects.getHistory(path); } + + public Collection getAppliedModules(JHipsterProjectFolder projectFolder) { + return projects.getHistory(new ProjectPath(projectFolder.folder())).getAppliedModules(); + } } diff --git a/src/main/java/tech/jhipster/lite/project/domain/history/ProjectHistory.java b/src/main/java/tech/jhipster/lite/project/domain/history/ProjectHistory.java index 00825c136a2..3a9a94efbee 100644 --- a/src/main/java/tech/jhipster/lite/project/domain/history/ProjectHistory.java +++ b/src/main/java/tech/jhipster/lite/project/domain/history/ProjectHistory.java @@ -41,4 +41,8 @@ public Collection actions() { public ModuleParameters latestProperties() { return actions.stream().map(ProjectAction::parameters).reduce(ModuleParameters.EMPTY, ModuleParameters::merge); } + + public Collection getAppliedModules() { + return actions.stream().map(ProjectAction::module).map(ModuleSlug::slug).toList(); + } } diff --git a/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java b/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java index 4befcfda4d0..4bab173b239 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java +++ b/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java @@ -3,8 +3,10 @@ import static tech.jhipster.lite.module.domain.JHipsterModule.*; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tech.jhipster.lite.TestFileUtils; @@ -254,7 +256,7 @@ public static JHipsterModuleBuilder emptyModuleBuilder() { } public static JHipsterModuleProperties testModuleProperties() { - return new JHipsterModuleProperties(TestFileUtils.tmpDirForTest(), true, null); + return new JHipsterModuleProperties(TestFileUtils.tmpDirForTest(), true, null, List.of(), List.of()); } public static JavaDependenciesVersions currentJavaDependenciesVersion() { @@ -298,7 +300,9 @@ public static JHipsterModuleProperties allProperties() { true, "optionalBoolean", true - ) + ), + List.of(), + List.of() ); } @@ -422,13 +426,17 @@ public static MavenPlugin asciidoctorPlugin() { } public static JHipsterModulesToApply modulesToApply() { + var maven = moduleSlug("maven-java"); + var init = moduleSlug("init"); return new JHipsterModulesToApply( - List.of(moduleSlug("maven-java"), moduleSlug("init")), + List.of(maven, init), propertiesBuilder("/dummy") .projectName("Chips Project") .basePackage("tech.jhipster.chips") .put("baseName", "chips") .put("serverPort", 8080) + .module(maven) + .module(init) .build() ); } @@ -454,6 +462,8 @@ public static final class JHipsterModulePropertiesBuilder { private boolean commitModules = false; private final String projectFolder; private final Map properties = new HashMap<>(); + private final Set newModules = new HashSet<>(); + private final Set alreadyApplied = new HashSet<>(); private JHipsterModulePropertiesBuilder(String projectFolder) { this.projectFolder = projectFolder; @@ -483,6 +493,18 @@ public JHipsterModulePropertiesBuilder projectName(String projectName) { return this; } + public JHipsterModulePropertiesBuilder module(JHipsterModuleSlug module) { + newModules.add(module); + + return this; + } + + public JHipsterModulePropertiesBuilder alreadyApplied(JHipsterModuleSlug module) { + alreadyApplied.add(module); + + return this; + } + public JHipsterModulePropertiesBuilder put(String key, Object value) { properties.put(key, value); @@ -490,7 +512,7 @@ public JHipsterModulePropertiesBuilder put(String key, Object value) { } public JHipsterModuleProperties build() { - return new JHipsterModuleProperties(projectFolder, commitModules, properties); + return new JHipsterModuleProperties(projectFolder, commitModules, properties, newModules, alreadyApplied); } } } diff --git a/src/test/java/tech/jhipster/lite/module/domain/properties/JHipsterModulePropertiesTest.java b/src/test/java/tech/jhipster/lite/module/domain/properties/JHipsterModulePropertiesTest.java index 0b2a45c6246..3468c5fd754 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/properties/JHipsterModulePropertiesTest.java +++ b/src/test/java/tech/jhipster/lite/module/domain/properties/JHipsterModulePropertiesTest.java @@ -4,6 +4,7 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -193,7 +194,9 @@ private JHipsterModuleProperties properties() { return new JHipsterModuleProperties( "/tmp/folder", false, - Map.of("string", "value", "boolean", true, "integer", 42, "blank", " ", "instant", today.toString()) + Map.of("string", "value", "boolean", true, "integer", 42, "blank", " ", "instant", today.toString()), + List.of(), + List.of() ); } } diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulePropertiesTest.java b/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulePropertiesTest.java index fcfbd5b60f7..4df87b39419 100644 --- a/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulePropertiesTest.java +++ b/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulePropertiesTest.java @@ -1,10 +1,12 @@ package tech.jhipster.lite.module.infrastructure.primary; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static tech.jhipster.lite.module.domain.JHipsterModulesFixture.*; +import static tech.jhipster.lite.module.domain.JHipsterModulesFixture.allProperties; +import java.util.List; import org.junit.jupiter.api.Test; import tech.jhipster.lite.JsonHelper; import tech.jhipster.lite.UnitTest; @@ -20,13 +22,15 @@ void shouldNotConvertToPropertiesWithInvalidProjectFolder() { when(jHipsterProjectFolderFactory.isInvalid("/test")).thenReturn(true); assertThatThrownBy( - () -> JsonHelper.readFromJson(json(), RestJHipsterModuleProperties.class).toDomain(jHipsterProjectFolderFactory) + () -> JsonHelper.readFromJson(json(), RestJHipsterModuleProperties.class).toDomain(jHipsterProjectFolderFactory, List.of(), List.of()) ).isExactlyInstanceOf(InvalidProjectFolderException.class); } @Test void shouldConvertToProperties() { - assertThat(JsonHelper.readFromJson(json(), RestJHipsterModuleProperties.class).toDomain(jHipsterProjectFolderFactory)) + assertThat( + JsonHelper.readFromJson(json(), RestJHipsterModuleProperties.class).toDomain(jHipsterProjectFolderFactory, List.of(), List.of()) + ) .usingRecursiveComparison() .isEqualTo(allProperties()); } diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApplyTest.java b/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApplyTest.java index 972e4022a5c..02f93619039 100644 --- a/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApplyTest.java +++ b/src/test/java/tech/jhipster/lite/module/infrastructure/primary/RestJHipsterModulesToApplyTest.java @@ -18,7 +18,7 @@ class RestJHipsterModulesToApplyTest { @Test void shouldDeserializeFromJson() { - assertThat(JsonHelper.readFromJson(json(), RestJHipsterModulesToApply.class).toDomain(projectFolder)) + assertThat(JsonHelper.readFromJson(json(), RestJHipsterModulesToApply.class).toDomain(projectFolder, List.of())) .usingRecursiveComparison() .isEqualTo(JHipsterModulesFixture.modulesToApply()); }