diff --git a/src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java index 687281c48..e681a42c1 100644 --- a/src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java @@ -72,7 +72,8 @@ protected ResponseEntity handleStudyException(StudyException exception) MAXIMUM_ROOT_NETWORK_BY_STUDY_REACHED, MAXIMUM_TAG_LENGTH_EXCEEDED, TOO_MANY_NAD_CONFIGS, - TOO_MANY_MAP_CARDS + TOO_MANY_MAP_CARDS, + MOVE_NETWORK_MODIFICATION_FAILED -> ResponseEntity.status(HttpStatus.FORBIDDEN).body(exception.getMessage()); case CANT_DELETE_ROOT_NODE -> ResponseEntity.status(HttpStatus.FORBIDDEN).body(NOT_ALLOWED); case CREATE_NETWORK_MODIFICATION_FAILED, diff --git a/src/main/java/org/gridsuite/study/server/StudyException.java b/src/main/java/org/gridsuite/study/server/StudyException.java index 062a9ba78..884f64d4b 100644 --- a/src/main/java/org/gridsuite/study/server/StudyException.java +++ b/src/main/java/org/gridsuite/study/server/StudyException.java @@ -52,6 +52,7 @@ public enum Type { CREATE_NETWORK_MODIFICATION_FAILED, UPDATE_NETWORK_MODIFICATION_FAILED, DELETE_NETWORK_MODIFICATION_FAILED, + MOVE_NETWORK_MODIFICATION_FAILED, UNKNOWN_EQUIPMENT_TYPE, BAD_NODE_TYPE, NETWORK_NOT_FOUND, 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 c45cf2aa3..1d667ddfb 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -17,6 +17,8 @@ import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.gridsuite.study.server.StudyApi; +import org.gridsuite.study.server.StudyConstants.ModificationsActionType; +import org.gridsuite.study.server.StudyConstants.SldDisplayMode; import org.gridsuite.study.server.StudyException; import org.gridsuite.study.server.StudyException.Type; import org.gridsuite.study.server.dto.*; @@ -642,20 +644,30 @@ private void handleMoveNetworkModification(UUID studyUuid, UUID nodeUuid, UUID m public ResponseEntity moveOrCopyModifications(@PathVariable("studyUuid") UUID studyUuid, @PathVariable("nodeUuid") UUID nodeUuid, @RequestParam("action") ModificationsActionType action, + @Nullable @RequestParam("originStudyUuid") UUID originStudyUuid, @Nullable @RequestParam("originNodeUuid") UUID originNodeUuid, @RequestBody List modificationsToCopyUuidList, @RequestHeader(HEADER_USER_ID) String userId) { studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); studyService.assertCanUpdateModifications(studyUuid, nodeUuid); - if (originNodeUuid != null) { - studyService.assertIsNodeExist(studyUuid, originNodeUuid); - studyService.assertCanUpdateModifications(studyUuid, originNodeUuid); + if (originNodeUuid != null && !nodeUuid.equals(originNodeUuid)) { + if (originStudyUuid != null && !studyUuid.equals(originStudyUuid)) { + studyService.assertIsStudyAndNodeExist(originStudyUuid, originNodeUuid); + studyService.assertCanUpdateModifications(originStudyUuid, originNodeUuid); + } else { + studyService.assertIsStudyAndNodeExist(studyUuid, originNodeUuid); + studyService.assertCanUpdateModifications(studyUuid, originNodeUuid); + } } switch (action) { case COPY, INSERT: - handleDuplicateOrInsertNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyUuidList, userId, action); + handleDuplicateOrInsertNetworkModifications(studyUuid, nodeUuid, originStudyUuid, originNodeUuid, modificationsToCopyUuidList, userId, action); break; case MOVE: + // we don't cut - paste modifications from different studies + if (originStudyUuid != null && !studyUuid.equals(originStudyUuid)) { + throw new StudyException(Type.MOVE_NETWORK_MODIFICATION_FAILED); + } handleMoveNetworkModifications(studyUuid, nodeUuid, originNodeUuid, modificationsToCopyUuidList, userId); break; default: @@ -664,13 +676,13 @@ public ResponseEntity moveOrCopyModifications(@PathVariable("studyUuid") U return ResponseEntity.ok().build(); } - private void handleDuplicateOrInsertNetworkModifications(UUID studyUuid, UUID targetNodeUuid, UUID originNodeUuid, List modificationsToCopyUuidList, String userId, ModificationsActionType action) { - studyService.assertNoBlockedNodeInStudy(studyUuid, targetNodeUuid); - studyService.invalidateNodeTreeWithLF(studyUuid, targetNodeUuid); + private void handleDuplicateOrInsertNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, UUID originStudyUuid, UUID originNodeUuid, List modificationsToCopyUuidList, String userId, ModificationsActionType action) { + studyService.assertNoBlockedNodeInStudy(targetStudyUuid, targetNodeUuid); + studyService.invalidateNodeTreeWithLF(targetStudyUuid, targetNodeUuid); try { - studyService.duplicateOrInsertNetworkModifications(studyUuid, targetNodeUuid, originNodeUuid, modificationsToCopyUuidList, userId, action); + studyService.duplicateOrInsertNetworkModifications(targetStudyUuid, targetNodeUuid, originStudyUuid, originNodeUuid, modificationsToCopyUuidList, userId, action); } finally { - studyService.unblockNodeTree(studyUuid, targetNodeUuid); + studyService.unblockNodeTree(targetStudyUuid, targetNodeUuid); } } diff --git a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java index 2c01b50c5..49f2253f5 100644 --- a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java +++ b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java @@ -517,6 +517,14 @@ public ModificationApplicationContext getNetworkModificationApplicationContext(U return new ModificationApplicationContext(networkUuid, variantId, reportUuid, nodeUuid, rootNetworkNodeInfoEntity.getModificationsUuidsToExclude()); } + @Transactional + public ModificationApplicationContext createModificationApplicationContextAllActivated(UUID rootNetworkUuid, UUID nodeUuid, UUID networkUuid) { + RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = rootNetworkNodeInfoRepository.findByNodeInfoIdAndRootNetworkId(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND)); + String variantId = rootNetworkNodeInfoEntity.getVariantId(); + UUID reportUuid = rootNetworkNodeInfoEntity.getModificationReports().get(nodeUuid); + return new ModificationApplicationContext(networkUuid, variantId, reportUuid, nodeUuid, new HashSet<>()); + } + private List getReportUuids(RootNetworkNodeInfo rootNetworkNodeInfo) { return Stream.of( rootNetworkNodeInfo.getModificationReports().values().stream(), 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 c5b89334c..4b5155a36 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2421,43 +2421,50 @@ private void emitNetworkModificationImpactsForAllRootNetworks(List modificationsUuis, String userId, StudyConstants.ModificationsActionType action) { + public void duplicateOrInsertNetworkModifications(UUID targetStudyUuid, UUID targetNodeUuid, UUID originStudyUuid, UUID originNodeUuid, List modificationsUuis, String userId, StudyConstants.ModificationsActionType action) { List childrenUuids = networkModificationTreeService.getChildrenUuids(targetNodeUuid); - notificationService.emitStartModificationEquipmentNotification(studyUuid, targetNodeUuid, childrenUuids, NotificationService.MODIFICATIONS_UPDATING_IN_PROGRESS); + notificationService.emitStartModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids, NotificationService.MODIFICATIONS_UPDATING_IN_PROGRESS); try { - checkStudyContainsNode(studyUuid, targetNodeUuid); + checkStudyContainsNode(targetStudyUuid, targetNodeUuid); - List studyRootNetworkEntities = getStudyRootNetworks(studyUuid); - UUID groupUuid = networkModificationTreeService.getModificationGroupUuid(targetNodeUuid); + List targetStudyRootNetworkEntities = getStudyRootNetworks(targetStudyUuid); + UUID targetGroupUuid = networkModificationTreeService.getModificationGroupUuid(targetNodeUuid); - List modificationApplicationContexts = studyRootNetworkEntities.stream() - .map(rootNetworkEntity -> rootNetworkNodeInfoService.getNetworkModificationApplicationContext(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) - .toList(); + List modificationApplicationContexts; + if (originNodeUuid == null || targetStudyUuid.equals(originStudyUuid)) { + modificationApplicationContexts = targetStudyRootNetworkEntities.stream() + .map(rootNetworkEntity -> rootNetworkNodeInfoService.getNetworkModificationApplicationContext(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) + .toList(); + } else { + modificationApplicationContexts = targetStudyRootNetworkEntities.stream() + .map(rootNetworkEntity -> rootNetworkNodeInfoService.createModificationApplicationContextAllActivated(rootNetworkEntity.getId(), targetNodeUuid, rootNetworkEntity.getNetworkUuid())) + .toList(); + } - NetworkModificationsResult networkModificationResults = networkModificationService.duplicateOrInsertModifications(groupUuid, action, Pair.of(modificationsUuis, modificationApplicationContexts)); + NetworkModificationsResult networkModificationResults = networkModificationService.duplicateOrInsertModifications(targetGroupUuid, action, Pair.of(modificationsUuis, modificationApplicationContexts)); Map originToDuplicateModificationsUuids = new HashMap<>(); for (int i = 0; i < modificationsUuis.size(); i++) { originToDuplicateModificationsUuids.put(modificationsUuis.get(i), networkModificationResults.modificationUuids().get(i)); } - rootNetworkNodeInfoService.copyModificationsToExclude(originNodeUuid, targetNodeUuid, originToDuplicateModificationsUuids); + rootNetworkNodeInfoService.copyModificationsToExclude((originNodeUuid != null) ? originNodeUuid : targetNodeUuid, targetNodeUuid, originToDuplicateModificationsUuids); 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(studyUuid, targetNodeUuid, studyRootNetworkEntities.get(index).getId(), modificationResultOpt.get()); + if (modificationResultOpt.isPresent() && targetStudyRootNetworkEntities.get(index) != null) { + emitNetworkModificationImpacts(targetStudyUuid, targetNodeUuid, targetStudyRootNetworkEntities.get(index).getId(), modificationResultOpt.get()); } index++; } } } finally { - notificationService.emitEndModificationEquipmentNotification(studyUuid, targetNodeUuid, childrenUuids); + notificationService.emitEndModificationEquipmentNotification(targetStudyUuid, targetNodeUuid, childrenUuids); } - notificationService.emitElementUpdated(studyUuid, userId); + notificationService.emitElementUpdated(targetStudyUuid, userId); } private void checkStudyContainsNode(UUID studyUuid, UUID nodeUuid) { 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 717315c76..738e54f2a 100644 --- a/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java +++ b/src/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.java @@ -320,14 +320,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(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); + studyService.duplicateOrInsertNetworkModifications(studyEntity.getId(), firstNode.getId(), studyEntity.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); RootNetworkNodeInfoEntity upToDateRootNetworkNodeInfoEntity1 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(firstNode.getId(), rootNetworkBasicInfos.get(0).rootNetworkUuid()).orElseThrow(() -> new StudyException(StudyException.Type.ROOT_NETWORK_NOT_FOUND)); RootNetworkNodeInfoEntity upToDateRootNetworkNodeInfoEntity2 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(firstNode.getId(), rootNetworkBasicInfos.get(1).rootNetworkUuid()).orElseThrow(() -> new StudyException(StudyException.Type.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(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); + studyService.duplicateOrInsertNetworkModifications(studyEntity.getId(), secondNode.getId(), studyEntity.getId(), firstNode.getId(), modificationsToDuplicate, USER_ID, StudyConstants.ModificationsActionType.COPY); upToDateRootNetworkNodeInfoEntity1 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(secondNode.getId(), rootNetworkBasicInfos.get(0).rootNetworkUuid()).orElseThrow(() -> new StudyException(StudyException.Type.ROOT_NETWORK_NOT_FOUND)); upToDateRootNetworkNodeInfoEntity2 = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(secondNode.getId(), rootNetworkBasicInfos.get(1).rootNetworkUuid()).orElseThrow(() -> new StudyException(StudyException.Type.ROOT_NETWORK_NOT_FOUND)); assertEquals(expectedExcludedModification1, upToDateRootNetworkNodeInfoEntity1.getModificationsUuidsToExclude());