diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java index d23ce8cff..47074e4e5 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationController.java @@ -17,6 +17,7 @@ import org.gridsuite.modification.server.dto.catalog.LineTypeInfos; import org.gridsuite.modification.server.service.LineTypesCatalogService; import org.gridsuite.modification.server.service.NetworkModificationService; +import org.springframework.data.util.Pair; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -71,13 +72,42 @@ public ResponseEntity getNetworkModificationsCount(@Parameter(descripti @PostMapping(value = "/groups") @Operation(summary = "Create a modification group based on another group") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The group and its modifications have been duplicated")}) - public ResponseEntity createModificationGroup(@RequestParam("groupUuid") UUID groupUuid, - @RequestParam("duplicateFrom") UUID sourceGroupUuid) { - networkModificationService.createModificationGroup(sourceGroupUuid, groupUuid); + public ResponseEntity duplicateGroup(@RequestParam("groupUuid") UUID groupUuid, + @RequestParam("duplicateFrom") UUID sourceGroupUuid) { + networkModificationService.duplicateGroup(sourceGroupUuid, groupUuid); return ResponseEntity.ok().build(); } - @PutMapping(value = "/groups/{groupUuid}", produces = MediaType.APPLICATION_JSON_VALUE) + @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") + @ApiResponse(responseCode = "200", description = "The modification list of the group has been updated.") + public ResponseEntity>> 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 = "destination node can be built (default is true)") @RequestParam(value = "build", required = false, defaultValue = "true") Boolean build, + @RequestBody Pair, List> modificationContextInfos) { + return switch (action) { + case COPY -> + ResponseEntity.ok().body(networkModificationService.duplicateModifications(targetGroupUuid, originGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond())); + case INSERT -> + ResponseEntity.ok().body(networkModificationService.insertCompositeModifications(targetGroupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond())); + case MOVE -> { + UUID sourceGroupUuid = originGroupUuid == null ? targetGroupUuid : originGroupUuid; + boolean canBuildNode = build; + if (sourceGroupUuid.equals(targetGroupUuid)) { + canBuildNode = false; + } + yield ResponseEntity.ok().body(networkModificationService.moveModifications(targetGroupUuid, sourceGroupUuid, beforeModificationUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond(), canBuildNode)); + } + }; + } + + /** + * TODO : Remove this endpoint after the final integration of root networks (used only for move and tests) + * Need to use the new endpoint with modificationContextInfos DTO (see above) + */ + @PutMapping(value = "/groups/{groupUuid}", params = {"networkUuid", "reportUuid", "reporterId"}, 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") @ApiResponse(responseCode = "200", description = "The modification list of the group has been updated.") public ResponseEntity> handleNetworkModifications(@Parameter(description = "updated group UUID, where modifications are pasted") @PathVariable("groupUuid") UUID targetGroupUuid, @@ -123,18 +153,34 @@ public ResponseEntity> getModificationGroups() { return ResponseEntity.ok().body(networkModificationService.getModificationGroups()); } + @PostMapping(value = "/network-modifications", params = "groupUuid", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Create a network modification") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "The network modification was created"), + @ApiResponse(responseCode = "404", description = "The network or equipment was not found")}) + public ResponseEntity>> createNetworkModification( + @Parameter(description = "Group UUID") @RequestParam(name = "groupUuid") UUID groupUuid, + @RequestBody Pair> modificationContextInfos) { + modificationContextInfos.getFirst().check(); + return ResponseEntity.ok().body(networkModificationService.createNetworkModification(groupUuid, modificationContextInfos.getFirst(), modificationContextInfos.getSecond())); + } + + /** + * TODO : Remove this endpoint after the final integration of root networks (all tests need to migrate before) + * Need to use tne new endpoint with modificationContextInfos DTO (see above) + */ @PostMapping(value = "/network-modifications", params = {"networkUuid", "reportUuid", "reporterId"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Create a network modification") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "The network modification was created"), @ApiResponse(responseCode = "404", description = "The network or equipment was not found")}) public ResponseEntity> createNetworkModification( - @Parameter(description = "Network UUID") @RequestParam("networkUuid") UUID networkUuid, - @Parameter(description = "Variant ID") @RequestParam(name = "variantId", required = false) String variantId, - @Parameter(description = "Group UUID") @RequestParam(name = "groupUuid", required = false) UUID groupUuid, - @Parameter(description = "Report UUID") @RequestParam("reportUuid") UUID reportUuid, - @Parameter(description = "Reporter ID") @RequestParam("reporterId") String reporterId, - @RequestBody ModificationInfos modificationInfos) { + @Parameter(description = "Network UUID") @RequestParam("networkUuid") UUID networkUuid, + @Parameter(description = "Variant ID") @RequestParam(name = "variantId", required = false) String variantId, + @Parameter(description = "Group UUID") @RequestParam(name = "groupUuid", required = false) UUID groupUuid, + @Parameter(description = "Report UUID") @RequestParam("reportUuid") UUID reportUuid, + @Parameter(description = "Reporter ID") @RequestParam("reporterId") String reporterId, + @RequestBody ModificationInfos modificationInfos) { modificationInfos.check(); return ResponseEntity.ok().body(networkModificationService.createNetworkModification(networkUuid, variantId, groupUuid, new ReportInfos(reportUuid, UUID.fromString(reporterId)), modificationInfos)); } @@ -208,13 +254,6 @@ public ResponseEntity deleteLineTypesCatalog() { return ResponseEntity.ok().build(); } - @PostMapping(value = "/groups/modification", consumes = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Create a group containing a modification") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The group with the modification has been created")}) - public ResponseEntity createModificationInGroup(@RequestBody ModificationInfos modificationsInfos) { - return ResponseEntity.ok().body(networkModificationService.createModificationInGroup(modificationsInfos)); - } - @PostMapping(value = "/network-composite-modifications", consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Create a network composite modification") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The composite modification has been created")}) @@ -267,18 +306,6 @@ public ResponseEntity updateNetworkModificationsActivationStatus( return ResponseEntity.ok().build(); } - @PutMapping(value = "/groups/{groupUuid}/duplications", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Duplicate all modifications in a group and append them at the end of another modifications group") - @ApiResponse(responseCode = "200", description = "The modifications have been duplicated") - public ResponseEntity> duplicateModificationsInGroup(@Parameter(description = "updated group UUID, where modifications are pasted") @PathVariable("groupUuid") UUID targetGroupUuid, - @Parameter(description = "the network uuid", required = true) @RequestParam(value = "networkUuid") UUID networkUuid, - @Parameter(description = "the report uuid", required = true) @RequestParam(value = "reportUuid") UUID reportUuid, - @Parameter(description = "the reporter id", required = true) @RequestParam(value = "reporterId") UUID reporterId, - @Parameter(description = "the variant id", required = true) @RequestParam(value = "variantId") String variantId, - @Parameter(description = "origin group UUID, from where modifications are copied") @RequestParam(value = "duplicateFrom") UUID originGroupUuid) { - return ResponseEntity.ok().body(networkModificationService.duplicateModificationsInGroup(targetGroupUuid, networkUuid, variantId, new ReportInfos(reportUuid, reporterId), originGroupUuid)); - } - @DeleteMapping(value = "/groups/{groupUuid}/stashed-modifications") @Operation(summary = "Delete the stashed modifications in a group") @ApiResponse(responseCode = "200", description = "Stashed modifications in the group deleted") diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationServerException.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationServerException.java new file mode 100644 index 000000000..2540fc653 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationServerException.java @@ -0,0 +1,38 @@ +/* + Copyright (c) 2025, 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.modification.server; + +import com.powsybl.commons.PowsyblException; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import java.util.Objects; + +/** + * @author Slimane Amar + */ +public class NetworkModificationServerException extends PowsyblException { + public enum Type { + DUPLICATION_ARGUMENT_INVALID(HttpStatus.BAD_REQUEST, "Invalid argument for duplication"); + + public final HttpStatus status; + private final String message; + + Type(HttpStatus status, String message) { + this.status = status; + this.message = message; + } + } + + @Getter + private final Type type; + + public NetworkModificationServerException(Type type) { + super(Objects.requireNonNull(type.name()) + ((type.message == null) ? "" : " : " + type.message)); + this.type = type; + } +} diff --git a/src/main/java/org/gridsuite/modification/server/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/modification/server/RestResponseEntityExceptionHandler.java index 174aa4ed8..d4b87abf9 100644 --- a/src/main/java/org/gridsuite/modification/server/RestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/modification/server/RestResponseEntityExceptionHandler.java @@ -9,6 +9,7 @@ import org.gridsuite.modification.NetworkModificationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -20,14 +21,24 @@ public class RestResponseEntityExceptionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RestResponseEntityExceptionHandler.class); + private static final String HANDLER_MESSAGE = "Caught in handler"; @ExceptionHandler(NetworkModificationException.class) - protected ResponseEntity handleNetworkModificationException(NetworkModificationException exception) { + protected ResponseEntity handleException(NetworkModificationException exception) { + return handleException(exception.getType().status, exception); + } + + @ExceptionHandler(NetworkModificationServerException.class) + protected ResponseEntity handleException(NetworkModificationServerException exception) { + return handleException(exception.getType().status, exception); + } + + private ResponseEntity handleException(HttpStatus status, Exception exception) { if (LOGGER.isErrorEnabled()) { - LOGGER.error(exception.getMessage()); + LOGGER.error(HANDLER_MESSAGE, exception); } return ResponseEntity - .status(exception.getType().status) - .body(exception.getMessage()); + .status(status) + .body(exception.getMessage()); } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/ModificationApplicationContext.java b/src/main/java/org/gridsuite/modification/server/dto/ModificationApplicationContext.java new file mode 100644 index 000000000..a67c4cfa0 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/ModificationApplicationContext.java @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2024, 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.modification.server.dto; + +import java.util.UUID; + +public record ModificationApplicationContext(UUID networkUuid, String variantId, UUID reportUuid, UUID reporterId) { } 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 8263652d9..b3c920b61 100644 --- a/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java +++ b/src/main/java/org/gridsuite/modification/server/repositories/NetworkModificationRepository.java @@ -62,16 +62,16 @@ public void deleteAll() { // This method should be package-private and not used as API of the service as it uses ModificationEntity and // we want to encapsulate the use of Entity related objects to this service. // Nevertheless We have to keep it public for transactional annotation. - public void saveModifications(UUID groupUuid, List modifications) { - saveModificationsNonTransactional(groupUuid, modifications); + public List saveModifications(UUID groupUuid, List modifications) { + return saveModificationsNonTransactional(groupUuid, modifications); } @Transactional // To have all create in the same transaction (atomic) // TODO Remove transaction when errors will no longer be sent to the front - public void saveModificationInfos(UUID groupUuid, List modifications) { + public List saveModificationInfos(UUID groupUuid, List modifications) { List entities = modifications.stream().map(ModificationEntity::fromDTO).toList(); - saveModificationsNonTransactional(groupUuid, entities); + return saveModificationsNonTransactional(groupUuid, entities); } public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { @@ -85,7 +85,7 @@ public UUID createNetworkCompositeModification(@NonNull List modificationU return modificationRepository.save(compositeEntity).getId(); } - private void saveModificationsNonTransactional(UUID groupUuid, List modifications) { + private List saveModificationsNonTransactional(UUID groupUuid, List modifications) { int order = modificationRepository.countByGroupIdAndStashed(groupUuid, false); var modificationGroupEntity = this.modificationGroupRepository .findById(groupUuid) @@ -95,7 +95,7 @@ private void saveModificationsNonTransactional(UUID groupUuid, List @@ -146,6 +148,16 @@ public void restoreNetworkModifications(UUID groupUuid, @NonNull List modi // No transactional because we need to save modification in DB also in case of error // Transaction made in 'saveModifications' method // TODO Add transaction when errors will no longer be sent to the front + public List> createNetworkModification(@NonNull UUID groupUuid, @NonNull ModificationInfos modificationInfo, @NonNull List applicationContexts) { + networkModificationRepository.saveModificationInfos(groupUuid, List.of(modificationInfo)); + + return applyModifications(List.of(modificationInfo), applicationContexts); + } + + /** + * TODO : Remove this method after the final integration of root networks + * Need to use tne new method with ModificationApplicationContext DTO (see above) + */ public Optional createNetworkModification(@NonNull UUID networkUuid, String variantId, @NonNull UUID groupUuid, @NonNull ReportInfos reportInfos, @NonNull ModificationInfos modificationInfos) { @@ -158,6 +170,18 @@ public Optional createNetworkModification(@NonNull UU Optional.empty(); } + /** + * Apply modifications on several networks + */ + private List> applyModifications(List modifications, List applicationContexts) { + return applicationContexts.stream().map(modificationApplicationContext -> + applyModifications(modificationApplicationContext.networkUuid(), + modificationApplicationContext.variantId(), + new ReportInfos(modificationApplicationContext.reportUuid(), modificationApplicationContext.reporterId()), + modifications) + ).toList(); + } + public Network cloneNetworkVariant(UUID networkUuid, String originVariantId, String destinationVariantId, @@ -230,6 +254,22 @@ public void deleteNetworkModifications(UUID groupUuid, List modificationsU } } + @Transactional + public List> moveModifications(@NonNull UUID destinationGroupUuid, @NonNull UUID originGroupUuid, UUID beforeModificationUuid, + @NonNull List modificationsToMoveUuids, @NonNull List applicationContexts, + boolean canBuildNode) { + // update origin/destinations groups to cut and paste all modificationsToMove + List modificationInfos = networkModificationRepository.moveModifications(destinationGroupUuid, originGroupUuid, modificationsToMoveUuids, beforeModificationUuid).stream() + .map(networkModificationRepository::getModificationInfos) + .toList(); + + return canBuildNode && !modificationInfos.isEmpty() ? applyModifications(modificationInfos, applicationContexts) : List.of(); + } + + /** + * TODO : Remove this method after the final integration of root networks + * Need to use the new method with ModificationApplicationContext DTO (see above) + */ @Transactional public Optional moveModifications(UUID destinationGroupUuid, UUID originGroupUuid, UUID beforeModificationUuid, UUID networkUuid, String variantId, @@ -240,22 +280,22 @@ public Optional moveModifications(UUID destinationGro if (canBuildNode && !movedEntities.isEmpty()) { // TODO remove canBuildNode ? // try to apply the moved modifications only (incremental mode) PreloadingStrategy preloadingStrategy = movedEntities.stream() - .map(e -> ModificationType.valueOf(e.getType())) - .reduce(ModificationType::maxStrategy).map(ModificationType::getStrategy).orElse(PreloadingStrategy.NONE); + .map(e -> ModificationType.valueOf(e.getType())) + .reduce(ModificationType::maxStrategy).map(ModificationType::getStrategy).orElse(PreloadingStrategy.NONE); NetworkInfos networkInfos = getNetworkInfos(networkUuid, variantId, preloadingStrategy); if (networkInfos.isVariantPresent()) { List movedModifications = movedEntities.stream() - .map(networkModificationRepository::getModificationInfos).toList(); + .map(networkModificationRepository::getModificationInfos).toList(); return Optional.of(modificationApplicator.applyModifications( - movedModifications, - networkInfos, - reportInfos)); + movedModifications, + networkInfos, + reportInfos)); } } return Optional.empty(); } - public void createModificationGroup(UUID sourceGroupUuid, UUID groupUuid) { + public void duplicateGroup(UUID sourceGroupUuid, UUID groupUuid) { try { networkModificationRepository.saveModificationInfos(groupUuid, networkModificationRepository.getActiveModificationsInfos(sourceGroupUuid)); } catch (NetworkModificationException e) { @@ -286,6 +326,20 @@ private Optional applyModifications(UUID networkUuid, return Optional.empty(); } + @Transactional + public List> duplicateModifications(@NonNull UUID targetGroupUuid, UUID originGroupUuid, @NonNull List modificationsUuids, @NonNull List applicationContexts) { + if (originGroupUuid != null && !modificationsUuids.isEmpty()) { // Duplicate modifications from a group or from a list only + throw new NetworkModificationServerException(DUPLICATION_ARGUMENT_INVALID); + } + List modificationInfos = originGroupUuid != null ? networkModificationRepository.getActiveModificationsInfos(originGroupUuid) : networkModificationRepository.getModificationsInfos(modificationsUuids); + networkModificationRepository.saveModificationInfos(targetGroupUuid, modificationInfos); + return applyModifications(modificationInfos, applicationContexts); + } + + /** + * TODO : Remove this method after the final integration of root networks + * Need to use the new method with ModificationApplicationContext DTO (see above) + */ @Transactional public Optional duplicateModifications(UUID targetGroupUuid, UUID networkUuid, String variantId, @@ -295,6 +349,17 @@ public Optional duplicateModifications(UUID targetGro return applyModifications(networkUuid, variantId, reportInfos, modificationInfos); } + @Transactional + public List> insertCompositeModifications(@NonNull UUID targetGroupUuid, @NonNull List modificationsUuids, @NonNull List applicationContexts) { + List modificationInfos = networkModificationRepository.getCompositeModificationsInfos(modificationsUuids); + networkModificationRepository.saveModificationInfos(targetGroupUuid, modificationInfos); + return applyModifications(modificationInfos, applicationContexts); + } + + /** + * TODO : Remove this method after the final integration of root networks (used only for move) + * Need to use the new method with ModificationApplicationContext DTO (see above) + */ @Transactional public Optional insertCompositeModifications(UUID targetGroupUuid, UUID networkUuid, String variantId, @@ -304,12 +369,6 @@ public Optional insertCompositeModifications(UUID tar return applyModifications(networkUuid, variantId, reportInfos, modificationInfos); } - public UUID createModificationInGroup(@NonNull ModificationInfos modificationsInfos) { - UUID groupUuid = UUID.randomUUID(); - networkModificationRepository.saveModificationInfos(groupUuid, List.of(modificationsInfos)); - return groupUuid; - } - @Transactional public UUID createNetworkCompositeModification(@NonNull List modificationUuids) { return networkModificationRepository.createNetworkCompositeModification(modificationUuids); @@ -319,16 +378,6 @@ public Map duplicateModifications(List sourceModificationUuids return networkModificationRepository.duplicateModifications(sourceModificationUuids); } - @Transactional - public Optional duplicateModificationsInGroup(UUID targetGroupUuid, - UUID networkUuid, String variantId, - ReportInfos reportInfos, - UUID originGroupUuid) { - List modificationsInfos = networkModificationRepository.getActiveModificationsInfos(originGroupUuid); - networkModificationRepository.saveModificationInfos(targetGroupUuid, modificationsInfos); - return applyModifications(networkUuid, variantId, reportInfos, modificationsInfos); - } - public void deleteStashedModificationInGroup(UUID groupUuid, boolean errorOnGroupNotFound) { networkModificationRepository.deleteStashedModificationInGroup(groupUuid, errorOnGroupNotFound); } diff --git a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java index 46f00237f..2ef7faf75 100644 --- a/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java +++ b/src/test/java/org/gridsuite/modification/server/ModificationControllerTest.java @@ -24,6 +24,7 @@ import org.gridsuite.modification.NetworkModificationException; import org.gridsuite.modification.dto.*; import org.gridsuite.modification.dto.LoadCreationInfos.LoadCreationInfosBuilder; +import org.gridsuite.modification.server.dto.ModificationApplicationContext; import org.gridsuite.modification.server.dto.ModificationMetadata; import org.gridsuite.modification.server.dto.NetworkModificationResult; import org.gridsuite.modification.server.dto.catalog.LineTypeInfos; @@ -59,6 +60,7 @@ import static org.gridsuite.modification.ModificationType.EQUIPMENT_ATTRIBUTE_MODIFICATION; import static org.gridsuite.modification.NetworkModificationException.Type.*; +import static org.gridsuite.modification.server.NetworkModificationServerException.Type.DUPLICATION_ARGUMENT_INVALID; import static org.gridsuite.modification.server.impacts.TestImpactUtils.*; import static org.gridsuite.modification.server.utils.TestUtils.assertLogMessage; import static org.gridsuite.modification.server.utils.assertions.Assertions.assertThat; @@ -177,6 +179,17 @@ private boolean existTombstonedEquipmentInfos(String equipmentId, UUID networkUu return tombstonedEquipmentInfosRepository.findAllByNetworkUuidAndVariantId(networkUuid, variantId).stream().anyMatch(t -> t.getId().equals(equipmentId)); } + private void assertApplicationStatusOKNew(MvcResult mvcResult) throws Exception { + List> networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + assertEquals(1, networkModificationResult.size()); + assertTrue(networkModificationResult.get(0).isPresent()); + assertNotEquals(NetworkModificationResult.ApplicationStatus.WITH_ERRORS, networkModificationResult.get(0).get().getApplicationStatus()); + } + + /** + * TODO : Remove this method after the final integration of root networks + * Need to use the new endpoint with modificationContextInfos DTO (see above) + */ private void assertApplicationStatusOK(MvcResult mvcResult) throws Exception { Optional networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); assertTrue(networkModificationResult.isPresent()); @@ -474,13 +487,14 @@ private List createSomeSwitchModifications(UUID groupId, int .equipmentId("v1b1") .build(); MvcResult mvcResult; + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); for (int i = 0; i < number; i++) { switchStatusModificationInfos.setEquipmentAttributeValue(openStates.get(i % 2)); - String switchStatusModificationInfosJson = objectWriter.writeValueAsString(switchStatusModificationInfos); - mvcResult = mockMvc.perform(post(URI_NETWORK_MODIF_BASE + "?networkUuid=" + TEST_NETWORK_ID + "&groupUuid=" + groupId + "&reportUuid=" + TEST_REPORT_ID + "&reporterId=" + UUID.randomUUID()) - .content(switchStatusModificationInfosJson).contentType(MediaType.APPLICATION_JSON)) + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(switchStatusModificationInfos, List.of(applicationContext))); + mvcResult = mockMvc.perform(post(URI_NETWORK_MODIF_BASE + "?groupUuid=" + groupId) + .content(bodyJson).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn(); - assertApplicationStatusOK(mvcResult); + assertApplicationStatusOKNew(mvcResult); } var modificationList = modificationRepository.getModifications(groupId, false, true); assertEquals(number, modificationList.size()); @@ -508,6 +522,102 @@ void testCopyModification() throws Exception { List modificationList = createSomeSwitchModifications(TEST_GROUP_ID, 3); List modificationUuidList = modificationList.stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); + // Duplicate [0] and [1], and append them at the end of the group modification list. + List duplicateModificationUuidList = new ArrayList<>(modificationUuidList.subList(0, 2)); + List badModificationUuidList = List.of(UUID.randomUUID(), UUID.randomUUID()); + duplicateModificationUuidList.addAll(badModificationUuidList); + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(duplicateModificationUuidList, List.of(applicationContext))); + MvcResult mvcResult = mockMvc.perform( + put("/v1/groups/" + TEST_GROUP_ID + "?action=COPY") + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + assertApplicationStatusOKNew(mvcResult); + + var newModificationList = modificationRepository.getModifications(TEST_GROUP_ID, false, true); + List newModificationUuidList = newModificationList.stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); + // now 5 modifications: first 0-1-2 are still the same, last 3-4 are new (duplicates of 0-1) + assertEquals(5, newModificationList.size()); + assertEquals(modificationUuidList, newModificationUuidList.subList(0, 3)); + // compare duplicates 0 and 3 (same data except uuid) + assertThat(newModificationList.get(3)).recursivelyEquals(modificationList.get(0)); + + // compare duplicates 1 and 4 (same data except uuid) + assertThat(newModificationList.get(4)).recursivelyEquals(modificationList.get(1)); + + // bad request error case: wrong action param + mockMvc.perform( + put("/v1/groups/" + TEST_GROUP_ID + "?action=XXXXXXX") + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + + // create 1 modification in another group + UUID otherGroupId = UUID.randomUUID(); + List modificationListOtherGroup = createSomeSwitchModifications(otherGroupId, 1); + List modificationUuidListOtherGroup = modificationListOtherGroup.stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); + + // Duplicate the same modifications, and append them at the end of this new group modification list. + duplicateModificationUuidList = new ArrayList<>(modificationUuidList.subList(0, 2)); + bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(duplicateModificationUuidList, List.of(applicationContext))); + mvcResult = mockMvc.perform( + put("/v1/groups/" + otherGroupId + "?action=COPY") + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + assertApplicationStatusOKNew(mvcResult); + + var newModificationListOtherGroup = modificationRepository.getModifications(otherGroupId, false, true); + List newModificationUuidListOtherGroup = newModificationListOtherGroup.stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); + // now 3 modifications in new group: first 0 is still the same, last 1-2 are new (duplicates of 0-1 from first group) + assertEquals(3, newModificationListOtherGroup.size()); + assertEquals(modificationUuidListOtherGroup, newModificationUuidListOtherGroup.subList(0, 1)); + // compare duplicates + assertThat(newModificationListOtherGroup.get(1)).recursivelyEquals(modificationList.get(0)); + assertThat(newModificationListOtherGroup.get(2)).recursivelyEquals(modificationList.get(1)); + + // Duplicate all modifications in TEST_GROUP_ID, and append them at the end of otherGroupId + applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(List.of(), List.of(applicationContext))); + mvcResult = mockMvc.perform( + put("/v1/groups/" + otherGroupId + "?action=COPY" + "&originGroupUuid=" + TEST_GROUP_ID) + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + assertApplicationStatusOKNew(mvcResult); + + newModificationListOtherGroup = modificationRepository.getModifications(otherGroupId, true, true); + // now 8 modifications in new group: first 3 are still the same, 5 last are new duplicates from first group + assertEquals(8, newModificationListOtherGroup.size()); + + // compare duplicates + modificationList = modificationRepository.getModifications(TEST_GROUP_ID, true, true); + for (int i = 3; i < 8; ++i) { + assertThat(newModificationListOtherGroup.get(i)).recursivelyEquals(modificationList.get(i - 3)); + } + + // Duplicate modifications from a group and from a list : illegal operation + applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(duplicateModificationUuidList, List.of(applicationContext))); + mvcResult = mockMvc.perform( + put("/v1/groups/" + otherGroupId + "?action=COPY" + "&originGroupUuid=" + TEST_GROUP_ID) + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()).andReturn(); + assertEquals(new NetworkModificationServerException(DUPLICATION_ARGUMENT_INVALID).getMessage(), mvcResult.getResponse().getContentAsString()); + } + + /** + * TODO : Remove this test after the final integration of root networks + * Need to use tne new test with modificationContextInfos DTO (see above) + */ + @Test + void testCopyModificationOld() throws Exception { + // create 3 modifications + List modificationList = createSomeSwitchModifications(TEST_GROUP_ID, 3); + List modificationUuidList = modificationList.stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); + // Duplicate [0] and [1], and append them at the end of the group modification list. List duplicateModificationUuidList = new ArrayList<>(modificationUuidList.subList(0, 2)); List badModificationUuidList = List.of(UUID.randomUUID(), UUID.randomUUID()); @@ -570,16 +680,14 @@ void testCopyModification() throws Exception { assertThat(newModificationListOtherGroup.get(2)).recursivelyEquals(modificationList.get(1)); // Duplicate all modifications in TEST_GROUP_ID, and append them at the end of otherGroupId + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(List.of(), List.of(applicationContext))); mvcResult = mockMvc.perform( - put("/v1/groups/" + otherGroupId + "/duplications" - + "?networkUuid=" + TEST_NETWORK_ID - + "&reportUuid=" + TEST_REPORT_ID - + "&reporterId=" + UUID.randomUUID() - + "&variantId=" + NetworkCreation.VARIANT_ID - + "&duplicateFrom=" + TEST_GROUP_ID) + put("/v1/groups/" + otherGroupId + "?action=COPY" + "&originGroupUuid=" + TEST_GROUP_ID) + .content(bodyJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn(); - assertApplicationStatusOK(mvcResult); + assertApplicationStatusOKNew(mvcResult); newModificationListOtherGroup = modificationRepository.getModifications(otherGroupId, true, true); // now 8 modifications in new group: first 3 are still the same, 5 last are new duplicates from first group @@ -679,14 +787,11 @@ void testMoveModificationInSameGroup() throws Exception { stream().map(ModificationInfos::getUuid).collect(Collectors.toList()); // swap modifications: move [1] before [0] - List movingModificationUuidList = Collections.singletonList(modificationUuidList.get(1)); - String url = "/v1/groups/" + TEST_GROUP_ID + "?action=MOVE" - + "&networkUuid=" + TEST_NETWORK_ID - + "&reportUuid=" + TEST_REPORT_ID - + "&reporterId=" + UUID.randomUUID() - + "&variantId=" + NetworkCreation.VARIANT_ID - + "&before=" + modificationUuidList.get(0); - mockMvc.perform(put(url).content(objectWriter.writeValueAsString(movingModificationUuidList)) + List movingModificationUuidList = List.of(modificationUuidList.get(1)); + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(movingModificationUuidList, List.of(applicationContext))); + String url = "/v1/groups/" + TEST_GROUP_ID + "?action=MOVE" + "&before=" + modificationUuidList.get(0); + mockMvc.perform(put(url).content(bodyJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -704,6 +809,68 @@ void testNetworkCompositeModification() throws Exception { List modificationList = createSomeSwitchModifications(TEST_GROUP_ID, modificationsNumber); assertEquals(modificationsNumber, modificationRepository.getModifications(TEST_GROUP_ID, true, true).size()); + // Create a composite modification with the switch modification + List modificationUuids = modificationList.stream().map(ModificationInfos::getUuid).toList(); + MvcResult mvcResult; + mvcResult = mockMvc.perform(post(URI_COMPOSITE_NETWORK_MODIF_BASE) + .content(mapper.writeValueAsString(modificationUuids)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + ModificationInfos compositeModificationInfos = CompositeModificationInfos.builder() + .modifications(modificationList) + .build(); + UUID compositeModificationUuid = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + assertThat(modificationRepository.getModificationInfo(compositeModificationUuid)).recursivelyEquals(compositeModificationInfos); + assertEquals(modificationsNumber, modificationRepository.getModifications(TEST_GROUP_ID, true, true).size()); + + // get the composite modification (metadata only) + mvcResult = mockMvc.perform(get(URI_GET_COMPOSITE_NETWORK_MODIF_CONTENT + compositeModificationUuid + "/network-modifications")) + .andExpect(status().isOk()).andReturn(); + List compositeModificationContent = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + assertEquals(modificationsNumber, compositeModificationContent.size()); + assertNotNull(compositeModificationContent.get(0).getMessageType()); + assertNotNull(compositeModificationContent.get(0).getMessageValues()); + assertNull(((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeName()); + assertNull(((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentAttributeValue()); + assertNull(((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentType()); + assertNull(((EquipmentAttributeModificationInfos) compositeModificationContent.get(0)).getEquipmentId()); + + // get the composite modification (complete data) + mvcResult = mockMvc.perform(get(URI_GET_COMPOSITE_NETWORK_MODIF_CONTENT + compositeModificationUuid + "/network-modifications?onlyMetadata=false")) + .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()); + + // Insert the composite modification in the group + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(List.of(compositeModificationUuid), List.of(applicationContext))); + mvcResult = mockMvc.perform( + put("/v1/groups/" + TEST_GROUP_ID + "?action=INSERT") + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + assertApplicationStatusOKNew(mvcResult); + + List newModificationList = modificationRepository.getModifications(TEST_GROUP_ID, false, true); + assertEquals(modificationsNumber * 2, newModificationList.size()); + List newModificationUuidList = newModificationList.stream().map(ModificationInfos::getUuid).toList(); + assertEquals(modificationUuids.get(0), newModificationUuidList.get(0)); + assertThat(modificationList.get(0)).recursivelyEquals(newModificationList.get(modificationsNumber)); + } + + /** + * TODO : Remove this test after the final integration of root networks + * Need to use tne new test with modificationContextInfos DTO (see above) + */ + @Test + void testNetworkCompositeModificationOld() throws Exception { + // Insert some switch modifications in the group + int modificationsNumber = 2; + List modificationList = createSomeSwitchModifications(TEST_GROUP_ID, modificationsNumber); + assertEquals(modificationsNumber, modificationRepository.getModifications(TEST_GROUP_ID, true, true).size()); + // Create a composite modification with the switch modification List modificationUuids = modificationList.stream().map(ModificationInfos::getUuid).toList(); MvcResult mvcResult; @@ -773,24 +940,20 @@ void testMoveModificationBetweenTwoGroups() throws Exception { UUID originSingleModification = createDeletionModification(TEST_GROUP2_ID, IdentifiableType.LOAD, "v1load").getUuid(); // cut origin[0] and append to destination - List movingModificationUuidList = Collections.singletonList(originSingleModification); - String url = "/v1/groups/" + TEST_GROUP_ID + "?action=MOVE" - + "&networkUuid=" + TEST_NETWORK_ID - + "&reportUuid=" + TEST_REPORT_ID - + "&reporterId=" + UUID.randomUUID() - + "&variantId=" + NetworkCreation.VARIANT_ID - + "&originGroupUuid=" + TEST_GROUP2_ID - + "&build=true"; - - MvcResult mvcResult = mockMvc.perform(put(url).content(objectWriter.writeValueAsString(movingModificationUuidList)) + List movingModificationUuidList = List.of(originSingleModification); + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, NetworkCreation.VARIANT_ID, TEST_REPORT_ID, UUID.randomUUID()); + String bodyJson = objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(movingModificationUuidList, List.of(applicationContext))); + String url = "/v1/groups/" + TEST_GROUP_ID + "?action=MOVE" + "&originGroupUuid=" + TEST_GROUP2_ID + "&build=true"; + MvcResult mvcResult = mockMvc.perform(put(url).content(bodyJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); // incremental build: deletion impacts expected, all related to the moved load deletion (dealing with "s1" substation) - Optional networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); - assertTrue(networkModificationResult.isPresent()); - networkModificationResult.get().getNetworkImpacts().forEach(i -> { + List> networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + assertEquals(1, networkModificationResult.size()); + assertTrue(networkModificationResult.get(0).isPresent()); + networkModificationResult.get(0).get().getNetworkImpacts().forEach(i -> { assertTrue(i.isSimple()); SimpleElementImpact simpleImpact = (SimpleElementImpact) i; assertEquals(Set.of(substationS1), simpleImpact.getSubstationIds()); @@ -1477,15 +1640,15 @@ void testCreateVoltageInitModification() throws Exception { .build())) .build(); - MvcResult mvcResult = mockMvc.perform(post("/v1/groups/modification") - .content(objectWriter.writeValueAsString(modificationsInfos1)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn(); - UUID groupUuid = UUID.fromString(mapper.readValue(mvcResult.getResponse().getContentAsString(), String.class)); + UUID groupUuid = UUID.randomUUID(); + mockMvc.perform(post(URI_NETWORK_MODIF_BASE) + .queryParam("groupUuid", groupUuid.toString()) + .content(objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(modificationsInfos1, List.of()))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); // Get the modifications - mvcResult = mockMvc.perform(get("/v1/groups/{groupUuid}/network-modifications?onlyMetadata=false", groupUuid)).andExpectAll( + MvcResult mvcResult = mockMvc.perform(get("/v1/groups/{groupUuid}/network-modifications?onlyMetadata=false", groupUuid)).andExpectAll( status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); @@ -1630,14 +1793,15 @@ void testApplyModificationsFromUuids() throws Exception { CompositeModificationInfos compositeModificationInfos = CompositeModificationInfos.builder() .modifications(List.of(switchStatusModificationInfos)) .build(); - MvcResult mvcResult = mockMvc.perform(post("/v1/groups/modification") - .content(objectWriter.writeValueAsString(compositeModificationInfos)) + + UUID groupUuid = UUID.randomUUID(); + mockMvc.perform(post(URI_NETWORK_MODIF_BASE) + .queryParam("groupUuid", groupUuid.toString()) + .content(objectWriter.writeValueAsString(org.springframework.data.util.Pair.of(compositeModificationInfos, List.of()))) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn(); - UUID groupUuid = UUID.fromString(mapper.readValue(mvcResult.getResponse().getContentAsString(), String.class)); + .andExpect(status().isOk()); - mvcResult = mockMvc.perform(get("/v1/groups/{groupUuid}/network-modifications?onlyMetadata=false", groupUuid)).andExpectAll( + MvcResult mvcResult = mockMvc.perform(get("/v1/groups/{groupUuid}/network-modifications?onlyMetadata=false", groupUuid)).andExpectAll( status().isOk(), content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List modificationsInfos = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); diff --git a/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java b/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java index dbbec9625..e5336086d 100644 --- a/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java +++ b/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java @@ -81,7 +81,7 @@ void testVoltageInitDuplicationLogs(final ApplicationStatus resultStatus, final final UUID networkUuuid = UUID.fromString("11111111-1111-1111-1111-111111111111"); final UUID reportUuid = UUID.fromString("88888888-8888-8888-8888-888888888888"); - //simulate PUT /v1/groups/abc/duplications?networkUuid=0000&reportUuid=0000&reporterId=0000&variantId=0000&duplicateFrom=0000 + //simulate PUT /v1/groups/abc?action=COPY with body ModificationApplicationContext(networkUuid=0000, reportUuid=0000, reporterId=0000, variantId=0000, duplicateFrom=0000) assertThat(networkModificationApplicator.applyModifications( List.of(modificationInfos), new NetworkInfos(network, networkUuuid, true), diff --git a/src/test/java/org/gridsuite/modification/server/modifications/tabularmodifications/TabularGeneratorModificationsTest.java b/src/test/java/org/gridsuite/modification/server/modifications/tabularmodifications/TabularGeneratorModificationsTest.java index fa5bfca49..63e2558ee 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/tabularmodifications/TabularGeneratorModificationsTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/tabularmodifications/TabularGeneratorModificationsTest.java @@ -169,7 +169,7 @@ void testSqlRequestsCountOnPostGroups2() throws Exception { } /* - PUT /v1/groups/{groupUuid}/duplications SQL requests analysis + PUT /v1/groups/{groupUuid}?action=COPY SQL requests analysis Given an example with 2 tabular modifications having 1000 modifications each diff --git a/src/test/java/org/gridsuite/modification/server/service/BuildTest.java b/src/test/java/org/gridsuite/modification/server/service/BuildTest.java index 646fb3474..555d77961 100644 --- a/src/test/java/org/gridsuite/modification/server/service/BuildTest.java +++ b/src/test/java/org/gridsuite/modification/server/service/BuildTest.java @@ -24,12 +24,7 @@ import org.gridsuite.modification.server.ContextConfigurationWithTestChannel; import org.gridsuite.modification.TapChangerType; import org.gridsuite.modification.dto.*; -import org.gridsuite.modification.server.dto.BuildInfos; -import org.gridsuite.modification.server.dto.NetworkInfos; -import org.gridsuite.modification.server.dto.NetworkModificationResult; -import org.gridsuite.modification.server.dto.ReportInfos; -import org.gridsuite.modification.server.dto.SubstationInfos; -import org.gridsuite.modification.server.dto.VoltageLevelInfos; +import org.gridsuite.modification.server.dto.*; import org.gridsuite.modification.server.dto.elasticsearch.EquipmentInfos; import org.gridsuite.modification.server.dto.elasticsearch.TombstonedEquipmentInfos; import org.gridsuite.modification.server.elasticsearch.EquipmentInfosRepository; @@ -925,14 +920,19 @@ void testApplyModificationWithErrors(final MockWebServer server) { assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches(String.format("/v1/reports/%s", reportUuid)))); // Incremental mode : No error send with exception - Optional networkModificationResult2 = networkModificationService.createNetworkModification(TEST_NETWORK_ID, variantId, groupUuid, new ReportInfos(reportUuid, reporterId), loadCreationInfos); - assertTrue(networkModificationResult2.isPresent()); + ModificationApplicationContext applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, variantId, reportUuid, reporterId); + List> networkModificationResult2 = networkModificationService.createNetworkModification(groupUuid, loadCreationInfos, List.of(applicationContext)); + assertEquals(1, networkModificationResult2.size()); + assertTrue(networkModificationResult2.get(0).isPresent()); testEmptyImpactsWithErrors(networkModificationResult); assertTrue(TestUtils.getRequestsDone(1, server).stream().anyMatch(r -> r.matches(String.format("/v1/reports/%s", reportUuid)))); testNetworkModificationsCount(groupUuid, 1); // Save mode only (variant does not exist) : No log and no error send with exception - assertTrue(networkModificationService.createNetworkModification(TEST_NETWORK_ID, UUID.randomUUID().toString(), groupUuid, new ReportInfos(reportUuid, reporterId), loadCreationInfos).isEmpty()); + applicationContext = new ModificationApplicationContext(TEST_NETWORK_ID, UUID.randomUUID().toString(), reportUuid, reporterId); + networkModificationResult2 = networkModificationService.createNetworkModification(groupUuid, loadCreationInfos, List.of(applicationContext)); + assertEquals(1, networkModificationResult2.size()); + assertTrue(networkModificationResult2.get(0).isEmpty()); testNetworkModificationsCount(groupUuid, 2); } diff --git a/src/test/java/org/gridsuite/modification/server/utils/ApiUtils.java b/src/test/java/org/gridsuite/modification/server/utils/ApiUtils.java index b780670a3..5fb96225e 100644 --- a/src/test/java/org/gridsuite/modification/server/utils/ApiUtils.java +++ b/src/test/java/org/gridsuite/modification/server/utils/ApiUtils.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.gridsuite.modification.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.ModificationApplicationContext; import org.gridsuite.modification.server.dto.NetworkModificationResult; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -53,17 +54,19 @@ public static void postGroups(MockMvc mockMvc, UUID originGroupUuid, UUID target } public static Optional putGroupsDuplications(MockMvc mockMvc, UUID originGroupUuid, UUID targetGroupUuid, UUID networkUuid) throws Exception { + ModificationApplicationContext applicationContext = new ModificationApplicationContext(networkUuid, UUID.randomUUID().toString(), UUID.randomUUID(), UUID.randomUUID()); + String bodyJson = getObjectMapper().writeValueAsString(org.springframework.data.util.Pair.of(List.of(), List.of(applicationContext))); MvcResult mvcResult = mockMvc.perform( - put("/v1/groups/{groupUuid}/duplications", targetGroupUuid) - .param("networkUuid", networkUuid.toString()) - .param("reporterId", UUID.randomUUID().toString()) - .param("duplicateFrom", originGroupUuid.toString()) - .param("reportUuid", UUID.randomUUID().toString()) - .param("variantId", UUID.randomUUID().toString()) + put("/v1/groups/{groupUuid}", targetGroupUuid) + .param("action", "COPY") + .param("originGroupUuid", originGroupUuid.toString()) + .content(bodyJson) + .contentType(MediaType.APPLICATION_JSON) ) .andExpectAll(status().isOk()) .andReturn(); - return getObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + List> result = getObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { }); + return result.isEmpty() ? Optional.empty() : result.get(0); } public static Optional putGroupsWithCopy(MockMvc mockMvc, UUID targetGroupUuid, List modificationUuids, UUID networkUuid) throws Exception {