From d470ec5f91930b1074bd0e3c52b9f704a7b78fdc Mon Sep 17 00:00:00 2001 From: sBouzols Date: Thu, 30 Apr 2026 11:22:52 +0200 Subject: [PATCH 1/2] feat(): add `getLoadFlowStatuses` Signed-off-by: sBouzols --- .../RootNetworkNodeInfoRepository.java | 2 + .../study/server/service/LoadFlowService.java | 26 +++++++++++++ .../service/RootNetworkNodeInfoService.java | 38 +++++++++++++------ .../study/server/service/StudyService.java | 3 +- .../server/NetworkModificationTreeTest.java | 6 +-- .../studycontroller/NodeControllerTest.java | 2 +- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/repository/rootnetwork/RootNetworkNodeInfoRepository.java b/src/main/java/org/gridsuite/study/server/repository/rootnetwork/RootNetworkNodeInfoRepository.java index 22a7fb788..ea8776807 100644 --- a/src/main/java/org/gridsuite/study/server/repository/rootnetwork/RootNetworkNodeInfoRepository.java +++ b/src/main/java/org/gridsuite/study/server/repository/rootnetwork/RootNetworkNodeInfoRepository.java @@ -49,6 +49,8 @@ public interface RootNetworkNodeInfoRepository extends JpaRepository findAllWithRootNetworkByNodeInfoId(UUID nodeInfoId); + List findAllByNodeInfoIdInAndRootNetworkId(List nodeInfoIds, UUID rootNetworkUuid); + Optional findByNodeInfoIdAndRootNetworkId(UUID nodeInfoId, UUID rootNetworkUuid); @EntityGraph(attributePaths = {"modificationsUuidsToExclude"}, type = EntityGraph.EntityGraphType.LOAD) diff --git a/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java b/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java index 7945e6d33..f9631c464 100644 --- a/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java +++ b/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java @@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -143,6 +144,22 @@ public LoadFlowStatus getLoadFlowStatus(UUID resultUuid) { return restTemplate.getForObject(loadFlowServerBaseUri + path, LoadFlowStatus.class); } + public Map getLoadFlowStatuses(List resultUuids) { + if (resultUuids == null || resultUuids.isEmpty()) { + return null; + } + + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + LOADFLOW_API_VERSION + "/results/statuses"); + String path = uriComponentsBuilder.toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); + + return restTemplate.exchange(loadFlowServerBaseUri + path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); + } + public void stopLoadFlow(UUID studyUuid, UUID nodeUuid, UUID rootNetworkUuid, UUID resultUuid, String userId) { Objects.requireNonNull(studyUuid); Objects.requireNonNull(nodeUuid); @@ -198,6 +215,15 @@ public void assertLoadFlowNotRunning(UUID resultUuid) { } } + public void assertLoadFlowsNotRunning(List resultUuids) { + Map loadFlowStatuses = getLoadFlowStatuses(resultUuids); + // this is O(n) complexity, maybe we should adapt endoint to simply check LoadFlowsNotRunning + // for a list of resultUuids returning boolean if encounter one RUNNING computation ? + if (loadFlowStatuses != null && loadFlowStatuses.containsValue(LoadFlowStatus.RUNNING)) { + throw new StudyException(COMPUTATION_RUNNING); + } + } + public List getLimitViolations(UUID resultUuid, String filters, String globalFilters, Sort sort, UUID networkUuid, String variantId) { List result = new ArrayList<>(); 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 002b34baf..d414ceacb 100644 --- a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java +++ b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java @@ -449,6 +449,10 @@ public Optional getRootNetworkNodeInfo(UUID nodeUuid, return rootNetworkNodeInfoRepository.findByNodeInfoIdAndRootNetworkId(nodeUuid, rootNetworkUuid); } + public List getRootNetworkNodeInfos(List nodeUuids, UUID rootNetworkUuid) { + return rootNetworkNodeInfoRepository.findAllByNodeInfoIdInAndRootNetworkId(nodeUuids, rootNetworkUuid); + } + private static UUID getComputationResultUuid(RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity, ComputationType computationType) { return switch (computationType) { case LOAD_FLOW -> rootNetworkNodeInfoEntity.getLoadFlowResultUuid(); @@ -470,6 +474,14 @@ public UUID getComputationResultUuid(UUID nodeUuid, UUID rootNetworkUuid, Comput return rootNetworkNodeInfoEntityOpt.map(rootNetworkNodeInfoEntity -> getComputationResultUuid(rootNetworkNodeInfoEntity, computationType)).orElse(null); } + public List getComputationResultUuids(List nodeUuids, UUID rootNetworkUuid, ComputationType computationType) { + List rootNetworkNodeInfoEntities = getRootNetworkNodeInfos(nodeUuids, rootNetworkUuid); + return rootNetworkNodeInfoEntities.stream() + .map(rootNetworkNodeInfoEntity -> getComputationResultUuid(rootNetworkNodeInfoEntity, computationType)) + .filter(Objects::nonNull) + .toList(); + } + public List getComputationResultUuids(UUID studyUuid, ComputationType computationType) { return rootNetworkNodeInfoRepository.findAllByRootNetworkStudyId(studyUuid).stream() .map(rootNetworkNodeInfoEntity -> getComputationResultUuid(rootNetworkNodeInfoEntity, computationType)) @@ -656,19 +668,23 @@ private List getReportUuids(RootNetworkNodeInfo rootNetworkNodeInfo) { .toList(); } - public void assertComputationNotRunning(UUID nodeUuid, UUID rootNetworkUuid) { - loadFlowService.assertLoadFlowNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, LOAD_FLOW)); - securityAnalysisService.assertSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SECURITY_ANALYSIS)); - dynamicSimulationService.assertDynamicSimulationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SIMULATION)); - dynamicSecurityAnalysisService.assertDynamicSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SECURITY_ANALYSIS)); - dynamicMarginCalculationService.assertDynamicMarginCalculationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_MARGIN_CALCULATION)); - sensitivityAnalysisService.assertSensitivityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SENSITIVITY_ANALYSIS)); - shortCircuitService.assertShortCircuitAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT), getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT_ONE_BUS)); - voltageInitService.assertVoltageInitNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, VOLTAGE_INITIALIZATION)); - stateEstimationService.assertStateEstimationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, STATE_ESTIMATION)); - pccMinService.assertPccMinNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, PCC_MIN)); + public void assertComputationsNotRunning(List nodeUuids, UUID rootNetworkUuid) { + nodeUuids.forEach(nodeUuid -> { + securityAnalysisService.assertSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SECURITY_ANALYSIS)); + dynamicSimulationService.assertDynamicSimulationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SIMULATION)); + dynamicSecurityAnalysisService.assertDynamicSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SECURITY_ANALYSIS)); + dynamicMarginCalculationService.assertDynamicMarginCalculationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_MARGIN_CALCULATION)); + sensitivityAnalysisService.assertSensitivityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SENSITIVITY_ANALYSIS)); + shortCircuitService.assertShortCircuitAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT), getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT_ONE_BUS)); + voltageInitService.assertVoltageInitNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, VOLTAGE_INITIALIZATION)); + stateEstimationService.assertStateEstimationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, STATE_ESTIMATION)); + pccMinService.assertPccMinNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, PCC_MIN)); + }); + loadFlowService.assertLoadFlowsNotRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, LOAD_FLOW)); } + + /*************************** * GET COMPUTATION RESULTS * ***************************/ 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 0a2566e2a..628de2519 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -1152,8 +1152,7 @@ public void assertCanBuildNode(UUID rootNetworkUuid, UUID nodeUuid) { } private void assertNoBuildNoComputationInTree(UUID rootNetworkUuid, List nodesUuids) { - // TODO modify computations endpoints to test multiple uuids - nodesUuids.forEach(uuid -> rootNetworkNodeInfoService.assertComputationNotRunning(uuid, rootNetworkUuid)); + rootNetworkNodeInfoService.assertComputationsNotRunning(nodesUuids, rootNetworkUuid); rootNetworkNodeInfoService.assertNoBuildingNode(rootNetworkUuid, nodesUuids); } diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java index 65bac6da3..b203a2791 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java @@ -449,7 +449,7 @@ private void assertForbiddenNodeInsertions(UUID studyId, String userId, NetworkModificationNode security1, NetworkModificationNode security2) throws Exception { // Construction node cannot be inserted before a security node - doNothing().when(rootNetworkNodeInfoService).assertComputationNotRunning(any(), any()); + doNothing().when(rootNetworkNodeInfoService).assertComputationsNotRunning(any(), any()); mockMvc.perform(post("/v1/studies/{studyUuid}/tree/nodes?nodeToCutUuid={nodeUuid}&referenceNodeUuid={referenceNodeUuid}&insertMode={insertMode}", studyId, construction2.getId(), security1.getId(), InsertMode.BEFORE) .header(USER_ID_HEADER, userId)) @@ -637,7 +637,7 @@ void testNodeStashAndRestore() throws Exception { assertEquals("not built node", networkModificationNode.getDescription()); //stash 1 node and do the checks - doNothing().when(rootNetworkNodeInfoService).assertComputationNotRunning(any(), any()); + doNothing().when(rootNetworkNodeInfoService).assertComputationsNotRunning(any(), any()); stashNode(root.getStudyId(), children.get(0), false, Set.of(children.get(0)), userId); var stashedNode = nodeRepository.findById(children.get(0).getId()).orElseThrow(); assertTrue(stashedNode.isStashed()); @@ -1746,7 +1746,7 @@ void testNodeAliases() throws Exception { checkNodeAliasUpdateMessageReceived(root.getStudyId()); // Stashing node3 (with stashChildren=true) should result in aliases no more associated to nodes node3, node4 and node5 - doNothing().when(rootNetworkNodeInfoService).assertComputationNotRunning(any(), any()); + doNothing().when(rootNetworkNodeInfoService).assertComputationsNotRunning(any(), any()); stashNode(root.getStudyId(), node3, true, Set.of(node3, node4, node5), userId); nodeAliases = objectMapper.readValue(mockMvc.perform(get("/v1/studies/{studyUuid}/node-aliases", root.getStudyId())).andExpect(status().isOk()).andReturn() .getResponse() diff --git a/src/test/java/org/gridsuite/study/server/studycontroller/NodeControllerTest.java b/src/test/java/org/gridsuite/study/server/studycontroller/NodeControllerTest.java index b0744d095..806d2c6bd 100644 --- a/src/test/java/org/gridsuite/study/server/studycontroller/NodeControllerTest.java +++ b/src/test/java/org/gridsuite/study/server/studycontroller/NodeControllerTest.java @@ -372,7 +372,7 @@ private void cutAndPasteNode(UUID studyUuid, NetworkModificationNode nodeToCopy, boolean wasBuilt = rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeToCopy.getId(), studyTestUtils.getOneRootNetworkUuid(studyUuid)).get().getNodeBuildStatus().toDto().isBuilt(); UUID deleteModificationIndexStub = wireMockStubs.stubNetworkModificationDeleteIndex(); output.receive(TIMEOUT, studyUpdateDestination); - doNothing().when(rootNetworkNodeInfoService).assertComputationNotRunning(any(), any()); + doNothing().when(rootNetworkNodeInfoService).assertComputationsNotRunning(any(), any()); mockMvc.perform(post(STUDIES_URL + "/{studyUuid}/tree/nodes?nodeToCutUuid={nodeUuid}&referenceNodeUuid={referenceNodeUuid}&insertMode={insertMode}", studyUuid, nodeToCopy.getId(), referenceNodeUuid, insertMode) From b19f1e91205bb5832fbc67a3cbe61edb021f6227 Mon Sep 17 00:00:00 2001 From: sBouzols Date: Tue, 12 May 2026 22:06:02 +0200 Subject: [PATCH 2/2] feat(): generalize get computation statuses service for all types of computation Co-authored-by: Copilot Signed-off-by: sBouzols --- .../server/controller/StudyController.java | 22 ++++++------ ...s.java => ShortCircuitAnalysisStatus.java} | 2 +- .../study/server/service/LoadFlowService.java | 30 +++++----------- .../study/server/service/PccMinService.java | 34 ++++++++++++++----- .../service/RootNetworkNodeInfoService.java | 33 +++++++++--------- .../service/SecurityAnalysisService.java | 31 ++++++++++++----- .../service/SensitivityAnalysisService.java | 33 +++++++++++++----- .../service/StateEstimationService.java | 33 +++++++++++++----- .../server/service/VoltageInitService.java | 31 ++++++++++++++--- .../DynamicMarginCalculationClient.java | 27 ++++++++++----- .../DynamicSecurityAnalysisClient.java | 22 +++++++++--- .../DynamicSimulationClient.java | 3 ++ .../impl/DynamicSimulationClientImpl.java | 24 ++++++++++--- .../DynamicMarginCalculationService.java | 17 +++++++++- .../DynamicSecurityAnalysisService.java | 21 +++++++++++- .../DynamicSimulationService.java | 10 ++++++ .../impl/DynamicSimulationServiceImpl.java | 18 +++++++++- .../shortcircuit/ShortCircuitService.java | 32 +++++++++++------ 18 files changed, 301 insertions(+), 122 deletions(-) rename src/main/java/org/gridsuite/study/server/dto/{ShortCircuitStatus.java => ShortCircuitAnalysisStatus.java} (91%) 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 b165475a7..10ae2db47 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -20,6 +20,8 @@ import org.gridsuite.filter.globalfilter.GlobalFilter; import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.study.server.StudyApi; +import org.gridsuite.study.server.StudyConstants.CompositeModificationsActionType; +import org.gridsuite.study.server.StudyConstants.ModificationsActionType; import org.gridsuite.study.server.dto.*; import org.gridsuite.study.server.dto.computation.LoadFlowComputationInfos; import org.gridsuite.study.server.dto.dynamicmargincalculation.DynamicMarginCalculationStatus; @@ -883,8 +885,8 @@ public ResponseEntity getShortCircuitAnalysisStatus(@Parameter(descripti @PathVariable("rootNetworkUuid") UUID rootNetworkUuid, @Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid, @Parameter(description = "type") @RequestParam(value = "type", required = false, defaultValue = "ALL_BUSES") ShortcircuitAnalysisType type) { - String result = rootNetworkNodeInfoService.getShortCircuitAnalysisStatus(nodeUuid, rootNetworkUuid, type); - return result != null ? ResponseEntity.ok().body(result) : + ShortCircuitAnalysisStatus result = rootNetworkNodeInfoService.getShortCircuitAnalysisStatus(nodeUuid, rootNetworkUuid, type); + return result != null ? ResponseEntity.ok().body(result.name()) : ResponseEntity.noContent().build(); } @@ -976,8 +978,8 @@ public ResponseEntity getVoltageInitResult(@Parameter(description = "stu public ResponseEntity getVoltageInitStatus(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid, @Parameter(description = "rootNetworkUuid") @PathVariable("rootNetworkUuid") UUID rootNetworkUuid, @Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) { - String result = rootNetworkNodeInfoService.getVoltageInitStatus(nodeUuid, rootNetworkUuid); - return result != null ? ResponseEntity.ok().body(result) : + VoltageInitStatus result = rootNetworkNodeInfoService.getVoltageInitStatus(nodeUuid, rootNetworkUuid); + return result != null ? ResponseEntity.ok().body(result.name()) : ResponseEntity.noContent().build(); } @@ -1814,8 +1816,8 @@ public ResponseEntity getSensitivityAnalysisFilterOptions( public ResponseEntity getSensitivityAnalysisStatus(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid, @Parameter(description = "rootNetworkUuid") @PathVariable("rootNetworkUuid") UUID rootNetworkUuid, @Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) { - String result = rootNetworkNodeInfoService.getSensitivityAnalysisStatus(nodeUuid, rootNetworkUuid); - return result != null ? ResponseEntity.ok().body(result) : + SensitivityAnalysisStatus result = rootNetworkNodeInfoService.getSensitivityAnalysisStatus(nodeUuid, rootNetworkUuid); + return result != null ? ResponseEntity.ok().body(result.name()) : ResponseEntity.noContent().build(); } @@ -2403,8 +2405,8 @@ public ResponseEntity getStateEstimationResult(@Parameter(description = public ResponseEntity getStateEstimationStatus(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid, @PathVariable("rootNetworkUuid") UUID rootNetworkUuid, @Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) { - String status = rootNetworkNodeInfoService.getStateEstimationStatus(nodeUuid, rootNetworkUuid); - return status != null ? ResponseEntity.ok().body(status) : ResponseEntity.noContent().build(); + StateEstimationStatus status = rootNetworkNodeInfoService.getStateEstimationStatus(nodeUuid, rootNetworkUuid); + return status != null ? ResponseEntity.ok().body(status.name()) : ResponseEntity.noContent().build(); } @GetMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/pcc-min/status") @@ -2415,8 +2417,8 @@ public ResponseEntity getStateEstimationStatus(@Parameter(description = public ResponseEntity getPccMinStatus(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid, @PathVariable("rootNetworkUuid") UUID rootNetworkUuid, @Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) { - String status = rootNetworkNodeInfoService.getPccMinStatus(nodeUuid, rootNetworkUuid); - return status != null ? ResponseEntity.ok().body(status) : ResponseEntity.noContent().build(); + PccMinStatus status = rootNetworkNodeInfoService.getPccMinStatus(nodeUuid, rootNetworkUuid); + return status != null ? ResponseEntity.ok().body(status.name()) : ResponseEntity.noContent().build(); } @PutMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/state-estimation/stop") diff --git a/src/main/java/org/gridsuite/study/server/dto/ShortCircuitStatus.java b/src/main/java/org/gridsuite/study/server/dto/ShortCircuitAnalysisStatus.java similarity index 91% rename from src/main/java/org/gridsuite/study/server/dto/ShortCircuitStatus.java rename to src/main/java/org/gridsuite/study/server/dto/ShortCircuitAnalysisStatus.java index 524d7a190..7204334fb 100644 --- a/src/main/java/org/gridsuite/study/server/dto/ShortCircuitStatus.java +++ b/src/main/java/org/gridsuite/study/server/dto/ShortCircuitAnalysisStatus.java @@ -9,7 +9,7 @@ /** * @author Etienne Homer */ -public enum ShortCircuitStatus { +public enum ShortCircuitAnalysisStatus { NOT_DONE, RUNNING, COMPLETED diff --git a/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java b/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java index f9631c464..80ab65be7 100644 --- a/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java +++ b/src/main/java/org/gridsuite/study/server/service/LoadFlowService.java @@ -20,6 +20,7 @@ import org.springframework.http.*; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -27,9 +28,11 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -134,19 +137,12 @@ public String getLoadFlowModifications(UUID resultUuid) { } public LoadFlowStatus getLoadFlowStatus(UUID resultUuid) { - if (resultUuid == null) { - return null; - } - - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + LOADFLOW_API_VERSION + "/results/{resultUuid}/status"); - String path = uriComponentsBuilder.buildAndExpand(resultUuid).toUriString(); - - return restTemplate.getForObject(loadFlowServerBaseUri + path, LoadFlowStatus.class); + return getLoadFlowStatuses(List.of(resultUuid)).get(resultUuid); } public Map getLoadFlowStatuses(List resultUuids) { - if (resultUuids == null || resultUuids.isEmpty()) { - return null; + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); } UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + LOADFLOW_API_VERSION + "/results/statuses"); @@ -208,18 +204,10 @@ public void setLoadFlowServerBaseUri(String loadFlowServerBaseUri) { this.loadFlowServerBaseUri = loadFlowServerBaseUri; } - public void assertLoadFlowNotRunning(UUID resultUuid) { - LoadFlowStatus loadFlowStatus = getLoadFlowStatus(resultUuid); - if (LoadFlowStatus.RUNNING.equals(loadFlowStatus)) { - throw new StudyException(COMPUTATION_RUNNING); - } - } - - public void assertLoadFlowsNotRunning(List resultUuids) { + public void assertNoLoadFlowRunning(List resultUuids) { Map loadFlowStatuses = getLoadFlowStatuses(resultUuids); - // this is O(n) complexity, maybe we should adapt endoint to simply check LoadFlowsNotRunning - // for a list of resultUuids returning boolean if encounter one RUNNING computation ? - if (loadFlowStatuses != null && loadFlowStatuses.containsValue(LoadFlowStatus.RUNNING)) { + Set values = new HashSet<>(loadFlowStatuses.values()); + if (values.contains(LoadFlowStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } diff --git a/src/main/java/org/gridsuite/study/server/service/PccMinService.java b/src/main/java/org/gridsuite/study/server/service/PccMinService.java index e9b9d8b09..7260e219c 100644 --- a/src/main/java/org/gridsuite/study/server/service/PccMinService.java +++ b/src/main/java/org/gridsuite/study/server/service/PccMinService.java @@ -18,10 +18,12 @@ import org.gridsuite.study.server.utils.ResultParameters; import org.gridsuite.study.server.utils.StudyUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.domain.Sort; import org.springframework.http.*; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -29,8 +31,11 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import org.springframework.data.domain.Pageable; @@ -118,14 +123,24 @@ public void stopPccMin(UUID studyUuid, UUID nodeUuid, UUID rootNetworkUuid, UUID restTemplate.put(pccMinServerBaseUri + path, Void.class); } - public String getPccMinStatus(UUID resultUuid) { - if (resultUuid == null) { - return null; + public PccMinStatus getPccMinStatus(UUID resultUuid) { + return getPccMinStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getPccMinStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); } String path = UriComponentsBuilder - .fromPath(PCC_MIN_URI + DELIMITER + "results/{resultUuid}/status") - .buildAndExpand(resultUuid).toUriString(); - return restTemplate.getForObject(pccMinServerBaseUri + path, String.class); + .fromPath(PCC_MIN_URI + DELIMITER + "results/statuses") + .toUriString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); + return restTemplate.exchange(path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void deletePccMinResults(List resultsUuids) { @@ -142,9 +157,10 @@ public Integer getPccMinResultsCount() { return restTemplate.getForObject(pccMinServerBaseUri + path, Integer.class); } - public void assertPccMinNotRunning(UUID resultUuid) { - String status = getPccMinStatus(resultUuid); - if (PccMinStatus.RUNNING.name().equals(status)) { + public void assertNoPccMinRunning(List resultUuids) { + Map pccMinStatuses = getPccMinStatuses(resultUuids); + Set values = new HashSet<>(pccMinStatuses.values()); + if (values.contains(PccMinStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } 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 d414ceacb..d8c12cf08 100644 --- a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java +++ b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java @@ -10,6 +10,7 @@ import lombok.NonNull; import org.apache.commons.lang3.StringUtils; import org.gridsuite.study.server.dto.*; +import org.gridsuite.study.server.dto.InvalidateNodeTreeParameters.ComputationsInvalidationMode; import org.gridsuite.study.server.dto.computation.LoadFlowComputationInfos; import org.gridsuite.study.server.dto.dynamicmargincalculation.DynamicMarginCalculationStatus; import org.gridsuite.study.server.dto.dynamicsecurityanalysis.DynamicSecurityAnalysisStatus; @@ -669,18 +670,16 @@ private List getReportUuids(RootNetworkNodeInfo rootNetworkNodeInfo) { } public void assertComputationsNotRunning(List nodeUuids, UUID rootNetworkUuid) { - nodeUuids.forEach(nodeUuid -> { - securityAnalysisService.assertSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SECURITY_ANALYSIS)); - dynamicSimulationService.assertDynamicSimulationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SIMULATION)); - dynamicSecurityAnalysisService.assertDynamicSecurityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SECURITY_ANALYSIS)); - dynamicMarginCalculationService.assertDynamicMarginCalculationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, DYNAMIC_MARGIN_CALCULATION)); - sensitivityAnalysisService.assertSensitivityAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SENSITIVITY_ANALYSIS)); - shortCircuitService.assertShortCircuitAnalysisNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT), getComputationResultUuid(nodeUuid, rootNetworkUuid, SHORT_CIRCUIT_ONE_BUS)); - voltageInitService.assertVoltageInitNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, VOLTAGE_INITIALIZATION)); - stateEstimationService.assertStateEstimationNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, STATE_ESTIMATION)); - pccMinService.assertPccMinNotRunning(getComputationResultUuid(nodeUuid, rootNetworkUuid, PCC_MIN)); - }); - loadFlowService.assertLoadFlowsNotRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, LOAD_FLOW)); + loadFlowService.assertNoLoadFlowRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, LOAD_FLOW)); + securityAnalysisService.assertNoSecurityAnalysisRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, SECURITY_ANALYSIS)); + dynamicSimulationService.assertNoDynamicSimulationRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, DYNAMIC_SIMULATION)); + dynamicSecurityAnalysisService.assertNoDynamicSecurityAnalysisRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, DYNAMIC_SECURITY_ANALYSIS)); + dynamicMarginCalculationService.assertNoDynamicMarginCalculationRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, DYNAMIC_MARGIN_CALCULATION)); + sensitivityAnalysisService.assertNoSensitivityAnalysisRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, SENSITIVITY_ANALYSIS)); + shortCircuitService.assertNoShortCircuitAnalysisRunning(Stream.concat(getComputationResultUuids(nodeUuids, rootNetworkUuid, SHORT_CIRCUIT).stream(), getComputationResultUuids(nodeUuids, rootNetworkUuid, SHORT_CIRCUIT_ONE_BUS).stream()).toList()); + voltageInitService.assertNoVoltageInitRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, VOLTAGE_INITIALIZATION)); + stateEstimationService.assertNoStateEstimationRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, STATE_ESTIMATION)); + pccMinService.assertNoPccMinRunning(getComputationResultUuids(nodeUuids, rootNetworkUuid, PCC_MIN)); } @@ -873,32 +872,32 @@ public DynamicMarginCalculationStatus getDynamicMarginCalculationStatus(UUID nod return dynamicMarginCalculationService.getStatus(resultUuid); } - public String getSensitivityAnalysisStatus(UUID nodeUuid, UUID rootNetworkUuid) { + public SensitivityAnalysisStatus getSensitivityAnalysisStatus(UUID nodeUuid, UUID rootNetworkUuid) { UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, SENSITIVITY_ANALYSIS); return sensitivityAnalysisService.getSensitivityAnalysisStatus(resultUuid); } @Transactional(readOnly = true) - public String getShortCircuitAnalysisStatus(UUID nodeUuid, UUID rootNetworkUuid, ShortcircuitAnalysisType type) { + public ShortCircuitAnalysisStatus getShortCircuitAnalysisStatus(UUID nodeUuid, UUID rootNetworkUuid, ShortcircuitAnalysisType type) { UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, type == ShortcircuitAnalysisType.ALL_BUSES ? SHORT_CIRCUIT : SHORT_CIRCUIT_ONE_BUS); return shortCircuitService.getShortCircuitAnalysisStatus(resultUuid); } @Transactional(readOnly = true) - public String getVoltageInitStatus(UUID nodeUuid, UUID rootNetworkUuid) { + public VoltageInitStatus getVoltageInitStatus(UUID nodeUuid, UUID rootNetworkUuid) { UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, VOLTAGE_INITIALIZATION); return voltageInitService.getVoltageInitStatus(resultUuid); } @Transactional(readOnly = true) - public String getStateEstimationStatus(UUID nodeUuid, UUID rootNetworkUuid) { + public StateEstimationStatus getStateEstimationStatus(UUID nodeUuid, UUID rootNetworkUuid) { UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, STATE_ESTIMATION); return stateEstimationService.getStateEstimationStatus(resultUuid); } @Transactional(readOnly = true) - public String getPccMinStatus(UUID nodeUuid, UUID rootNetworkUuid) { + public PccMinStatus getPccMinStatus(UUID nodeUuid, UUID rootNetworkUuid) { UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, PCC_MIN); return pccMinService.getPccMinStatus(resultUuid); } diff --git a/src/main/java/org/gridsuite/study/server/service/SecurityAnalysisService.java b/src/main/java/org/gridsuite/study/server/service/SecurityAnalysisService.java index 5c9cf64b2..f6aa8ec38 100644 --- a/src/main/java/org/gridsuite/study/server/service/SecurityAnalysisService.java +++ b/src/main/java/org/gridsuite/study/server/service/SecurityAnalysisService.java @@ -20,19 +20,24 @@ import org.gridsuite.study.server.service.common.AbstractComputationService; import org.gridsuite.study.server.service.securityanalysis.SecurityAnalysisResultType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.http.*; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -182,16 +187,23 @@ public void stopSecurityAnalysis(UUID studyUuid, UUID nodeUuid, UUID rootNetwork } public SecurityAnalysisStatus getSecurityAnalysisStatus(UUID resultUuid) { + return getSecurityAnalysisStatuses(List.of(resultUuid)).get(resultUuid); + } - if (resultUuid == null) { - return null; + public Map getSecurityAnalysisStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); } - String path = UriComponentsBuilder - .fromPath(DELIMITER + SECURITY_ANALYSIS_API_VERSION + "/results/{resultUuid}/status") - .buildAndExpand(resultUuid).toUriString(); + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + SECURITY_ANALYSIS_API_VERSION + "/results/statuses"); + String path = uriComponentsBuilder.toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); - return restTemplate.getForObject(securityAnalysisServerBaseUri + path, SecurityAnalysisStatus.class); + return restTemplate.exchange(securityAnalysisServerBaseUri + path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void deleteSecurityAnalysisResults(List resultsUuids) { @@ -218,9 +230,10 @@ public void invalidateSaStatus(List uuids) { } } - public void assertSecurityAnalysisNotRunning(UUID resultUuid) { - SecurityAnalysisStatus sas = getSecurityAnalysisStatus(resultUuid); - if (sas == SecurityAnalysisStatus.RUNNING) { + public void assertNoSecurityAnalysisRunning(List resultUuids) { + Map securityAnalysisStatuses = getSecurityAnalysisStatuses(resultUuids); + Set values = new HashSet<>(securityAnalysisStatuses.values()); + if (values.contains(SecurityAnalysisStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } diff --git a/src/main/java/org/gridsuite/study/server/service/SensitivityAnalysisService.java b/src/main/java/org/gridsuite/study/server/service/SensitivityAnalysisService.java index 495ebf5c0..986b80696 100644 --- a/src/main/java/org/gridsuite/study/server/service/SensitivityAnalysisService.java +++ b/src/main/java/org/gridsuite/study/server/service/SensitivityAnalysisService.java @@ -16,9 +16,11 @@ import org.gridsuite.study.server.dto.sensianalysis.SensitivityAnalysisCsvFileInfos; import org.gridsuite.study.server.repository.StudyEntity; import org.gridsuite.study.server.service.common.AbstractComputationService; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -26,8 +28,11 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -167,15 +172,24 @@ public String getSensitivityResultsFilterOptions(UUID resultUuid, String selecto return restTemplate.getForObject(uri, String.class); } - public String getSensitivityAnalysisStatus(UUID resultUuid) { - if (resultUuid == null) { - return null; + public SensitivityAnalysisStatus getSensitivityAnalysisStatus(UUID resultUuid) { + return getSensitivityAnalysisStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getSensitivityAnalysisStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); } - String path = UriComponentsBuilder.fromPath(DELIMITER + SENSITIVITY_ANALYSIS_API_VERSION + "/results/{resultUuid}/status") - .buildAndExpand(resultUuid).toUriString(); + String path = UriComponentsBuilder.fromPath(DELIMITER + SENSITIVITY_ANALYSIS_API_VERSION + "/results/statuses") + .toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); - return restTemplate.getForObject(sensitivityAnalysisServerBaseUri + path, String.class); + return restTemplate.exchange(path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void stopSensitivityAnalysis(UUID studyUuid, UUID nodeUuid, UUID rootNetworkUuid, UUID resultUuid, String userId) { @@ -228,9 +242,10 @@ public Integer getSensitivityAnalysisResultsCount() { return restTemplate.getForObject(sensitivityAnalysisServerBaseUri + path, Integer.class); } - public void assertSensitivityAnalysisNotRunning(UUID resultUuid) { - String sas = getSensitivityAnalysisStatus(resultUuid); - if (SensitivityAnalysisStatus.RUNNING.name().equals(sas)) { + public void assertNoSensitivityAnalysisRunning(List resultUuids) { + Map sensitivityAnalysisStatuses = getSensitivityAnalysisStatuses(resultUuids); + Set values = new HashSet<>(sensitivityAnalysisStatuses.values()); + if (values.contains(SensitivityAnalysisStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } diff --git a/src/main/java/org/gridsuite/study/server/service/StateEstimationService.java b/src/main/java/org/gridsuite/study/server/service/StateEstimationService.java index 9fe5f5ec8..1e0024587 100644 --- a/src/main/java/org/gridsuite/study/server/service/StateEstimationService.java +++ b/src/main/java/org/gridsuite/study/server/service/StateEstimationService.java @@ -18,20 +18,25 @@ import org.gridsuite.study.server.repository.StudyEntity; import org.gridsuite.study.server.service.common.AbstractComputationService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -122,14 +127,23 @@ public void stopStateEstimation(UUID studyUuid, UUID nodeUuid, UUID rootNetworkU restTemplate.put(stateEstimationServerServerBaseUri + path, Void.class); } - public String getStateEstimationStatus(UUID resultUuid) { - if (resultUuid == null) { - return null; + public StateEstimationStatus getStateEstimationStatus(UUID resultUuid) { + return getStateEstimationStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getStateEstimationStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); } String path = UriComponentsBuilder - .fromPath(DELIMITER + STATE_ESTIMATION_API_VERSION + "/results/{resultUuid}/status") - .buildAndExpand(resultUuid).toUriString(); - return restTemplate.getForObject(stateEstimationServerServerBaseUri + path, String.class); + .fromPath(DELIMITER + STATE_ESTIMATION_API_VERSION + "/results/statuses") + .toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); + return restTemplate.exchange(path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void deleteStateEstimationResults(List resultsUuids) { @@ -146,9 +160,10 @@ public Integer getStateEstimationResultsCount() { return restTemplate.getForObject(stateEstimationServerServerBaseUri + path, Integer.class); } - public void assertStateEstimationNotRunning(UUID resultUuid) { - String status = getStateEstimationStatus(resultUuid); - if (StateEstimationStatus.RUNNING.name().equals(status)) { + public void assertNoStateEstimationRunning(List resultUuids) { + Map stateEstimationStatuses = getStateEstimationStatuses(resultUuids); + Set values = new HashSet<>(stateEstimationStatuses.values()); + if (values.contains(StateEstimationStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } diff --git a/src/main/java/org/gridsuite/study/server/service/VoltageInitService.java b/src/main/java/org/gridsuite/study/server/service/VoltageInitService.java index a2fb4275d..0f40b5d58 100644 --- a/src/main/java/org/gridsuite/study/server/service/VoltageInitService.java +++ b/src/main/java/org/gridsuite/study/server/service/VoltageInitService.java @@ -9,6 +9,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.gridsuite.study.server.RemoteServicesProperties; import org.gridsuite.study.server.dto.voltageinit.ContextInfos; @@ -19,6 +21,7 @@ import org.gridsuite.study.server.dto.VoltageInitStatus; import org.gridsuite.study.server.dto.voltageinit.parameters.VoltageInitParametersInfos; import org.gridsuite.study.server.service.common.AbstractComputationService; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; @@ -28,8 +31,11 @@ import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -121,8 +127,22 @@ public String getVoltageInitResult(UUID resultUuid, UUID networkUuid, String var return getVoltageInitResultOrStatus(resultUuid, "", networkUuid, variantId, globalFilters); } - public String getVoltageInitStatus(UUID resultUuid) { - return getVoltageInitResultOrStatus(resultUuid, "/status", null, null, null); + public VoltageInitStatus getVoltageInitStatus(UUID resultUuid) { + return getVoltageInitStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getVoltageInitStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); + } + String path = UriComponentsBuilder.fromPath(DELIMITER + VOLTAGE_INIT_API_VERSION + "/results/statuses").toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); + + return restTemplate.exchange(path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public VoltageInitParametersInfos getVoltageInitParameters(UUID parametersUuid) { @@ -228,9 +248,10 @@ public Integer getVoltageInitResultsCount() { return restTemplate.getForObject(voltageInitServerBaseUri + path, Integer.class); } - public void assertVoltageInitNotRunning(UUID resultUuid) { - String scs = getVoltageInitStatus(resultUuid); - if (VoltageInitStatus.RUNNING.name().equals(scs)) { + public void assertNoVoltageInitRunning(List resultUuids) { + Map voltageInitStatuses = getVoltageInitStatuses(resultUuids); + Set values = new HashSet<>(voltageInitStatuses.values()); + if (values.contains(VoltageInitStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } } diff --git a/src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java b/src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java index 919a32dbc..6e9a10f5c 100644 --- a/src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java +++ b/src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java @@ -14,6 +14,7 @@ import org.gridsuite.study.server.dto.dynamicmargincalculation.DynamicMarginCalculationStatus; import org.gridsuite.study.server.service.StudyService; import org.gridsuite.study.server.service.client.AbstractRestClient; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -24,6 +25,7 @@ import org.springframework.web.util.UriComponentsBuilder; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -192,19 +194,26 @@ public UUID run(@NonNull String receiver, @NonNull UUID networkUuid, String vari } // --- Related result methods --- // - public DynamicMarginCalculationStatus getStatus(@NonNull UUID resultUuid) { - Objects.requireNonNull(resultUuid); + return getStatuses(List.of(resultUuid)).get(resultUuid); + } - String resultBaseUrl = buildEndPointUrl(getBaseUri(), DYNAMIC_MARGIN_CALCULATION_API_VERSION, DYNAMIC_MARGIN_CALCULATION_END_POINT_RESULT); + public Map getStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); + } - String url = UriComponentsBuilder - .fromUriString(resultBaseUrl + "/{resultUuid}/status") - .buildAndExpand(resultUuid) - .toUriString(); + String endPointUrl = buildEndPointUrl(getBaseUri(), DYNAMIC_MARGIN_CALCULATION_API_VERSION, DYNAMIC_MARGIN_CALCULATION_END_POINT_RESULT); - // call dynamic-margin-calculation REST API - return getRestTemplate().getForObject(url, DynamicMarginCalculationStatus.class); + var uriComponents = UriComponentsBuilder.fromUriString(endPointUrl + "/statuses").buildAndExpand(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); + + return getRestTemplate().exchange(uriComponents.toUriString(), HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void invalidateStatus(@NonNull List resultUuids) { diff --git a/src/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.java b/src/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.java index 925073232..803c267a4 100644 --- a/src/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.java +++ b/src/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.java @@ -14,8 +14,10 @@ import org.gridsuite.study.server.dto.dynamicsecurityanalysis.DynamicSecurityAnalysisStatus; import org.gridsuite.study.server.service.StudyService; import org.gridsuite.study.server.service.client.AbstractRestClient; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; @@ -23,6 +25,7 @@ import org.springframework.web.util.UriComponentsBuilder; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -178,18 +181,27 @@ public UUID run(@NonNull String receiver, @NonNull UUID networkUuid, String vari } // --- Related result methods --- // - public DynamicSecurityAnalysisStatus getStatus(@NonNull UUID resultUuid) { - Objects.requireNonNull(resultUuid); + return getStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); + } String resultBaseUrl = buildEndPointUrl(getBaseUri(), DYNAMIC_SECURITY_ANALYSIS_API_VERSION, DYNAMIC_SECURITY_ANALYSIS_END_POINT_RESULT); - String url = UriComponentsBuilder.fromUriString(resultBaseUrl + "/{resultUuid}/status") - .buildAndExpand(resultUuid) + String url = UriComponentsBuilder.fromUriString(resultBaseUrl + "/statuses") .toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); // call dynamic-security-analysis REST API - return getRestTemplate().getForObject(url, DynamicSecurityAnalysisStatus.class); + return getRestTemplate().exchange(url, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } public void invalidateStatus(@NonNull List resultUuids) { diff --git a/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java b/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java index 41f27ccec..77279c019 100644 --- a/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java +++ b/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java @@ -14,6 +14,7 @@ import org.springframework.lang.NonNull; import java.util.List; +import java.util.Map; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.DYNAMIC_SIMULATION_API_VERSION; @@ -56,6 +57,8 @@ UUID run(String receiver, UUID networkUuid, String variantId, ReportInfos report DynamicSimulationStatus getStatus(UUID resultUuid); + Map getStatuses(List resultUuids); + void invalidateStatus(List resultUuids); void deleteResults(List resultsUuids); diff --git a/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java b/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java index 226cbf985..d144e4bdc 100644 --- a/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java +++ b/src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java @@ -16,8 +16,10 @@ import org.gridsuite.study.server.service.StudyService; import org.gridsuite.study.server.service.client.AbstractRestClient; import org.gridsuite.study.server.service.client.dynamicsimulation.DynamicSimulationClient; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; @@ -25,6 +27,7 @@ import org.springframework.web.util.UriComponentsBuilder; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -203,13 +206,26 @@ public UUID getTimelineResult(UUID resultUuid) { @Override public DynamicSimulationStatus getStatus(UUID resultUuid) { - Objects.requireNonNull(resultUuid); + return getStatuses(List.of(resultUuid)).get(resultUuid); + } + + @Override + public Map getStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); + } + String endPointUrl = buildEndPointUrl(getBaseUri(), DYNAMIC_SIMULATION_API_VERSION, DYNAMIC_SIMULATION_END_POINT_RESULT); - var uriComponents = UriComponentsBuilder.fromUriString(endPointUrl + "/{resultUuid}/status") - .buildAndExpand(resultUuid); + var uriComponents = UriComponentsBuilder.fromUriString(endPointUrl + "/statuses").buildAndExpand(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); - return getRestTemplate().getForObject(uriComponents.toUriString(), DynamicSimulationStatus.class); + return getRestTemplate().exchange(uriComponents.toUriString(), HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { + }).getBody(); } @Override diff --git a/src/main/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationService.java b/src/main/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationService.java index 5595c5740..8398770a6 100644 --- a/src/main/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationService.java +++ b/src/main/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationService.java @@ -21,7 +21,10 @@ import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.error.StudyBusinessErrorCode.COMPUTATION_RUNNING; @@ -83,7 +86,11 @@ public UUID runDynamicMarginCalculation(UUID nodeUuid, UUID rootNetworkUuid, UUI } public DynamicMarginCalculationStatus getStatus(UUID resultUuid) { - return resultUuid == null ? null : dynamicMarginCalculationClient.getStatus(resultUuid); + return getDynamicMarginCalculationStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getDynamicMarginCalculationStatuses(List resultUuids) { + return dynamicMarginCalculationClient.getStatuses(resultUuids); } public void invalidateStatus(List resultUuids) { @@ -122,4 +129,12 @@ public UUID getDynamicMarginCalculationParametersUuidOrElseCreateDefault(StudyEn public String getProvider(UUID parametersUuid) { return dynamicMarginCalculationClient.getProvider(parametersUuid); } + + public void assertNoDynamicMarginCalculationRunning(List resultUuids) { + Map dynamicMarginCalculationStatuses = getDynamicMarginCalculationStatuses(resultUuids); + Set values = new HashSet<>(dynamicMarginCalculationStatuses.values()); + if (values.contains(DynamicMarginCalculationStatus.RUNNING)) { + throw new StudyException(COMPUTATION_RUNNING); + } + } } diff --git a/src/main/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisService.java b/src/main/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisService.java index 56b84d635..dd1cb5382 100644 --- a/src/main/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisService.java +++ b/src/main/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisService.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; + import org.apache.commons.collections4.CollectionUtils; import org.gridsuite.study.server.dto.NodeReceiver; import org.gridsuite.study.server.dto.ReportInfos; @@ -21,7 +22,10 @@ import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.error.StudyBusinessErrorCode.COMPUTATION_RUNNING; @@ -83,7 +87,14 @@ public UUID runDynamicSecurityAnalysis(UUID nodeUuid, UUID rootNetworkUuid, UUID } public DynamicSecurityAnalysisStatus getStatus(UUID resultUuid) { - return resultUuid == null ? null : dynamicSecurityAnalysisClient.getStatus(resultUuid); + return getDynamicSecurityAnalysisStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getDynamicSecurityAnalysisStatuses(List resultUuids) { + if (CollectionUtils.isEmpty(resultUuids)) { + return Map.of(); + } + return dynamicSecurityAnalysisClient.getStatuses(resultUuids); } public void invalidateStatus(List resultUuids) { @@ -122,4 +133,12 @@ public UUID getDynamicSecurityAnalysisParametersUuidOrElseCreateDefault(StudyEnt public String getProvider(UUID parametersUuid) { return dynamicSecurityAnalysisClient.getProvider(parametersUuid); } + + public void assertNoDynamicSecurityAnalysisRunning(List resultUuids) { + Map dynamicSecurityAnalysisStatuses = getDynamicSecurityAnalysisStatuses(resultUuids); + Set values = new HashSet<>(dynamicSecurityAnalysisStatuses.values()); + if (values.contains(DynamicSecurityAnalysisStatus.RUNNING)) { + throw new StudyException(COMPUTATION_RUNNING); + } + } } diff --git a/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.java b/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.java index 3360a4066..8ebacf121 100644 --- a/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.java +++ b/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.java @@ -16,6 +16,7 @@ import org.gridsuite.study.server.repository.StudyEntity; import java.util.List; +import java.util.Map; import java.util.UUID; /** @@ -83,6 +84,13 @@ UUID runDynamicSimulation(UUID nodeUuid, UUID rootNetworkUuid, UUID networkUuid, */ DynamicSimulationStatus getStatus(UUID resultUuid); + /** + * Get the current status of the simulations + * @param resultUuids a given list of result UUIDs + * @return a map of result UUID and its corresponding dynamic simulation status + */ + Map getDynamicSimulationStatuses(List resultUuids); + /** * invalidate status of the simulation results * @param resultUuids a given list of result UUIDs @@ -117,4 +125,6 @@ UUID runDynamicSimulation(UUID nodeUuid, UUID rootNetworkUuid, UUID networkUuid, * @return a list of time-series metadata */ List getTimeSeriesMetadataList(UUID resultUuid); + + void assertNoDynamicSimulationRunning(List computationResultUuids); } diff --git a/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java b/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java index fed8ce764..b7d53ed77 100644 --- a/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java +++ b/src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java @@ -32,7 +32,10 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.stream.Stream; @@ -201,7 +204,12 @@ public List getTimelineResult(UUID resultUuid) { @Override public DynamicSimulationStatus getStatus(UUID resultUuid) { - return resultUuid == null ? null : dynamicSimulationClient.getStatus(resultUuid); + return getDynamicSimulationStatuses(List.of(resultUuid)).get(resultUuid); + } + + @Override + public Map getDynamicSimulationStatuses(List resultUuids) { + return dynamicSimulationClient.getStatuses(resultUuids); } @Override @@ -233,4 +241,12 @@ public void assertDynamicSimulationNotRunning(UUID resultUuid) { throw new StudyException(COMPUTATION_RUNNING); } } + + public void assertNoDynamicSimulationRunning(List computationResultUuids) { + Map loadFlowStatuses = getDynamicSimulationStatuses(computationResultUuids); + Set values = new HashSet<>(loadFlowStatuses.values()); + if (values.contains(DynamicSimulationStatus.RUNNING)) { + throw new StudyException(COMPUTATION_RUNNING); + } + } } diff --git a/src/main/java/org/gridsuite/study/server/service/shortcircuit/ShortCircuitService.java b/src/main/java/org/gridsuite/study/server/service/shortcircuit/ShortCircuitService.java index eed14a8c3..0d43014f2 100644 --- a/src/main/java/org/gridsuite/study/server/service/shortcircuit/ShortCircuitService.java +++ b/src/main/java/org/gridsuite/study/server/service/shortcircuit/ShortCircuitService.java @@ -16,7 +16,7 @@ import org.gridsuite.study.server.error.StudyException; import org.gridsuite.study.server.dto.NodeReceiver; import org.gridsuite.study.server.dto.ReportInfos; -import org.gridsuite.study.server.dto.ShortCircuitStatus; +import org.gridsuite.study.server.dto.ShortCircuitAnalysisStatus; import org.gridsuite.study.server.dto.VariantInfos; import org.gridsuite.study.server.service.StudyService; import org.gridsuite.study.server.service.common.AbstractComputationService; @@ -35,9 +35,11 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.*; @@ -193,15 +195,23 @@ public String getShortCircuitAnalysisResultsPage(ResultParameters resultParamete return getShortCircuitAnalysisResource(builder.build().encode().toUri()); // need to encode because of filter JSON array } - public String getShortCircuitAnalysisStatus(UUID resultUuid) { - String resultPath = getShortCircuitAnalysisResultResourcePath(resultUuid); - if (resultPath == null) { - return null; + public ShortCircuitAnalysisStatus getShortCircuitAnalysisStatus(UUID resultUuid) { + return getShortCircuitAnalysisStatuses(List.of(resultUuid)).get(resultUuid); + } + + public Map getShortCircuitAnalysisStatuses(List resultUuids) { + if (resultUuids.isEmpty()) { + return Map.of(); } + String path = UriComponentsBuilder + .fromPath(DELIMITER + SHORT_CIRCUIT_API_VERSION + "/results/statuses") + .toUriString(); - UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(shortCircuitServerBaseUri + resultPath + "/status"); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> httpEntity = new HttpEntity<>(resultUuids, headers); - return getShortCircuitAnalysisResource(builder.build().toUri()); + return restTemplate.exchange(shortCircuitServerBaseUri + path, HttpMethod.POST, httpEntity, new ParameterizedTypeReference>() { }).getBody(); } public String getShortCircuitAnalysisResource(URI resourcePath) { @@ -248,10 +258,10 @@ public Integer getShortCircuitResultsCount() { return restTemplate.getForObject(shortCircuitServerBaseUri + path, Integer.class); } - public void assertShortCircuitAnalysisNotRunning(UUID scsResultUuid, UUID oneBusScsResultUuid) { - String scs = getShortCircuitAnalysisStatus(scsResultUuid); - String oneBusScs = getShortCircuitAnalysisStatus(oneBusScsResultUuid); - if (ShortCircuitStatus.RUNNING.name().equals(scs) || ShortCircuitStatus.RUNNING.name().equals(oneBusScs)) { + public void assertNoShortCircuitAnalysisRunning(List resultUuids) { + Map shortCircuitStatuses = getShortCircuitAnalysisStatuses(resultUuids); + Set values = new HashSet<>(shortCircuitStatuses.values()); + if (values.contains(ShortCircuitAnalysisStatus.RUNNING)) { throw new StudyException(COMPUTATION_RUNNING); } }