diff --git a/src/main/java/org/gridsuite/study/server/StudyConstants.java b/src/main/java/org/gridsuite/study/server/StudyConstants.java index 57a9737b6..81860d968 100644 --- a/src/main/java/org/gridsuite/study/server/StudyConstants.java +++ b/src/main/java/org/gridsuite/study/server/StudyConstants.java @@ -119,8 +119,11 @@ public enum SldDisplayMode { public enum ModificationsActionType { 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 composite modifications + } + + public enum CompositeModificationsActionType { + SPLIT, // the network modifications contained into the composite modifications are extracted and inserted one by one + INSERT // the composite modifications are fully inserted as composite modifications } public enum Severity { diff --git a/src/main/java/org/gridsuite/study/server/controller/StudyController.java b/src/main/java/org/gridsuite/study/server/controller/StudyController.java index 6a0d09323..75f33edeb 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -658,14 +658,14 @@ public ResponseEntity moveOrCopyModifications(@PathVariable("studyUuid") U @RequestParam("action") ModificationsActionType action, @RequestParam("originStudyUuid") UUID originStudyUuid, @RequestParam("originNodeUuid") UUID originNodeUuid, - @RequestBody List modificationsToCopyInfos, + @RequestBody List modificationsToCopyUuidList, @RequestHeader(HEADER_USER_ID) String userId) { studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); studyService.assertIsStudyAndNodeExist(originStudyUuid, originNodeUuid); studyService.assertCanUpdateNodeInStudy(studyUuid, nodeUuid); switch (action) { - case COPY, SPLIT_COMPOSITE, INSERT_COMPOSITE: - handleDuplicateOrInsertNetworkModifications(studyUuid, nodeUuid, originStudyUuid, originNodeUuid, modificationsToCopyInfos, userId, action); + case COPY: + handleDuplicateNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyUuidList, userId); break; case MOVE: // we don't cut - paste modifications from different studies @@ -674,18 +674,44 @@ public ResponseEntity moveOrCopyModifications(@PathVariable("studyUuid") U } studyService.assertNoBlockedNodeInStudy(studyUuid, originNodeUuid); studyService.assertNoBlockedNodeInStudy(studyUuid, nodeUuid); - List modificationsToCopyInfosUuids = modificationsToCopyInfos.stream().map(ModificationsToCopyInfos::getUuid).toList(); - rebuildNodeService.moveNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyInfosUuids, userId); + rebuildNodeService.moveNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyUuidList, userId); break; } return ResponseEntity.ok().build(); } - private void handleDuplicateOrInsertNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, UUID originStudyUuid, UUID originNodeUuid, List modificationsToCopy, String userId, ModificationsActionType action) { + /** + * @param modificationsToInsert pair of the composite uuid and its name + */ + @PutMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/composite-modifications", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "For a list of composite network modifications passed in body, insert them into the target node") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The composite modification list has been inserted.")}) + public ResponseEntity insertCompositeModifications(@PathVariable("studyUuid") UUID studyUuid, + @PathVariable("nodeUuid") UUID nodeUuid, + @RequestParam("action") CompositeModificationsActionType action, + @RequestBody List> modificationsToInsert, + @RequestHeader(HEADER_USER_ID) String userId) { + studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); + studyService.assertCanUpdateNodeInStudy(studyUuid, nodeUuid); + handleInsertCompositeNetworkModifications(studyUuid, nodeUuid, modificationsToInsert, userId, action); + return ResponseEntity.ok().build(); + } + + private void handleInsertCompositeNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, List> modificationsToCopy, String userId, CompositeModificationsActionType action) { + studyService.assertNoBlockedNodeInStudy(targetStudyUuid, targetNodeUuid); + studyService.invalidateNodeTreeWithLF(targetStudyUuid, targetNodeUuid); + try { + studyService.insertCompositeNetworkModifications(targetStudyUuid, targetNodeUuid, modificationsToCopy, userId, action); + } finally { + studyService.unblockNodeTree(targetStudyUuid, targetNodeUuid); + } + } + + private void handleDuplicateNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, UUID originNodeUuid, List modificationsToCopyUuidList, String userId) { studyService.assertNoBlockedNodeInStudy(targetStudyUuid, targetNodeUuid); studyService.invalidateNodeTreeWithLF(targetStudyUuid, targetNodeUuid); try { - studyService.duplicateOrInsertNetworkModifications(targetStudyUuid, targetNodeUuid, originStudyUuid, originNodeUuid, modificationsToCopy, userId, action); + studyService.duplicateNetworkModifications(targetStudyUuid, targetNodeUuid, originNodeUuid, modificationsToCopyUuidList, userId); } finally { studyService.unblockNodeTree(targetStudyUuid, targetNodeUuid); } diff --git a/src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java b/src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java deleted file mode 100644 index c925d6a69..000000000 --- a/src/main/java/org/gridsuite/study/server/dto/ModificationsToCopyInfos.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2026, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package org.gridsuite.study.server.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.UUID; - -/** - * @author Mathieu Deharbe - */ -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Builder -public class ModificationsToCopyInfos { - private UUID uuid; - - private String compositeName; -} diff --git a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java index 6a056ce60..ad2eb3a5a 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -12,7 +12,6 @@ import org.gridsuite.study.server.RemoteServicesProperties; import org.gridsuite.study.server.StudyConstants; import org.gridsuite.study.server.dto.BuildInfos; -import org.gridsuite.study.server.dto.ModificationsToCopyInfos; import org.gridsuite.study.server.dto.NodeReceiver; import org.gridsuite.study.server.dto.modification.ModificationApplicationContext; import org.gridsuite.study.server.dto.modification.NetworkModificationMetadata; @@ -46,6 +45,7 @@ public class NetworkModificationService { private static final String DELIMITER = "/"; + private static final String COMPOSITE_PATH = "network-composite-modifications" + DELIMITER; private static final String GROUP_PATH = "groups" + DELIMITER + "{groupUuid}"; private static final String NETWORK_MODIFICATIONS_PATH = "network-modifications"; private static final String NETWORK_MODIFICATIONS_COUNT_PATH = "network-modifications-count"; @@ -257,7 +257,7 @@ public void stopBuild(@NonNull UUID nodeUuid, @NonNull UUID rootNetworkUuid) { restTemplate.put(getNetworkModificationServerURI(false) + path, null); } - public NetworkModificationsResult moveModifications(UUID originGroupUuid, UUID targetGroupUuid, UUID beforeUuid, Pair, List> modificationContextInfos, boolean buildTargetNode) { + public NetworkModificationsResult moveModifications(UUID originGroupUuid, UUID targetGroupUuid, UUID beforeUuid, Pair, List> modificationContextInfos, boolean buildTargetNode) { var path = UriComponentsBuilder.fromPath(GROUP_PATH) .queryParam(QUERY_PARAM_ACTION, ModificationsActionType.MOVE.name()) .queryParam("originGroupUuid", originGroupUuid) @@ -268,7 +268,7 @@ public NetworkModificationsResult moveModifications(UUID originGroupUuid, UUID t HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity, List>> httpEntity = new HttpEntity<>(modificationContextInfos, headers); + HttpEntity, List>> httpEntity = new HttpEntity<>(modificationContextInfos, headers); return restTemplate.exchange( getNetworkModificationServerURI(false) + path.buildAndExpand(targetGroupUuid).toUriString(), @@ -277,13 +277,31 @@ public NetworkModificationsResult moveModifications(UUID originGroupUuid, UUID t NetworkModificationsResult.class).getBody(); } - public NetworkModificationsResult duplicateOrInsertModifications(UUID groupUuid, ModificationsActionType action, - Pair, List> modificationContextInfos) { - return handleModifications(groupUuid, null, action, modificationContextInfos); + public NetworkModificationsResult duplicateModifications(UUID groupUuid, + Pair, List> modificationContextInfos) { + return handleModifications(groupUuid, null, ModificationsActionType.COPY, modificationContextInfos); + } + + public NetworkModificationsResult insertCompositeModifications(UUID groupUuid, + CompositeModificationsActionType action, + Pair>, List> modificationContextInfos) { + var path = UriComponentsBuilder.fromPath(COMPOSITE_PATH + GROUP_PATH) + .queryParam(QUERY_PARAM_ACTION, action.name()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity>, List>> httpEntity = new HttpEntity<>(modificationContextInfos, headers); + + return restTemplate.exchange( + getNetworkModificationServerURI(false) + path.buildAndExpand(groupUuid).toUriString(), + HttpMethod.PUT, + httpEntity, + NetworkModificationsResult.class + ).getBody(); } private NetworkModificationsResult handleModifications(UUID groupUuid, UUID originGroupUuid, ModificationsActionType action, - Pair, List> modificationContextInfos) { + Pair, List> modificationContextInfos) { var path = UriComponentsBuilder.fromPath(GROUP_PATH) .queryParam(QUERY_PARAM_ACTION, action.name()); @@ -293,7 +311,7 @@ private NetworkModificationsResult handleModifications(UUID groupUuid, UUID orig HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity, List>> httpEntity = new HttpEntity<>(modificationContextInfos, headers); + HttpEntity, List>> httpEntity = new HttpEntity<>(modificationContextInfos, headers); return restTemplate.exchange( getNetworkModificationServerURI(false) + path.buildAndExpand(groupUuid).toUriString(), @@ -323,7 +341,7 @@ public Map duplicateModificationsGroup(UUID sourceGroupUuid, UUID gr ).getBody(); } - public NetworkModificationsResult duplicateModificationsFromGroup(UUID groupUuid, UUID originGroupUuid, Pair, List> modificationContextInfos) { + public NetworkModificationsResult duplicateModificationsFromGroup(UUID groupUuid, UUID originGroupUuid, Pair, List> modificationContextInfos) { return handleModifications(groupUuid, originGroupUuid, StudyConstants.ModificationsActionType.COPY, modificationContextInfos); } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index 1fbbf6f18..7ae68b0a0 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2345,7 +2345,14 @@ public RootNetworkIndexationStatus getRootNetworkIndexationStatus(UUID studyUuid } @Transactional - public void moveNetworkModifications(@NonNull UUID studyUuid, UUID targetNodeUuid, @NonNull UUID originNodeUuid, List modificationUuidList, UUID beforeUuid, boolean isTargetInDifferentNodeTree, String userId) { + public void moveNetworkModifications( + @NonNull UUID studyUuid, + UUID targetNodeUuid, + @NonNull UUID originNodeUuid, + List modificationUuidList, + UUID beforeUuid, + boolean isTargetInDifferentNodeTree, + String userId) { boolean isTargetDifferentNode = !targetNodeUuid.equals(originNodeUuid); List childrenUuids = networkModificationTreeService.getChildrenUuids(targetNodeUuid); @@ -2367,8 +2374,7 @@ public void moveNetworkModifications(@NonNull UUID studyUuid, UUID targetNodeUui .map(rootNetworkEntity -> rootNetworkNodeInfoService.getNetworkModificationApplicationContext(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) .toList(); - List modificationsToCopyInfos = modificationUuidList.stream().map(modifUuid -> ModificationsToCopyInfos.builder().uuid(modifUuid).build()).toList(); - NetworkModificationsResult networkModificationsResult = networkModificationService.moveModifications(originGroupUuid, targetGroupUuid, beforeUuid, Pair.of(modificationsToCopyInfos, modificationApplicationContexts), isTargetInDifferentNodeTree); + NetworkModificationsResult networkModificationsResult = networkModificationService.moveModifications(originGroupUuid, targetGroupUuid, beforeUuid, Pair.of(modificationUuidList, modificationApplicationContexts), isTargetInDifferentNodeTree); rootNetworkNodeInfoService.moveModificationsToExclude(originNodeUuid, targetNodeUuid, networkModificationsResult.modificationUuids()); // Target node @@ -2397,14 +2403,12 @@ private void emitNetworkModificationImpactsForAllRootNetworks(List modifications, - String userId, - StudyConstants.ModificationsActionType action) { + List modificationsUuids, + String userId) { List childrenUuids = networkModificationTreeService.getChildrenUuids(targetNodeUuid); notificationService.emitStartModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids, NotificationService.MODIFICATIONS_UPDATING_IN_PROGRESS); try { @@ -2417,21 +2421,52 @@ public void duplicateOrInsertNetworkModifications( .map(rootNetworkEntity -> rootNetworkNodeInfoService.getNetworkModificationApplicationContext(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) .toList(); - NetworkModificationsResult networkModificationResults = networkModificationService.duplicateOrInsertModifications(groupUuid, action, Pair.of(modifications, modificationApplicationContexts)); + NetworkModificationsResult networkModificationResults = networkModificationService.duplicateModifications(groupUuid, Pair.of(modificationsUuids, modificationApplicationContexts)); - copyModificationsToExclude(originNodeUuid, targetNodeUuid, modifications, networkModificationResults); + copyModificationsToExclude(originNodeUuid, targetNodeUuid, modificationsUuids, networkModificationResults); - if (networkModificationResults != null) { - int index = 0; - // for each NetworkModificationResult, send an impact notification - studyRootNetworkEntities are ordered in the same way as networkModificationResults - for (Optional modificationResultOpt : networkModificationResults.modificationResults()) { - if (modificationResultOpt.isPresent() && studyRootNetworkEntities.get(index) != null) { - emitNetworkModificationImpacts(targetStudyUuid, targetNodeUuid, studyRootNetworkEntities.get(index).getId(), modificationResultOpt.get()); - } - index++; + sendImpactNotifications(targetStudyUuid, targetNodeUuid, networkModificationResults, studyRootNetworkEntities); + } finally { + notificationService.emitEndModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids); + } + notificationService.emitElementUpdated(targetStudyUuid, userId); + } + + private void sendImpactNotifications(UUID targetStudyUuid, UUID targetNodeUuid, NetworkModificationsResult networkModificationResults, List studyRootNetworkEntities) { + if (networkModificationResults != null) { + int index = 0; + // for each NetworkModificationResult, send an impact notification - studyRootNetworkEntities are ordered in the same way as networkModificationResults + for (Optional modificationResultOpt : networkModificationResults.modificationResults()) { + if (modificationResultOpt.isPresent() && studyRootNetworkEntities.get(index) != null) { + emitNetworkModificationImpacts(targetStudyUuid, targetNodeUuid, studyRootNetworkEntities.get(index).getId(), modificationResultOpt.get()); } + index++; } + } + } + + @Transactional + public void insertCompositeNetworkModifications( + UUID targetStudyUuid, + UUID targetNodeUuid, + List> modifications, + String userId, + StudyConstants.CompositeModificationsActionType action) { + List childrenUuids = networkModificationTreeService.getChildrenUuids(targetNodeUuid); + notificationService.emitStartModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids, NotificationService.MODIFICATIONS_UPDATING_IN_PROGRESS); + try { + checkStudyContainsNode(targetStudyUuid, targetNodeUuid); + + List studyRootNetworkEntities = getStudyRootNetworks(targetStudyUuid); + UUID groupUuid = networkModificationTreeService.getModificationGroupUuid(targetNodeUuid); + + List modificationApplicationContexts = studyRootNetworkEntities.stream() + .map(rootNetworkEntity -> rootNetworkNodeInfoService.getNetworkModificationApplicationContext(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) + .toList(); + + NetworkModificationsResult networkModificationResults = networkModificationService.insertCompositeModifications(groupUuid, action, Pair.of(modifications, modificationApplicationContexts)); + sendImpactNotifications(targetStudyUuid, targetNodeUuid, networkModificationResults, studyRootNetworkEntities); } finally { notificationService.emitEndModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids); } @@ -2440,10 +2475,11 @@ public void duplicateOrInsertNetworkModifications( private void copyModificationsToExclude(UUID originNodeUuid, UUID targetNodeUuid, - List modifications, NetworkModificationsResult networkModificationResults) { + List modificationsUuids, + NetworkModificationsResult networkModificationResults) { Map mappingModificationsUuids = new HashMap<>(); - for (int i = 0; i < modifications.size(); i++) { - mappingModificationsUuids.put(modifications.get(i).getUuid(), networkModificationResults.modificationUuids().get(i)); + for (int i = 0; i < modificationsUuids.size(); i++) { + mappingModificationsUuids.put(modificationsUuids.get(i), networkModificationResults.modificationUuids().get(i)); } rootNetworkNodeInfoService.copyModificationsToExcludeFromTags(originNodeUuid, targetNodeUuid, mappingModificationsUuids); diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java index 35fb86588..37e5e689b 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java @@ -48,10 +48,7 @@ import org.gridsuite.study.server.utils.SendInput; import org.gridsuite.study.server.utils.TestUtils; import org.gridsuite.study.server.utils.elasticsearch.DisableElasticsearch; -import org.gridsuite.study.server.utils.wiremock.ComputationServerStubs; -import org.gridsuite.study.server.utils.wiremock.ReportServerStubs; -import org.gridsuite.study.server.utils.wiremock.WireMockStubs; -import org.gridsuite.study.server.utils.wiremock.WireMockUtils; +import org.gridsuite.study.server.utils.wiremock.*; import org.json.JSONObject; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -2011,26 +2008,24 @@ void testReorderModification() throws Exception { UUID.randomUUID(), VARIANT_ID, "node", userId); UUID modificationNodeUuid = modificationNode.getId(); - UUID modification1Uuid = UUID.randomUUID(); - UUID modification2Uuid = UUID.randomUUID(); - ModificationsToCopyInfos modification1 = ModificationsToCopyInfos.builder().uuid(modification1Uuid).build(); - + UUID modification1 = UUID.randomUUID(); + UUID modification2 = UUID.randomUUID(); UUID groupStubId = wireMockServer.stubFor(WireMock.any(WireMock.urlPathMatching("/v1/groups/.*")) .withQueryParam("action", WireMock.equalTo("MOVE")) .willReturn(WireMock.ok() - .withBody(mapper.writeValueAsString(new NetworkModificationsResult(Arrays.asList(modification1Uuid, modification2Uuid), List.of(Optional.empty())))) + .withBody(mapper.writeValueAsString(new NetworkModificationsResult(Arrays.asList(modification1, modification2), List.of(Optional.empty())))) .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId(); // switch the 2 modifications order (modification1 is set at the end, after modification2) mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modification/{modificationID}", - studyNameUserIdUuid, modificationNodeUuid, modification1Uuid).header(USER_ID_HEADER, "userId")) + studyNameUserIdUuid, modificationNodeUuid, modification1).header(USER_ID_HEADER, "userId")) .andExpect(status().isOk()); checkUpdateStatusMessagesReceived(studyNameUserIdUuid, modificationNodeUuid, output); checkEquipmentUpdatingMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); - Pair, List> expectedBody = Pair.of(Collections.singletonList(modification1), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNodeUuid, NETWORK_UUID))); + Pair, List> expectedBody = Pair.of(Collections.singletonList(modification1), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNodeUuid, NETWORK_UUID))); String expectedBodyStr = mapper.writeValueAsString(expectedBody); String url = "/v1/groups/" + modificationNode.getModificationGroupUuid(); WireMockUtils.verifyPutRequest(wireMockServer, groupStubId, url, true, Map.of( @@ -2041,7 +2036,7 @@ void testReorderModification() throws Exception { // switch back the 2 modifications order (modification1 is set before modification2) mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modification/{modificationID}?beforeUuid={modificationID2}", - studyNameUserIdUuid, modificationNodeUuid, modification1Uuid, modification2Uuid).header(USER_ID_HEADER, "userId")) + studyNameUserIdUuid, modificationNodeUuid, modification1, modification2).header(USER_ID_HEADER, "userId")) .andExpect(status().isOk()); checkUpdateStatusMessagesReceived(studyNameUserIdUuid, modificationNodeUuid, output); checkEquipmentUpdatingMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); @@ -2052,7 +2047,7 @@ void testReorderModification() throws Exception { "action", WireMock.equalTo("MOVE"), "originGroupUuid", WireMock.equalTo(modificationNode.getModificationGroupUuid().toString()), "build", WireMock.equalTo("false"), - "before", WireMock.equalTo(modification2Uuid.toString())), + "before", WireMock.equalTo(modification2.toString())), expectedBodyStr); } @@ -2080,6 +2075,56 @@ void testReorderModificationErrorCase() throws Exception { .andExpect(status().isNotFound()); } + @Test + void testInsertComposite() throws Exception { + String userId = "userId"; + StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); + UUID studyUuid = studyEntity.getId(); + UUID firstRootNetworkUuid = studyTestUtils.getOneRootNetworkUuid(studyUuid); + UUID rootNodeUuid = getRootNode(studyUuid).getId(); + NetworkModificationNode node1 = createNetworkModificationNode(studyUuid, rootNodeUuid, + UUID.randomUUID(), VARIANT_ID, "New node 1", "userId"); + UUID nodeUuid1 = node1.getId(); + Pair modification1 = Pair.of(UUID.randomUUID(), "composite 1"); + Pair modification2 = Pair.of(UUID.randomUUID(), "composite 2"); + String compositesData = mapper.writeValueAsString( + Arrays.asList( + modification1, + modification2 + ) + ); + + wireMockServer.stubFor(WireMock.any(WireMock.urlPathMatching("/v1/network-composite-modifications/groups/.*")) + .withQueryParam("action", WireMock.equalTo("INSERT")) + .willReturn(WireMock.ok() + .withBody(mapper.writeValueAsString(new NetworkModificationsResult(List.of(UUID.randomUUID(), UUID.randomUUID()), List.of(Optional.empty())))) + .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId(); + + // insert 2 composite modifications in node1 + mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}/composite-modifications?action=INSERT", + studyUuid, nodeUuid1) + .contentType(MediaType.APPLICATION_JSON) + .content(compositesData) + .header(USER_ID_HEADER, "userId")) + .andExpect(status().isOk()); + checkUpdateStatusMessagesReceived(studyUuid, nodeUuid1, output); + checkEquipmentUpdatingMessagesReceived(studyUuid, nodeUuid1); + checkEquipmentUpdatingFinishedMessagesReceived(studyUuid, nodeUuid1); + checkElementUpdatedMessageSent(studyUuid, userId); + + Pair>, List> modificationBody = + Pair.of( + List.of(modification1, modification2), + List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, node1.getId(), NETWORK_UUID) + ) + ); + String expectedBody = mapper.writeValueAsString(modificationBody); + String url = "/v1/network-composite-modifications/groups/" + node1.getModificationGroupUuid(); + WireMockUtilsCriteria.verifyPutRequest(wireMockServer, url, false, Map.of( + "action", WireMock.equalTo("INSERT")), + expectedBody); + } + @Test void testDuplicateModification() throws Exception { String userId = "userId"; @@ -2090,8 +2135,8 @@ void testDuplicateModification() throws Exception { NetworkModificationNode node1 = createNetworkModificationNode(studyUuid, rootNodeUuid, UUID.randomUUID(), VARIANT_ID, "New node 1", "userId"); UUID nodeUuid1 = node1.getId(); - ModificationsToCopyInfos modification1 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); - ModificationsToCopyInfos modification2 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); + UUID modification1 = UUID.randomUUID(); + UUID modification2 = UUID.randomUUID(); String modificationUuidListBody = mapper.writeValueAsString(Arrays.asList(modification1, modification2)); UUID groupStubId = wireMockServer.stubFor(WireMock.any(WireMock.urlPathMatching("/v1/groups/.*")) @@ -2112,7 +2157,7 @@ void testDuplicateModification() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyUuid, nodeUuid1); checkElementUpdatedMessageSent(studyUuid, userId); - Pair, List> modificationBody = Pair.of(List.of(modification1, modification2), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, node1.getId(), NETWORK_UUID))); + Pair, List> modificationBody = Pair.of(List.of(modification1, modification2), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, node1.getId(), NETWORK_UUID))); String expectedBody = mapper.writeValueAsString(modificationBody); String url = "/v1/groups/" + node1.getModificationGroupUuid(); WireMockUtils.verifyPutRequest(wireMockServer, groupStubId, url, true, Map.of( @@ -2171,7 +2216,7 @@ void testDuplicateModificationBetweenStudies() throws Exception { .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId(); // Duplicate modification from node2 (study2) to node1 (study1) - List modifications = List.of(ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build()); + List modifications = List.of(UUID.randomUUID()); String modificationUuidListBody = mapper.writeValueAsString(modifications); mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}?originStudyUuid={originStudyUuid}&originNodeUuid={originNodeUuid}&action=COPY", studyEntity1.getId(), node1.getId(), studyEntity2.getId(), node2.getId()) @@ -2184,7 +2229,7 @@ void testDuplicateModificationBetweenStudies() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyEntity1.getId(), node1.getId()); checkElementUpdatedMessageSent(studyEntity1.getId(), userId); - Pair, List> modificationBody = Pair.of(modifications, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(studyTestUtils.getOneRootNetworkUuid(studyEntity1.getId()), node1.getId(), NETWORK_UUID))); + Pair, List> modificationBody = Pair.of(modifications, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(studyTestUtils.getOneRootNetworkUuid(studyEntity1.getId()), node1.getId(), NETWORK_UUID))); String expectedBody = mapper.writeValueAsString(modificationBody); String url = "/v1/groups/" + node1.getModificationGroupUuid(); WireMockUtils.verifyPutRequest(wireMockServer, groupStubId, url, true, Map.of( @@ -2208,8 +2253,8 @@ void testDuplicateModificationErrorCase() throws Exception { UUID studyUuid = studyEntity.getId(); UUID rootNodeUuid = getRootNode(studyUuid).getId(); createNetworkModificationNode(studyUuid, rootNodeUuid, UUID.randomUUID(), VARIANT_ID, "New node 1", "userId"); - ModificationsToCopyInfos modification1 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); - ModificationsToCopyInfos modification2 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); + UUID modification1 = UUID.randomUUID(); + UUID modification2 = UUID.randomUUID(); String modificationUuidListBody = mapper.writeValueAsString(Arrays.asList(modification1, modification2)); // Random/bad studyId error case @@ -2243,31 +2288,28 @@ void testCutAndPasteModification() throws Exception { NetworkModificationNode node2 = createNetworkModificationNode(studyUuid, rootNodeUuid, UUID.randomUUID(), VARIANT_ID, "New node 2", userId); UUID nodeUuid2 = node2.getId(); - UUID modification1Uuid = UUID.randomUUID(); - UUID modification2Uuid = UUID.randomUUID(); - ModificationsToCopyInfos modification1 = ModificationsToCopyInfos.builder().uuid(modification1Uuid).build(); - ModificationsToCopyInfos modification2 = ModificationsToCopyInfos.builder().uuid(modification2Uuid).build(); - String modificationsToCopyInfos = mapper.writeValueAsString(Arrays.asList(modification1, modification2)); + UUID modification1 = UUID.randomUUID(); + UUID modification2 = UUID.randomUUID(); + String modificationUuidListBody = mapper.writeValueAsString(Arrays.asList(modification1, modification2)); UUID groupStubId = wireMockServer.stubFor(WireMock.any(WireMock.urlPathMatching("/v1/groups/.*")) .withQueryParam("action", WireMock.equalTo("MOVE")) .willReturn(WireMock.ok() - .withBody(mapper.writeValueAsString(new NetworkModificationsResult(Arrays.asList(modification1Uuid, modification2Uuid), List.of(Optional.empty())))) + .withBody(mapper.writeValueAsString(new NetworkModificationsResult(Arrays.asList(modification1, modification2), List.of(Optional.empty())))) .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId(); // move 2 modifications within node 1 mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}?originStudyUuid={originStudyUuid}&originNodeUuid={originNodeUuid}&action=MOVE", studyUuid, nodeUuid1, studyUuid, nodeUuid1) .contentType(MediaType.APPLICATION_JSON) - .content(modificationsToCopyInfos) + .content(modificationUuidListBody) .header(USER_ID_HEADER, "userId")) .andExpect(status().isOk()); checkUpdateStatusMessagesReceived(studyUuid, nodeUuid1, output); checkEquipmentUpdatingMessagesReceived(studyUuid, nodeUuid1); checkEquipmentUpdatingFinishedMessagesReceived(studyUuid, nodeUuid1); - Pair, List> expectedBody = Pair.of(List.of(modification1, modification2), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, node1.getId(), NETWORK_UUID))); - + Pair, List> expectedBody = Pair.of(List.of(modification1, modification2), List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, node1.getId(), NETWORK_UUID))); String expectedBodyStr = mapper.writeValueAsString(expectedBody); String url = "/v1/groups/" + node1.getModificationGroupUuid(); WireMockUtils.verifyPutRequest(wireMockServer, groupStubId, url, true, Map.of( @@ -2280,7 +2322,7 @@ void testCutAndPasteModification() throws Exception { mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}?originStudyUuid={originStudyUuid}&originNodeUuid={originNodeUuid}&action=MOVE", studyUuid, nodeUuid2, studyUuid, nodeUuid1) .contentType(MediaType.APPLICATION_JSON) - .content(modificationsToCopyInfos) + .content(modificationUuidListBody) .header(USER_ID_HEADER, "userId")) .andExpect(status().isOk()); checkUpdateStatusMessagesReceived(studyUuid, nodeUuid1, output); @@ -2305,7 +2347,7 @@ void testCutAndPasteModification() throws Exception { mockMvc.perform(put("/v1/studies/{studyUuid}/nodes/{nodeUuid}?action=MOVE", studyUuid, nodeUuid1) .contentType(MediaType.APPLICATION_JSON) - .content(modificationsToCopyInfos) + .content(modificationUuidListBody) .header(USER_ID_HEADER, "userId")) .andExpect(status().isBadRequest()); } @@ -2318,8 +2360,8 @@ void testCutAndPasteModificationErrorCase() throws Exception { UUID rootNodeUuid = getRootNode(studyUuid).getId(); createNetworkModificationNode(studyUuid, rootNodeUuid, UUID.randomUUID(), VARIANT_ID, "New node 1", userId); createNetworkModificationNode(studyUuid, rootNodeUuid, UUID.randomUUID(), VARIANT_ID, "New node 2", userId); - ModificationsToCopyInfos modification1 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); - ModificationsToCopyInfos modification2 = ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build(); + UUID modification1 = UUID.randomUUID(); + UUID modification2 = UUID.randomUUID(); String modificationUuidListBody = mapper.writeValueAsString(Arrays.asList(modification1, modification2)); // Random/bad studyId error case diff --git a/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java b/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java index 12d0e062b..7b47cf868 100644 --- a/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java +++ b/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Sets; import org.gridsuite.study.server.ContextConfigurationWithTestChannel; -import org.gridsuite.study.server.StudyConstants; import org.gridsuite.study.server.error.StudyException; import org.gridsuite.study.server.dto.*; import org.gridsuite.study.server.dto.modification.NetworkModificationResult; @@ -519,29 +518,24 @@ void testDuplicateModificationBetweenStudiesWithCommonRootNetworkTag() { ); // -------- MOCK DUPLICATION RESULT -------- - List modifications = List.of( - ModificationsToCopyInfos.builder().uuid(MODIFICATION_TO_EXCLUDE_1).build(), - ModificationsToCopyInfos.builder().uuid(MODIFICATION_TO_EXCLUDE_2).build() - ); + List modifications = List.of(MODIFICATION_TO_EXCLUDE_1, MODIFICATION_TO_EXCLUDE_2); Mockito.doReturn( new NetworkModificationsResult( modifications.stream() - .map(m -> ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP.get(m.getUuid())) + .map(ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP::get) .toList(), List.of() ) ).when(networkModificationService) - .duplicateOrInsertModifications(any(), any(), any()); + .duplicateModifications(any(), any()); // -------- EXECUTE -------- - studyService.duplicateOrInsertNetworkModifications( + studyService.duplicateNetworkModifications( study2.getId(), node2.getId(), - study1.getId(), node1.getId(), modifications, - USER_ID, - StudyConstants.ModificationsActionType.COPY + USER_ID ); // -------- ASSERT COMMON ROOT NETWORK -------- UUID commonRn2 = rnStudy2.stream() @@ -556,7 +550,6 @@ void testDuplicateModificationBetweenStudiesWithCommonRootNetworkTag() { ).orElseThrow(); Set duplicatedUuids = modifications.stream() - .map(ModificationsToCopyInfos::getUuid) .map(ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP::get) .collect(Collectors.toSet()); @@ -606,12 +599,10 @@ void testDuplicateModificationWithModificationsToExclude() { rootNetworkNodeInfoRepository.save(rootNetworkNodeInfoEntity2); // mock duplicateModificationsGroup to return a mapping between origin modification uuid and their duplicate uuid - List modificationsToDuplicate = List.of( - ModificationsToCopyInfos.builder().uuid(MODIFICATION_NEVER_EXCLUDED).build(), - ModificationsToCopyInfos.builder().uuid(MODIFICATION_TO_EXCLUDE_1).build(), - ModificationsToCopyInfos.builder().uuid(MODIFICATION_TO_EXCLUDE_2).build() - ); - Mockito.doReturn(new NetworkModificationsResult(modificationsToDuplicate.stream().map(ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP::get).toList(), List.of())).when(networkModificationService).duplicateOrInsertModifications(any(), any(), any()); + List modificationsToDuplicate = List.of(MODIFICATION_NEVER_EXCLUDED, MODIFICATION_TO_EXCLUDE_1, MODIFICATION_TO_EXCLUDE_2); + Mockito.doReturn( + new NetworkModificationsResult(modificationsToDuplicate.stream().map(ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP::get).toList(), List.of()) + ).when(networkModificationService).duplicateModifications(any(), any()); // duplicate (excluded) modification uuids for RH1 Set modificationUuidsToDuplicate1 = Sets.intersection(MODIFICATIONS_TO_EXCLUDE_RN_1, new HashSet<>(modificationsToDuplicate)); @@ -624,14 +615,14 @@ void testDuplicateModificationWithModificationsToExclude() { .map(ORIGIN_TO_DUPLICATE_MODIFICATION_UUID_MAP::get).collect(Collectors.toSet()); // test duplication on same node : node1 - studyService.duplicateOrInsertNetworkModifications(studyEntity.getId(), firstNode.getId(), studyEntity.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); + studyService.duplicateNetworkModifications(studyEntity.getId(), firstNode.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID); RootNetworkNodeInfoEntity upToDateRootNetworkNodeInfoEntity1 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(firstNode.getId(), rootNetworkBasicInfos.get(0).rootNetworkUuid()).orElseThrow(() -> new StudyException(NOT_FOUND, "Root network not found")); RootNetworkNodeInfoEntity upToDateRootNetworkNodeInfoEntity2 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(firstNode.getId(), rootNetworkBasicInfos.get(1).rootNetworkUuid()).orElseThrow(() -> new StudyException(NOT_FOUND, "Root network not found")); assertEquals(Sets.union(expectedExcludedModification1, MODIFICATIONS_TO_EXCLUDE_RN_1), upToDateRootNetworkNodeInfoEntity1.getModificationsUuidsToExclude()); assertEquals(Sets.union(expectedExcludedModification2, MODIFICATIONS_TO_EXCLUDE_RN_2), upToDateRootNetworkNodeInfoEntity2.getModificationsUuidsToExclude()); // test duplication on different nodes : node1 -> node2 - studyService.duplicateOrInsertNetworkModifications(studyEntity.getId(), secondNode.getId(), studyEntity.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); + studyService.duplicateNetworkModifications(studyEntity.getId(), secondNode.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID); upToDateRootNetworkNodeInfoEntity1 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(secondNode.getId(), rootNetworkBasicInfos.get(0).rootNetworkUuid()).orElseThrow(() -> new StudyException(NOT_FOUND, "Root network not found")); upToDateRootNetworkNodeInfoEntity2 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(secondNode.getId(), rootNetworkBasicInfos.get(1).rootNetworkUuid()).orElseThrow(() -> new StudyException(NOT_FOUND, "Root network not found")); assertEquals(expectedExcludedModification1, upToDateRootNetworkNodeInfoEntity1.getModificationsUuidsToExclude()); diff --git a/src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java b/src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java index 624d14278..b275e1e6f 100644 --- a/src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java +++ b/src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerRebuildNodeTest.java @@ -6,7 +6,6 @@ */ package org.gridsuite.study.server.studycontroller; -import org.gridsuite.study.server.dto.ModificationsToCopyInfos; import org.gridsuite.study.server.service.RebuildNodeService; import org.gridsuite.study.server.StudyConstants; import org.gridsuite.study.server.controller.StudyController; @@ -84,11 +83,10 @@ void testMoveNetworkModification() { @Test void testMoveNetworkModifications() { - List modifications = List.of(ModificationsToCopyInfos.builder().uuid(UUID.randomUUID()).build()); + List modificationUuids = List.of(UUID.randomUUID()); UUID originNodeUuid = UUID.randomUUID(); - studyController.moveOrCopyModifications(studyUuid, nodeUuid, StudyConstants.ModificationsActionType.MOVE, studyUuid, originNodeUuid, modifications, userId); + studyController.moveOrCopyModifications(studyUuid, nodeUuid, StudyConstants.ModificationsActionType.MOVE, studyUuid, originNodeUuid, modificationUuids, userId); - List modificationUuids = modifications.stream().map(ModificationsToCopyInfos::getUuid).toList(); verify(rebuildNodeService, times(1)).moveNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationUuids, userId); verify(studyService, times(1)).buildNode(eq(studyUuid), eq(nodeUuid), any(), eq(userId)); }