From fa928be9587e85483dbfe7e1e2f2c77a5471a8c0 Mon Sep 17 00:00:00 2001 From: Mathieu DEHARBE Date: Fri, 6 Feb 2026 14:46:29 +0100 Subject: [PATCH 1/5] adds a name to the composite modifications Signed-off-by: Mathieu DEHARBE --- .../server/entities/CompositeModificationEntity.java | 5 +++++ .../changelog/changesets/changelog_20260206T132143Z.xml | 8 ++++++++ src/main/resources/db/changelog/db.changelog-master.yaml | 3 +++ 3 files changed, 16 insertions(+) create mode 100644 src/main/resources/db/changelog/changesets/changelog_20260206T132143Z.xml diff --git a/src/main/java/org/gridsuite/modification/server/entities/CompositeModificationEntity.java b/src/main/java/org/gridsuite/modification/server/entities/CompositeModificationEntity.java index ecab41a0d..09370f8a7 100644 --- a/src/main/java/org/gridsuite/modification/server/entities/CompositeModificationEntity.java +++ b/src/main/java/org/gridsuite/modification/server/entities/CompositeModificationEntity.java @@ -27,6 +27,9 @@ @Table(name = "composite_modification") public class CompositeModificationEntity extends ModificationEntity { + @Column(name = "composite_name") + private String compositeName; + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinTable( name = "compositeModificationSubModifications", @@ -44,6 +47,7 @@ public CompositeModificationEntity(@NonNull CompositeModificationInfos composite public CompositeModificationInfos toModificationInfos() { List modificationsInfos = modifications.stream().map(ModificationEntity::toModificationInfos).toList(); return CompositeModificationInfos.builder() + .compositeName(getCompositeName()) .activated(getActivated()) .description(getDescription()) .date(getDate()) @@ -56,6 +60,7 @@ public CompositeModificationInfos toModificationInfos() { // when we go back to an empty list, dont use addAll() on the list because JPA could start // @OrderColumn to 1 instead of 0 private void assignAttributes(CompositeModificationInfos compositeModificationInfos) { + this.setCompositeName(compositeModificationInfos.getCompositeName()); modifications.clear(); modifications = compositeModificationInfos.getModifications().stream() .map(ModificationEntity::fromDTO) diff --git a/src/main/resources/db/changelog/changesets/changelog_20260206T132143Z.xml b/src/main/resources/db/changelog/changesets/changelog_20260206T132143Z.xml new file mode 100644 index 000000000..cf909ac87 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20260206T132143Z.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 22bc992fa..e6ba17e34 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -453,3 +453,6 @@ databaseChangeLog: - include: file: changesets/changelog_20251215T152152Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20260206T132143Z.xml + relativeToChangelogFile: true From 7f03a3711a501ec60ad066ce366fa47739c8e8c0 Mon Sep 17 00:00:00 2001 From: Mathieu DEHARBE Date: Fri, 6 Feb 2026 16:47:13 +0100 Subject: [PATCH 2/5] insertCompositeModificationIntoGroup Signed-off-by: Mathieu DEHARBE --- .../server/NetworkModificationController.java | 8 +++++++- .../NetworkModificationRepository.java | 14 +++++++++++++- .../server/service/NetworkModificationService.java | 9 ++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java index bc0503889..bbb971457 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java @@ -37,7 +37,7 @@ public class NetworkModificationController { private enum GroupModificationAction { - MOVE, COPY, INSERT + MOVE, COPY, INSERT, INSERT_AS_COMPOSITE } private final NetworkModificationService networkModificationService; @@ -100,6 +100,12 @@ public CompletableFuture> handleNetwo networkModificationService.duplicateModifications(targetGroupUuid, originGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); case INSERT -> networkModificationService.insertCompositeModifications(targetGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); + case INSERT_AS_COMPOSITE -> + networkModificationService.insertCompositeModificationIntoGroup( + targetGroupUuid, + modificationContextInfos.getFirst().getFirst(), + modificationContextInfos.getSecond().getFirst() + ).thenApply(ResponseEntity.ok()::body); case MOVE -> { UUID sourceGroupUuid = originGroupUuid == null ? targetGroupUuid : originGroupUuid; boolean applyModifications = canApply; diff --git a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java index 57c201a97..c7fc7b586 100644 --- a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java +++ b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java @@ -128,7 +128,7 @@ private List saveModificationInfosNonTransactional(UUID grou return saveModificationsNonTransactional(groupUuid, entities); } - public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { + public UUID createNetworkCompositeModification(@NonNull List modificationUuids, String name) { CompositeModificationInfos compositeInfos = CompositeModificationInfos.builder().modifications(List.of()).build(); CompositeModificationEntity compositeEntity = (CompositeModificationEntity) ModificationEntity.fromDTO(compositeInfos); List copyEntities = modificationRepository.findAllByIdIn(modificationUuids).stream() @@ -136,6 +136,7 @@ public UUID createNetworkCompositeModification(@NonNull List modificationU .map(ModificationEntity::fromDTO) .toList(); compositeEntity.setModifications(copyEntities); + compositeEntity.setCompositeName(name); return modificationRepository.save(compositeEntity).getId(); } @@ -765,4 +766,15 @@ public List saveCompositeModifications(@NonNull UUID targetGr // We can't return modificationInfos directly because it wouldn't have the IDs coming from the new saved entities return newEntities.stream().map(ModificationEntity::toModificationInfos).toList(); } + + @Transactional + public CompositeModificationInfos insertCompositeModificationIntoGroup(@NonNull UUID targetGroupUuid, @NonNull UUID compositeModificationUuid) { + CompositeModificationEntity oldCompositeModification = (CompositeModificationEntity) getModificationEntity(compositeModificationUuid); + List oldModificationsUuids = oldCompositeModification.getModifications().stream().map(ModificationEntity::getId).collect(Collectors.toList()); + + UUID newCompositeModificationUuid = createNetworkCompositeModification(oldModificationsUuids, "test de nom bidon"); // TODO : adds this into controller ?? + CompositeModificationEntity newCompositeModification = (CompositeModificationEntity) getModificationEntity(newCompositeModificationUuid); + saveModificationInfosNonTransactional(targetGroupUuid, List.of(newCompositeModification.toModificationInfos())); + return newCompositeModification.toModificationInfos(); + } } diff --git a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java index d0487ea21..7c4446485 100644 --- a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.modification.NetworkModificationException; +import org.gridsuite.modification.dto.CompositeModificationInfos; import org.gridsuite.modification.dto.GenerationDispatchInfos; import org.gridsuite.modification.dto.ModificationInfos; import org.gridsuite.modification.server.NetworkModificationServerException; @@ -404,9 +405,15 @@ public CompletableFuture insertCompositeModification new NetworkModificationsResult(ids, result)); } + public CompletableFuture insertCompositeModificationIntoGroup(@NonNull UUID targetGroupUuid, @NonNull UUID compositeModificationUuid, @NonNull ModificationApplicationContext applicationContext) { + CompositeModificationInfos modification = networkModificationRepository.insertCompositeModificationIntoGroup(targetGroupUuid, compositeModificationUuid); + return applyModifications(targetGroupUuid, List.of(modification), List.of(applicationContext)).thenApply(result -> + new NetworkModificationsResult(List.of(modification.getUuid()), result)); + } + @Transactional public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { - return networkModificationRepository.createNetworkCompositeModification(modificationUuids); + return networkModificationRepository.createNetworkCompositeModification(modificationUuids, null); } public Map duplicateCompositeModifications(List sourceModificationUuids) { From 5ce5826c9e4241c7aa8ff0000c27a891de69e728 Mon Sep 17 00:00:00 2001 From: Mathieu DEHARBE Date: Tue, 10 Feb 2026 17:11:12 +0100 Subject: [PATCH 3/5] updates endpoint Signed-off-by: Mathieu DEHARBE --- .../server/NetworkModificationController.java | 28 +++++++++++-------- .../NetworkModificationRepository.java | 7 +++-- .../service/NetworkModificationService.java | 14 ++++++++-- .../server/ModificationControllerTest.java | 10 +++++-- .../service/ModificationIndexationTest.java | 4 +-- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java index bbb971457..791faba0c 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java @@ -37,7 +37,10 @@ public class NetworkModificationController { private enum GroupModificationAction { - MOVE, COPY, INSERT, INSERT_AS_COMPOSITE + MOVE, + COPY, + SPLIT_COMPOSITE, // the network modifications contained into the composite modifications are extracted and inserted one by one + INSERT_COMPOSITE // the composite modifications are fully inserted as composote modifications } private final NetworkModificationService networkModificationService; @@ -89,22 +92,25 @@ public ResponseEntity> duplicateGroup(@RequestParam("groupUuid") @PutMapping(value = "/groups/{groupUuid}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "For a list of network modifications passed in body, Move them before another one or at the end of the list, or Duplicate them at the end of the list, or Insert them (composite) at the end of the list") @ApiResponse(responseCode = "200", description = "The modification list of the group has been updated.") - public CompletableFuture> handleNetworkModifications(@Parameter(description = "updated group UUID, where modifications are pasted") @PathVariable("groupUuid") UUID targetGroupUuid, - @Parameter(description = "kind of modification", required = true) @RequestParam(value = "action") GroupModificationAction action, - @Parameter(description = "the modification Uuid to move before (MOVE option, empty means moving at the end)") @RequestParam(value = "before", required = false) UUID beforeModificationUuid, - @Parameter(description = "origin group UUID, where modifications are copied or cut") @RequestParam(value = "originGroupUuid", required = false) UUID originGroupUuid, - @Parameter(description = "modifications can be applied (default is true)") @RequestParam(value = "build", required = false, defaultValue = "true") Boolean canApply, - @RequestBody Pair, List> modificationContextInfos) { + public CompletableFuture> handleNetworkModifications( + @Parameter(description = "updated group UUID, where modifications are pasted") @PathVariable("groupUuid") UUID targetGroupUuid, + @Parameter(description = "kind of modification", required = true) @RequestParam(value = "action") GroupModificationAction action, + @Parameter(description = "the modification Uuid to move before (MOVE option, empty means moving at the end)") @RequestParam(value = "before", required = false) UUID beforeModificationUuid, + @Parameter(description = "origin group UUID, where modifications are copied or cut") @RequestParam(value = "originGroupUuid", required = false) UUID originGroupUuid, + @Parameter(description = "modifications can be applied (default is true)") @RequestParam(value = "build", required = false, defaultValue = "true") Boolean canApply, + @Parameter(description = "composite modification name") @RequestParam(value = "compositeName", required = false, defaultValue = "My Composite") String compositeName, + @RequestBody Pair, List> modificationContextInfos) { return switch (action) { case COPY -> networkModificationService.duplicateModifications(targetGroupUuid, originGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); - case INSERT -> - networkModificationService.insertCompositeModifications(targetGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); - case INSERT_AS_COMPOSITE -> + case SPLIT_COMPOSITE -> + networkModificationService.splitCompositeModifications(targetGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); + case INSERT_COMPOSITE -> networkModificationService.insertCompositeModificationIntoGroup( targetGroupUuid, modificationContextInfos.getFirst().getFirst(), - modificationContextInfos.getSecond().getFirst() + modificationContextInfos.getSecond().getFirst(), + compositeName ).thenApply(ResponseEntity.ok()::body); case MOVE -> { UUID sourceGroupUuid = originGroupUuid == null ? targetGroupUuid : originGroupUuid; diff --git a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java index c7fc7b586..c9bdab462 100644 --- a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java +++ b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java @@ -768,11 +768,14 @@ public List saveCompositeModifications(@NonNull UUID targetGr } @Transactional - public CompositeModificationInfos insertCompositeModificationIntoGroup(@NonNull UUID targetGroupUuid, @NonNull UUID compositeModificationUuid) { + public CompositeModificationInfos insertCompositeModificationIntoGroup( + @NonNull UUID targetGroupUuid, + @NonNull UUID compositeModificationUuid, + @NonNull String compositeName) { CompositeModificationEntity oldCompositeModification = (CompositeModificationEntity) getModificationEntity(compositeModificationUuid); List oldModificationsUuids = oldCompositeModification.getModifications().stream().map(ModificationEntity::getId).collect(Collectors.toList()); - UUID newCompositeModificationUuid = createNetworkCompositeModification(oldModificationsUuids, "test de nom bidon"); // TODO : adds this into controller ?? + UUID newCompositeModificationUuid = createNetworkCompositeModification(oldModificationsUuids, compositeName); CompositeModificationEntity newCompositeModification = (CompositeModificationEntity) getModificationEntity(newCompositeModificationUuid); saveModificationInfosNonTransactional(targetGroupUuid, List.of(newCompositeModification.toModificationInfos())); return newCompositeModification.toModificationInfos(); diff --git a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java index 7c4446485..f10756b77 100644 --- a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java @@ -398,15 +398,23 @@ public CompletableFuture duplicateModifications(@Non new NetworkModificationsResult(ids, result)); } - public CompletableFuture insertCompositeModifications(@NonNull UUID targetGroupUuid, @NonNull List modificationsUuids, @NonNull List applicationContexts) { + /** + * all their network modifications are extracted from the composite modifications and inserted into the group + * @param modificationsUuids uuids of the composite modifications + */ + public CompletableFuture splitCompositeModifications(@NonNull UUID targetGroupUuid, @NonNull List modificationsUuids, @NonNull List applicationContexts) { List modifications = networkModificationRepository.saveCompositeModifications(targetGroupUuid, modificationsUuids); List ids = modifications.stream().map(ModificationInfos::getUuid).toList(); return applyModifications(targetGroupUuid, modifications, applicationContexts).thenApply(result -> new NetworkModificationsResult(ids, result)); } - public CompletableFuture insertCompositeModificationIntoGroup(@NonNull UUID targetGroupUuid, @NonNull UUID compositeModificationUuid, @NonNull ModificationApplicationContext applicationContext) { - CompositeModificationInfos modification = networkModificationRepository.insertCompositeModificationIntoGroup(targetGroupUuid, compositeModificationUuid); + public CompletableFuture insertCompositeModificationIntoGroup( + @NonNull UUID targetGroupUuid, + @NonNull UUID compositeModificationUuid, + @NonNull ModificationApplicationContext applicationContext, + @NonNull String compositeName) { + CompositeModificationInfos modification = networkModificationRepository.insertCompositeModificationIntoGroup(targetGroupUuid, compositeModificationUuid, compositeName); return applyModifications(targetGroupUuid, List.of(modification), List.of(applicationContext)).thenApply(result -> new NetworkModificationsResult(List.of(modification.getUuid()), result)); } diff --git a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java index 4ec138b38..68efcbc0b 100644 --- a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java +++ b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java @@ -851,8 +851,8 @@ void testNetworkCompositeModification() throws Exception { assertEquals("v1b1", ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentId()); // Insert the composite modification in the group - String bodyJson = getJsonBody(List.of(compositeModificationUuid), NetworkCreation.VARIANT_ID); - mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); + final String bodyJson = getJsonBody(List.of(compositeModificationUuid), NetworkCreation.VARIANT_ID); + mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=SPLIT_COMPOSITE").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); assertApplicationStatusOK(mvcResult); @@ -861,6 +861,12 @@ void testNetworkCompositeModification() throws Exception { List newModificationUuidList = newModificationList.stream().map(ModificationInfos::getUuid).toList(); assertEquals(modificationUuids.get(0), newModificationUuidList.get(0)); assertThat(modificationList.get(0)).recursivelyEquals(newModificationList.get(modificationsNumber)); + + // insert the same composite modification inside the same group but this time as a complete composite, not split into regular network modifications + mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT_COMPOSITE&compositeName='random name'").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); + assertApplicationStatusOK(mvcResult); + newModificationList = modificationRepository.getModifications(TEST_GROUP_ID, false, true); + assertEquals(modificationsNumber * 2 + 1, newModificationList.size()); } /** diff --git a/src/test/java/org/gridsuite/modification/server/service/ModificationIndexationTest.java b/src/test/java/org/gridsuite/modification/server/service/ModificationIndexationTest.java index 9b8e88385..b69352209 100644 --- a/src/test/java/org/gridsuite/modification/server/service/ModificationIndexationTest.java +++ b/src/test/java/org/gridsuite/modification/server/service/ModificationIndexationTest.java @@ -304,10 +304,10 @@ void testInsertCompositeModifications() { ((NetworkImpl) networkInfos.getNetwork()).getListeners().clear(); /* - Insert as composite this modification to group 2, variant 2 + Split this composite and insert the contained modifications to group 2, variant 2 */ UUID groupUuid2 = UUID.randomUUID(); - NetworkModificationsResult modificationsResult = networkModificationService.insertCompositeModifications( + NetworkModificationsResult modificationsResult = networkModificationService.splitCompositeModifications( groupUuid2, List.of(compositeUuid), List.of(new ModificationApplicationContext(networkInfos.getNetworkUuuid(), variant2, UUID.randomUUID(), UUID.randomUUID())) From d26f7cfc2cab93766b801d042422546dbf450f3f Mon Sep 17 00:00:00 2001 From: Mathieu DEHARBE Date: Tue, 10 Feb 2026 18:06:29 +0100 Subject: [PATCH 4/5] checkCompositeModificationContent in the TU Signed-off-by: Mathieu DEHARBE --- .../server/ModificationControllerTest.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java index 68efcbc0b..346c06d59 100644 --- a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java +++ b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java @@ -845,10 +845,7 @@ void testNetworkCompositeModification() throws Exception { mvcResult = mockMvc.perform(get(URI_GET_COMPOSITE_NETWORK_MODIF_CONTENT + "/network-modifications?uuids={id}&onlyMetadata=false", compositeModificationUuid)) .andExpect(status().isOk()).andReturn(); compositeModificationContent = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); - assertEquals("open", ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeName()); - assertEquals(Boolean.TRUE, ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeValue()); - assertEquals(IdentifiableType.SWITCH, ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentType()); - assertEquals("v1b1", ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentId()); + checkCompositeModificationContent(compositeModificationContent); // Insert the composite modification in the group final String bodyJson = getJsonBody(List.of(compositeModificationUuid), NetworkCreation.VARIANT_ID); @@ -863,10 +860,25 @@ void testNetworkCompositeModification() throws Exception { assertThat(modificationList.get(0)).recursivelyEquals(newModificationList.get(modificationsNumber)); // insert the same composite modification inside the same group but this time as a complete composite, not split into regular network modifications - mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT_COMPOSITE&compositeName='random name'").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); + mvcResult = runRequestAsync( + mockMvc, + put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT_COMPOSITE&compositeName='random name'") + .content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk() + ); assertApplicationStatusOK(mvcResult); newModificationList = modificationRepository.getModifications(TEST_GROUP_ID, false, true); assertEquals(modificationsNumber * 2 + 1, newModificationList.size()); + CompositeModificationInfos insertedComposite = (CompositeModificationInfos) newModificationList.stream().filter(modificationInfos -> + modificationInfos.getType().equals(COMPOSITE_MODIFICATION)).findFirst().orElseThrow(); + assertNotNull(insertedComposite); + checkCompositeModificationContent(insertedComposite.getModifications()); + } + + private static void checkCompositeModificationContent(List compositeModificationContent) { + assertEquals("open", ((EquipmentAttributeModificationInfos) compositeModificationContent.getFirst()).getEquipmentAttributeName()); + assertEquals(Boolean.TRUE, ((EquipmentAttributeModificationInfos) compositeModificationContent.getFirst()).getEquipmentAttributeValue()); + assertEquals(IdentifiableType.SWITCH, ((EquipmentAttributeModificationInfos) compositeModificationContent.getFirst()).getEquipmentType()); + assertEquals("v1b1", ((EquipmentAttributeModificationInfos) compositeModificationContent.getFirst()).getEquipmentId()); } /** @@ -909,13 +921,10 @@ void testNetworkCompositeModificationOld() throws Exception { mvcResult = mockMvc.perform(get(URI_GET_COMPOSITE_NETWORK_MODIF_CONTENT + "/network-modifications?uuids={id}&onlyMetadata=false", compositeModificationUuid)) .andExpect(status().isOk()).andReturn(); compositeModificationContent = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); - assertEquals("open", ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeName()); - assertEquals(Boolean.TRUE, ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeValue()); - assertEquals(IdentifiableType.SWITCH, ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentType()); - assertEquals("v1b1", ((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentId()); + checkCompositeModificationContent(compositeModificationContent); String bodyJson = getJsonBody(List.of(compositeModificationUuid), NetworkCreation.VARIANT_ID); // Insert the composite modification in the group - mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); + mvcResult = runRequestAsync(mockMvc, put("/v1/groups/" + TEST_GROUP_ID + "?action=SPLIT_COMPOSITE").content(bodyJson).contentType(MediaType.APPLICATION_JSON), status().isOk()); assertApplicationStatusOK(mvcResult); From 1f0171b398540132819979ed487eb9a6c1271af5 Mon Sep 17 00:00:00 2001 From: Mathieu DEHARBE Date: Wed, 11 Feb 2026 15:44:41 +0100 Subject: [PATCH 5/5] insert multiple composites Signed-off-by: Mathieu DEHARBE --- .../server/NetworkModificationController.java | 10 ++--- .../NetworkModificationRepository.java | 37 +++++++++++++------ .../service/NetworkModificationService.java | 19 +++++----- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java index 791faba0c..10f61d94b 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java @@ -98,7 +98,7 @@ public CompletableFuture> handleNetwo @Parameter(description = "the modification Uuid to move before (MOVE option, empty means moving at the end)") @RequestParam(value = "before", required = false) UUID beforeModificationUuid, @Parameter(description = "origin group UUID, where modifications are copied or cut") @RequestParam(value = "originGroupUuid", required = false) UUID originGroupUuid, @Parameter(description = "modifications can be applied (default is true)") @RequestParam(value = "build", required = false, defaultValue = "true") Boolean canApply, - @Parameter(description = "composite modification name") @RequestParam(value = "compositeName", required = false, defaultValue = "My Composite") String compositeName, + @Parameter(description = "composite modifications names") @RequestParam(value = "compositeNames", required = false) List compositeNames, @RequestBody Pair, List> modificationContextInfos) { return switch (action) { case COPY -> @@ -106,11 +106,11 @@ public CompletableFuture> handleNetwo case SPLIT_COMPOSITE -> networkModificationService.splitCompositeModifications(targetGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond()).thenApply(ResponseEntity.ok()::body); case INSERT_COMPOSITE -> - networkModificationService.insertCompositeModificationIntoGroup( + networkModificationService.insertCompositeModificationsIntoGroup( targetGroupUuid, - modificationContextInfos.getFirst().getFirst(), - modificationContextInfos.getSecond().getFirst(), - compositeName + modificationContextInfos.getFirst(), + modificationContextInfos.getSecond(), + compositeNames ).thenApply(ResponseEntity.ok()::body); case MOVE -> { UUID sourceGroupUuid = originGroupUuid == null ? targetGroupUuid : originGroupUuid; diff --git a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java index c9bdab462..f9abd9daf 100644 --- a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java +++ b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java @@ -128,7 +128,7 @@ private List saveModificationInfosNonTransactional(UUID grou return saveModificationsNonTransactional(groupUuid, entities); } - public UUID createNetworkCompositeModification(@NonNull List modificationUuids, String name) { + public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { CompositeModificationInfos compositeInfos = CompositeModificationInfos.builder().modifications(List.of()).build(); CompositeModificationEntity compositeEntity = (CompositeModificationEntity) ModificationEntity.fromDTO(compositeInfos); List copyEntities = modificationRepository.findAllByIdIn(modificationUuids).stream() @@ -136,10 +136,20 @@ public UUID createNetworkCompositeModification(@NonNull List modificationU .map(ModificationEntity::fromDTO) .toList(); compositeEntity.setModifications(copyEntities); - compositeEntity.setCompositeName(name); return modificationRepository.save(compositeEntity).getId(); } + public UUID cloneCompositeModification(@NonNull UUID compositeModificationUuid, String name) { + CompositeModificationInfos newCompositeInfos = CompositeModificationInfos.builder().modifications(List.of()).build(); + CompositeModificationEntity newCompositeEntity = (CompositeModificationEntity) ModificationEntity.fromDTO(newCompositeInfos); + List copiedModifications = getCompositeModificationsInfosNonTransactional(List.of(compositeModificationUuid)).stream() + .map(ModificationEntity::fromDTO) + .toList(); + newCompositeEntity.setModifications(copiedModifications); + newCompositeEntity.setCompositeName(name); + return modificationRepository.save(newCompositeEntity).getId(); + } + public void updateCompositeModification(@NonNull UUID compositeUuid, @NonNull List modificationUuids) { ModificationEntity modificationEntity = modificationRepository.findById(compositeUuid) .orElseThrow(() -> new NetworkModificationException(MODIFICATION_NOT_FOUND, String.format(MODIFICATION_NOT_FOUND_MESSAGE, compositeUuid))); @@ -768,16 +778,19 @@ public List saveCompositeModifications(@NonNull UUID targetGr } @Transactional - public CompositeModificationInfos insertCompositeModificationIntoGroup( + public List insertCompositeModificationsIntoGroup( @NonNull UUID targetGroupUuid, - @NonNull UUID compositeModificationUuid, - @NonNull String compositeName) { - CompositeModificationEntity oldCompositeModification = (CompositeModificationEntity) getModificationEntity(compositeModificationUuid); - List oldModificationsUuids = oldCompositeModification.getModifications().stream().map(ModificationEntity::getId).collect(Collectors.toList()); - - UUID newCompositeModificationUuid = createNetworkCompositeModification(oldModificationsUuids, compositeName); - CompositeModificationEntity newCompositeModification = (CompositeModificationEntity) getModificationEntity(newCompositeModificationUuid); - saveModificationInfosNonTransactional(targetGroupUuid, List.of(newCompositeModification.toModificationInfos())); - return newCompositeModification.toModificationInfos(); + @NonNull List compositeModificationsUuids, + @NonNull List compositeNames) { + List newCompositeModifications = new ArrayList<>(); + for (int i = 0; i < Math.min(compositeNames.size(), compositeModificationsUuids.size()); i++) { + UUID newCompositeModificationUuid = cloneCompositeModification(compositeModificationsUuids.get(i), compositeNames.get(i)); // ici c'est fait orderonné par modification order plutôt que UUID + newCompositeModifications.add((CompositeModificationEntity) getModificationEntity(newCompositeModificationUuid)); + } + List modifs = newCompositeModifications.stream() + .map(modif -> (ModificationInfos) modif.toModificationInfos()) + .toList(); + List newEntities = saveModificationInfosNonTransactional(targetGroupUuid, modifs); + return newEntities.stream().map(ModificationEntity::toModificationInfos).toList(); } } diff --git a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java index f10756b77..415717415 100644 --- a/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/modification/server/service/NetworkModificationService.java @@ -19,7 +19,6 @@ import org.apache.commons.lang3.StringUtils; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.modification.NetworkModificationException; -import org.gridsuite.modification.dto.CompositeModificationInfos; import org.gridsuite.modification.dto.GenerationDispatchInfos; import org.gridsuite.modification.dto.ModificationInfos; import org.gridsuite.modification.server.NetworkModificationServerException; @@ -409,19 +408,21 @@ public CompletableFuture splitCompositeModifications new NetworkModificationsResult(ids, result)); } - public CompletableFuture insertCompositeModificationIntoGroup( + public CompletableFuture insertCompositeModificationsIntoGroup( @NonNull UUID targetGroupUuid, - @NonNull UUID compositeModificationUuid, - @NonNull ModificationApplicationContext applicationContext, - @NonNull String compositeName) { - CompositeModificationInfos modification = networkModificationRepository.insertCompositeModificationIntoGroup(targetGroupUuid, compositeModificationUuid, compositeName); - return applyModifications(targetGroupUuid, List.of(modification), List.of(applicationContext)).thenApply(result -> - new NetworkModificationsResult(List.of(modification.getUuid()), result)); + @NonNull List compositeModificationUuids, + @NonNull List applicationContexts, + @NonNull List compositeNames) { + List modifications = networkModificationRepository.insertCompositeModificationsIntoGroup( + targetGroupUuid, compositeModificationUuids, compositeNames); + List ids = modifications.stream().map(ModificationInfos::getUuid).toList(); + return applyModifications(targetGroupUuid, modifications, applicationContexts).thenApply(result -> + new NetworkModificationsResult(ids, result)); } @Transactional public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { - return networkModificationRepository.createNetworkCompositeModification(modificationUuids, null); + return networkModificationRepository.createNetworkCompositeModification(modificationUuids); } public Map duplicateCompositeModifications(List sourceModificationUuids) {