From 96aa117c21c50659aa3cd7fd7bb3354f40705e88 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Mon, 24 Nov 2025 16:10:56 +0100 Subject: [PATCH 01/20] implement computation result filters uuid --- .../ComputationResultFiltersController.java | 54 +++++++++++++++++++ .../study/server/repository/StudyEntity.java | 3 ++ .../server/service/StudyConfigService.java | 32 +++++++++++ .../study/server/service/StudyService.java | 10 ++++ .../changesets/changelog_20251117T095627Z.xml | 8 +++ .../db/changelog/db.changelog-master.yaml | 3 ++ 6 files changed, 110 insertions(+) create mode 100644 src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java create mode 100644 src/main/resources/db/changelog/changesets/changelog_20251117T095627Z.xml diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java new file mode 100644 index 0000000000..5337fb9d9f --- /dev/null +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -0,0 +1,54 @@ +/* + * 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.study.server.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.gridsuite.study.server.StudyApi; +import org.gridsuite.study.server.service.StudyService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.UUID; +/** + * @author Rehili Ghazwa + */ + +@RestController +@RequestMapping(value = "/" + StudyApi.API_VERSION + "/studies/{studyUuid}/computation-result-filters") +@Tag(name = "Study server - Computation result filters") +public class ComputationResultFiltersController { + private final StudyService studyService; + + public ComputationResultFiltersController(StudyService studyService) { + this.studyService = studyService; + } + + @GetMapping() + @Operation(summary = "Get study's computation result filters") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The computation result filters")}) + public ResponseEntity getComputationResultFilters( + @PathVariable("studyUuid") UUID studyUuid) { + return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid)); + } + + @PostMapping("/{id}/global-filters") + @Operation(summary = "Set global filters", + description = "Replaces all existing global filters with the provided list for a computation result") + @ApiResponse(responseCode = "204", description = "Global filters set successfully") + @ApiResponse(responseCode = "404", description = "computation result global filters not found") + public ResponseEntity setGlobalFiltersForComputationResult( + @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "ID of the global filters") @PathVariable UUID id, + @RequestBody String filters) { + studyService.setGlobalFiltersForComputationResult(studyUuid, id, filters); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java b/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java index b16a4bee25..b46a1acf32 100644 --- a/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java +++ b/src/main/java/org/gridsuite/study/server/repository/StudyEntity.java @@ -107,6 +107,9 @@ public class StudyEntity extends AbstractManuallyAssignedIdentifierEntity @Column(name = "spreadsheetConfigCollectionUuid") private UUID spreadsheetConfigCollectionUuid; + @Column(name = "computationResultFiltersUuid") + private UUID computationResultFiltersUuid; + @Column(name = "diagramGridLayoutUuid") private UUID diagramGridLayoutUuid; diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index 4328daaee0..c2a9f747e4 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -45,6 +45,9 @@ public class StudyConfigService { private static final String DIAGRAM_GRID_LAYOUT_URI = "/diagram-grid-layout"; private static final String DIAGRAM_GRID_LAYOUT_WITH_ID_URI = DIAGRAM_GRID_LAYOUT_URI + UUID_PARAM; + private static final String COMPUTATION_RESULT_FILTERS_URI = "/computation-result-filters"; + private static final String COMPUTATION_RESULT_FILTERS_WITH_ID_URI = COMPUTATION_RESULT_FILTERS_URI + UUID_PARAM; + private static final DiagramPosition DEFAULT_DIAGRAM_POSITION = new DiagramPosition(2, 2, 0, 0); private final RestTemplate restTemplate; @@ -360,4 +363,33 @@ public UUID createGridLayoutFromNadDiagram(UUID sourceNadConfigUuid, UUID cloned HttpEntity httpEntity = new HttpEntity<>(diagramGridLayout, headers); return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, UUID.class).getBody(); } + + public UUID createDefaultComputationResultFilters() { + var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/default") + .buildAndExpand().toUriString(); + return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); + } + + public UUID getComputationResultFiltersUuidOrElseCreateDefaults(StudyEntity studyEntity) { + if (studyEntity.getComputationResultFiltersUuid() == null) { + studyEntity.setComputationResultFiltersUuid(createDefaultComputationResultFilters()); + } + return studyEntity.getComputationResultFiltersUuid(); + } + + public String getComputationResultFilters(UUID uuid) { + Objects.requireNonNull(uuid); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI) + .buildAndExpand(uuid).toUriString(); + return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); + } + + public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid, String globalFilters) { + var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/global-filters"); + String path = uriBuilder.buildAndExpand(configUuid).toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); + restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); + } } 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 571083c948..79e09d93a9 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2672,6 +2672,12 @@ public String getSpreadsheetConfigCollection(UUID studyUuid) { return studyConfigService.getSpreadsheetConfigCollection(studyConfigService.getSpreadsheetConfigCollectionUuidOrElseCreateDefaults(studyEntity)); } + @Transactional + public String getComputationResultFilters(UUID studyUuid) { + StudyEntity studyEntity = getStudy(studyUuid); + return studyConfigService.getComputationResultFilters(studyConfigService.getComputationResultFiltersUuidOrElseCreateDefaults(studyEntity)); + } + /** * Set spreadsheet config collection on study or reset to default one if empty body. * Default is the user profile one, or system default if no profile is available. @@ -3509,6 +3515,10 @@ public void setGlobalFilters(UUID studyUuid, UUID configUuid, String globalFilte notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); } + public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid, String globalFilters) { + studyConfigService.setGlobalFiltersForComputationResult(studyUuid, configUuid, globalFilters); + } + public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { studyConfigService.renameSpreadsheetConfig(configUuid, newName); notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); diff --git a/src/main/resources/db/changelog/changesets/changelog_20251117T095627Z.xml b/src/main/resources/db/changelog/changesets/changelog_20251117T095627Z.xml new file mode 100644 index 0000000000..388f7f03c8 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20251117T095627Z.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 6ae6d30648..c02bcdcd47 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -353,3 +353,6 @@ databaseChangeLog: - include: file: changesets/changelog_20251110T113159Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20251117T095627Z.xml + relativeToChangelogFile: true From da16f3884a47fa12c9e4e717ac70aac784c08961 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Sat, 29 Nov 2025 20:44:41 +0100 Subject: [PATCH 02/20] clean code --- .../ComputationResultFiltersController.java | 13 +++++++++++++ .../study/server/service/StudyConfigService.java | 9 +++++++++ .../study/server/service/StudyService.java | 4 ++++ 3 files changed, 26 insertions(+) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 5337fb9d9f..8350765d89 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import org.gridsuite.study.server.StudyApi; import org.gridsuite.study.server.service.StudyService; import org.springframework.http.ResponseEntity; @@ -51,4 +52,16 @@ public ResponseEntity setGlobalFiltersForComputationResult( studyService.setGlobalFiltersForComputationResult(studyUuid, id, filters); return ResponseEntity.noContent().build(); } + + @PutMapping("/{id}/columns/{columnUuid}") + @Operation(summary = "Update a column", description = "Updates an existing column") + @ApiResponse(responseCode = "204", description = "Column updated") + public ResponseEntity updateColumns( + @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id, + @Parameter(description = "ID of the column to update") @PathVariable UUID columnUuid, + @Valid @RequestBody String columnInfos) { + studyService.updateColumns(studyUuid, id, columnUuid, columnInfos); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index c2a9f747e4..63cf8a625b 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -392,4 +392,13 @@ public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } + + public void updateColumns(UUID configUuid, UUID columnUuid, String columnInfos) { + var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/columns/{colId}"); + String path = uriBuilder.buildAndExpand(configUuid, columnUuid).toUriString(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); + restTemplate.put(studyConfigServerBaseUri + path, httpEntity); + } } 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 79e09d93a9..a885ce3cd6 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -3519,6 +3519,10 @@ public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid studyConfigService.setGlobalFiltersForComputationResult(studyUuid, configUuid, globalFilters); } + public void updateColumns(UUID studyUuid, UUID configUuid, UUID columnUuid, String columnInfos) { + studyConfigService.updateColumns(configUuid, columnUuid, columnInfos); + } + public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { studyConfigService.renameSpreadsheetConfig(configUuid, newName); notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); From fb3ecee7eea7412dd38e9a510a3485fe75128f4b Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 14 Jan 2026 13:48:21 +0100 Subject: [PATCH 03/20] add TU --- .../server/ComputationResultFiltersTest.java | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java new file mode 100644 index 0000000000..32997d0248 --- /dev/null +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -0,0 +1,126 @@ +/** + * 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.study.server; + +import mockwebserver3.Dispatcher; +import mockwebserver3.MockResponse; +import mockwebserver3.MockWebServer; +import mockwebserver3.RecordedRequest; +import mockwebserver3.junit5.internal.MockWebServerExtension; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import org.gridsuite.study.server.repository.StudyEntity; +import org.gridsuite.study.server.repository.StudyRepository; +import org.gridsuite.study.server.repository.rootnetwork.RootNetworkEntity; +import org.gridsuite.study.server.service.StudyConfigService; +import org.gridsuite.study.server.utils.TestUtils; +import org.gridsuite.study.server.utils.elasticsearch.DisableElasticsearch; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.Objects; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Rehili Ghazwa + */ +@ExtendWith(MockWebServerExtension.class) +@AutoConfigureMockMvc +@SpringBootTest +@DisableElasticsearch +@ContextConfigurationWithTestChannel +class ComputationResultFiltersTest { + private static final String COMPUTATION_FILTERS_JSON = "{\"computationResultFilters\":[]}"; + private static final UUID COMPUTATION_FILTERS_UUID = UUID.randomUUID(); + private static final UUID COMPUTATION_GLOBAL_FILTERS_UUID = UUID.randomUUID(); + private static final UUID COLUMN_UUID = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"); + + @Autowired + private MockMvc mockMvc; + @Autowired + private StudyConfigService studyConfigService; + @Autowired + private StudyRepository studyRepository; + + @BeforeEach + void setup(final MockWebServer server) { + HttpUrl baseHttpUrl = server.url(""); + String baseUrl = baseHttpUrl.toString().substring(0, baseHttpUrl.toString().length() - 1); + studyConfigService.setStudyConfigServerBaseUri(baseUrl); + + final Dispatcher dispatcher = new Dispatcher() { + @Override + @NotNull + public MockResponse dispatch(RecordedRequest request) { + String path = Objects.requireNonNull(request.getPath()); + String method = request.getMethod(); + if ("GET".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID)) { + return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); + } + if ("POST".equals(method) && path.equals("/v1/computation-result-filters/default")) { + return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), "\"" + COMPUTATION_FILTERS_UUID + "\""); + } + if ("POST".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_GLOBAL_FILTERS_UUID + "/global-filters")) { + return new MockResponse(204, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); + } + if ("PUT".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/columns/" + COLUMN_UUID)) { + return new MockResponse(204, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); + } + return new MockResponse.Builder().code(418).body("Unhandled method+path: " + request.getMethod() + " " + request.getPath()).build(); + } + }; + server.setDispatcher(dispatcher); + } + + @Test + void getComputationResultFilters(final MockWebServer server) throws Exception { + StudyEntity study = insertDummyStudy(null); + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); + JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); + var requests = TestUtils.getRequestsDone(2, server); + assertTrue(requests.stream().anyMatch(r -> r.equals("/v1/computation-result-filters/default"))); + assertTrue(requests.stream().anyMatch(r -> r.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + + study = insertDummyStudy(COMPUTATION_FILTERS_UUID); + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); + JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); + requests = TestUtils.getRequestsDone(1, server); + assertTrue(requests.stream().allMatch(r -> r.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + } + + @Test + void setGlobalFilters() throws Exception { + StudyEntity study = insertDummyStudy(COMPUTATION_GLOBAL_FILTERS_UUID); + String json = "{\"globalFilters\":[]}"; + mockMvc.perform(post("/v1/studies/{studyUuid}/computation-result-filters/{id}/global-filters", study.getId(), COMPUTATION_GLOBAL_FILTERS_UUID) + .contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + } + + private StudyEntity insertDummyStudy(UUID computationResultFiltersUuid) { + StudyEntity studyEntity = StudyEntity.builder().id(UUID.randomUUID()).computationResultFiltersUuid(computationResultFiltersUuid).build(); + RootNetworkEntity rootNetworkEntity = RootNetworkEntity.builder().id(UUID.randomUUID()).name("rootNetworkName") + .tag("dum").caseFormat("").caseUuid(UUID.randomUUID()).caseName("").networkId(String.valueOf(UUID.randomUUID())).networkUuid(UUID.randomUUID()).build(); + studyEntity.addRootNetwork(rootNetworkEntity); + return studyRepository.save(studyEntity); + } +} From 1cc78e2b40aaf02715b2e07fe4236e13d96c5f1e Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 15 Jan 2026 15:14:42 +0100 Subject: [PATCH 04/20] add TU --- .../study/server/ComputationResultFiltersTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 32997d0248..0431d23c18 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -37,6 +37,7 @@ import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -53,7 +54,7 @@ class ComputationResultFiltersTest { private static final String COMPUTATION_FILTERS_JSON = "{\"computationResultFilters\":[]}"; private static final UUID COMPUTATION_FILTERS_UUID = UUID.randomUUID(); private static final UUID COMPUTATION_GLOBAL_FILTERS_UUID = UUID.randomUUID(); - private static final UUID COLUMN_UUID = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"); + private static final UUID COLUMN_UUID = UUID.randomUUID(); @Autowired private MockMvc mockMvc; @@ -116,6 +117,14 @@ void setGlobalFilters() throws Exception { .contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); } + @Test + void updateColumn() throws Exception { + StudyEntity study = insertDummyStudy(COLUMN_UUID); + String json = "{\"columnsFilters\":[]}"; + mockMvc.perform(put("/v1/studies/{studyUuid}/computation-result-filters/{id}/columns/{columnUuid}", study.getId(), + COMPUTATION_FILTERS_UUID, COLUMN_UUID).contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + } + private StudyEntity insertDummyStudy(UUID computationResultFiltersUuid) { StudyEntity studyEntity = StudyEntity.builder().id(UUID.randomUUID()).computationResultFiltersUuid(computationResultFiltersUuid).build(); RootNetworkEntity rootNetworkEntity = RootNetworkEntity.builder().id(UUID.randomUUID()).name("rootNetworkName") From 87532f15fc9cb40aa9d3e42972789aa52b658108 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 16 Jan 2026 13:00:26 +0100 Subject: [PATCH 05/20] code review remarks --- .../study/server/service/ConsumerService.java | 12 +++++++++++- .../gridsuite/study/server/service/StudyService.java | 8 +++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java index 4ece406120..9f813e3984 100644 --- a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java +++ b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java @@ -295,12 +295,13 @@ private void insertStudy(UUID studyUuid, String userId, NetworkInfos networkInfo UUID pccMinParametersUuid = createDefaultPccMinParameters(); UUID spreadsheetConfigCollectionUuid = createDefaultSpreadsheetConfigCollection(userId, userProfileInfos); UUID diagramGridLayoutUuid = studyService.createGridLayoutFromNadDiagram(userId, userProfileInfos); + UUID computationResultFiltersUuid = createDefaultComputationResultFilters(); studyService.insertStudy(studyUuid, userId, networkInfos, caseInfos, loadFlowParametersUuid, shortCircuitParametersUuid, DynamicSimulationService.toEntity(dynamicSimulationParameters, objectMapper), voltageInitParametersUuid, securityAnalysisParametersUuid, sensitivityAnalysisParametersUuid, networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, - importParameters, importReportUuid); + importParameters, importReportUuid, computationResultFiltersUuid); } private UUID createDefaultLoadFlowParameters(String userId, UserProfileInfos userProfileInfos) { @@ -461,6 +462,15 @@ private UUID createDefaultPccMinParameters() { } } + private UUID createDefaultComputationResultFilters() { + try { + return studyConfigService.createDefaultComputationResultFilters(); + } catch (final Exception e) { + LOGGER.error("Error while creating pcc min default parameters", e); + return null; + } + } + private UUID createDefaultSpreadsheetConfigCollection(String userId, UserProfileInfos userProfileInfos) { if (userProfileInfos != null && userProfileInfos.getSpreadsheetConfigCollectionId() != null) { // try to access/duplicate the user profile spreadsheet config collection 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 2654c68fd3..b0a182a926 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -617,7 +617,7 @@ public CreatedStudyBasicInfos insertStudy(UUID studyUuid, String userId, Network UUID shortCircuitParametersUuid, DynamicSimulationParametersEntity dynamicSimulationParametersEntity, UUID voltageInitParametersUuid, UUID securityAnalysisParametersUuid, UUID sensitivityAnalysisParametersUuid, UUID networkVisualizationParametersUuid, UUID dynamicSecurityAnalysisParametersUuid, UUID stateEstimationParametersUuid, UUID pccMinParametersUuid, - UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid) { + UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid, UUID computationResultFiltersUuid) { Objects.requireNonNull(studyUuid); Objects.requireNonNull(userId); Objects.requireNonNull(networkInfos.getNetworkUuid()); @@ -631,7 +631,8 @@ public CreatedStudyBasicInfos insertStudy(UUID studyUuid, String userId, Network shortCircuitParametersUuid, dynamicSimulationParametersEntity, voltageInitParametersUuid, securityAnalysisParametersUuid, sensitivityAnalysisParametersUuid, networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, - stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, importParameters, importReportUuid); + stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, + importParameters, importReportUuid, computationResultFiltersUuid); // Need to deal with the study creation (with a default root network ?) CreatedStudyBasicInfos createdStudyBasicInfos = toCreatedStudyBasicInfos(studyEntity); @@ -1615,7 +1616,7 @@ private StudyEntity saveStudyThenCreateBasicTree(UUID studyUuid, NetworkInfos ne UUID shortCircuitParametersUuid, DynamicSimulationParametersEntity dynamicSimulationParametersEntity, UUID voltageInitParametersUuid, UUID securityAnalysisParametersUuid, UUID sensitivityAnalysisParametersUuid, UUID networkVisualizationParametersUuid, UUID dynamicSecurityAnalysisParametersUuid, UUID stateEstimationParametersUuid, UUID pccMinParametersUuid, - UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid) { + UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid, UUID computationResultFilterUuid) { StudyEntity studyEntity = StudyEntity.builder() .id(studyUuid) @@ -1633,6 +1634,7 @@ private StudyEntity saveStudyThenCreateBasicTree(UUID studyUuid, NetworkInfos ne .pccMinParametersUuid(pccMinParametersUuid) .spreadsheetConfigCollectionUuid(spreadsheetConfigCollectionUuid) .diagramGridLayoutUuid(diagramGridLayoutUuid) + .computationResultFiltersUuid(computationResultFilterUuid) .monoRoot(true) .build(); From d119f175cf4e975cee69ff3f778207305668d147 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 16 Jan 2026 13:25:20 +0100 Subject: [PATCH 06/20] use WireMock for TU --- .../server/ComputationResultFiltersTest.java | 81 ++++++++----------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 0431d23c18..09cbf128ca 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -6,23 +6,16 @@ */ package org.gridsuite.study.server; -import mockwebserver3.Dispatcher; -import mockwebserver3.MockResponse; -import mockwebserver3.MockWebServer; -import mockwebserver3.RecordedRequest; -import mockwebserver3.junit5.internal.MockWebServerExtension; -import okhttp3.Headers; -import okhttp3.HttpUrl; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; import org.gridsuite.study.server.repository.StudyEntity; import org.gridsuite.study.server.repository.StudyRepository; import org.gridsuite.study.server.repository.rootnetwork.RootNetworkEntity; import org.gridsuite.study.server.service.StudyConfigService; -import org.gridsuite.study.server.utils.TestUtils; import org.gridsuite.study.server.utils.elasticsearch.DisableElasticsearch; -import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.beans.factory.annotation.Autowired; @@ -33,19 +26,19 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; -import java.util.Objects; import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * @author Rehili Ghazwa */ -@ExtendWith(MockWebServerExtension.class) @AutoConfigureMockMvc @SpringBootTest @DisableElasticsearch @@ -55,7 +48,7 @@ class ComputationResultFiltersTest { private static final UUID COMPUTATION_FILTERS_UUID = UUID.randomUUID(); private static final UUID COMPUTATION_GLOBAL_FILTERS_UUID = UUID.randomUUID(); private static final UUID COLUMN_UUID = UUID.randomUUID(); - + private WireMockServer wireMockServer; @Autowired private MockMvc mockMvc; @Autowired @@ -64,49 +57,34 @@ class ComputationResultFiltersTest { private StudyRepository studyRepository; @BeforeEach - void setup(final MockWebServer server) { - HttpUrl baseHttpUrl = server.url(""); - String baseUrl = baseHttpUrl.toString().substring(0, baseHttpUrl.toString().length() - 1); - studyConfigService.setStudyConfigServerBaseUri(baseUrl); - - final Dispatcher dispatcher = new Dispatcher() { - @Override - @NotNull - public MockResponse dispatch(RecordedRequest request) { - String path = Objects.requireNonNull(request.getPath()); - String method = request.getMethod(); - if ("GET".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID)) { - return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); - } - if ("POST".equals(method) && path.equals("/v1/computation-result-filters/default")) { - return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), "\"" + COMPUTATION_FILTERS_UUID + "\""); - } - if ("POST".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_GLOBAL_FILTERS_UUID + "/global-filters")) { - return new MockResponse(204, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); - } - if ("PUT".equals(method) && path.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/columns/" + COLUMN_UUID)) { - return new MockResponse(204, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_FILTERS_JSON); - } - return new MockResponse.Builder().code(418).body("Unhandled method+path: " + request.getMethod() + " " + request.getPath()).build(); - } - }; - server.setDispatcher(dispatcher); + void setup() { + wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); + wireMockServer.start(); + studyConfigService.setStudyConfigServerBaseUri(wireMockServer.baseUrl()); + wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID)) + .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); + wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/default")) + .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody("\"" + COMPUTATION_FILTERS_UUID + "\""))); + wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_GLOBAL_FILTERS_UUID + "/global-filters")) + .willReturn(aResponse().withStatus(204))); + wireMockServer.stubFor(WireMock.put(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/columns/" + COLUMN_UUID)) + .willReturn(aResponse().withStatus(204))); } @Test - void getComputationResultFilters(final MockWebServer server) throws Exception { + void getComputationResultFilters() throws Exception { StudyEntity study = insertDummyStudy(null); MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - var requests = TestUtils.getRequestsDone(2, server); - assertTrue(requests.stream().anyMatch(r -> r.equals("/v1/computation-result-filters/default"))); - assertTrue(requests.stream().anyMatch(r -> r.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + wireMockServer.resetRequests(); study = insertDummyStudy(COMPUTATION_FILTERS_UUID); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - requests = TestUtils.getRequestsDone(1, server); - assertTrue(requests.stream().allMatch(r -> r.equals("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); } @Test @@ -132,4 +110,11 @@ private StudyEntity insertDummyStudy(UUID computationResultFiltersUuid) { studyEntity.addRootNetwork(rootNetworkEntity); return studyRepository.save(studyEntity); } + + @AfterEach + void tearDown() { + if (wireMockServer != null) { + wireMockServer.stop(); + } + } } From df1bdc5eb449a3f5a1b17e9d89c8048102b36f7a Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 16 Jan 2026 13:35:09 +0100 Subject: [PATCH 07/20] unused import --- .../org/gridsuite/study/server/ComputationResultFiltersTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 09cbf128ca..eb3b1287ae 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -30,7 +30,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; From f7fd1be71fc5b0cc44c3c6ff46b054bc8fa80175 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 16 Jan 2026 15:08:57 +0100 Subject: [PATCH 08/20] fix TU --- .../server/studycontroller/StudyTest.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java b/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java index 65bf94cc57..8d5fc33d62 100644 --- a/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java +++ b/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java @@ -261,6 +261,7 @@ class StudyTest { private static final String SPREADSHEET_CONFIG_COLLECTION_UUID_STRING = "f4ce25e1-59a7-401d-abb1-04425fe24587"; private static final String DUPLICATED_SPREADSHEET_CONFIG_COLLECTION_UUID_JSON = "\"" + SPREADSHEET_CONFIG_COLLECTION_UUID_STRING + "\""; + private static final String COMPUTATION_RESULT_FILTERS_UUID_STRING = "f4ce25e1-59a7-401d-abb1-04425fe24597"; private static final String DEFAULT_PROVIDER = "defaultProvider"; @@ -621,6 +622,8 @@ public MockResponse dispatch(RecordedRequest request) { return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), mapper.writeValueAsString(UUID.randomUUID())); } else if (path.contains("/v1/download-file/")) { return new MockResponse.Builder().code(200).build(); + } else if (path.matches("/v1/computation-result-filters/default") && !POST.equals(request.getMethod())) { + return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTATION_RESULT_FILTERS_UUID_STRING); } switch (path) { @@ -1253,7 +1256,7 @@ private UUID createStudy(final MockWebServer server, String userId, UUID caseUui assertStudyCreation(studyUuid, userId); // assert that all http requests have been sent to remote services - int nbRequest = 14; + int nbRequest = 15; if (parameterDuplicatedUuid != null && !parameterDuplicationSuccess) { nbRequest += 7; } @@ -1293,7 +1296,7 @@ protected UUID createStudyWithImportParameters(final MockWebServer server, Strin assertStudyCreation(studyUuid, userId); // assert that all http requests have been sent to remote services - Set requests = TestUtils.getRequestsWithBodyDone(14, server); + Set requests = TestUtils.getRequestsWithBodyDone(15, server); assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/cases/%s/exists".formatted(caseUuid)))); assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/networks\\?caseUuid=" + caseUuid + "&variantId=" + FIRST_VARIANT_ID + "&reportUuid=.*"))); assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/cases/%s/disableExpiration".formatted(caseUuid)))); @@ -1323,7 +1326,7 @@ private UUID createStudyWithDuplicateCase(final MockWebServer server, String use assertStudyCreation(studyUuid, userId); // assert that all http requests have been sent to remote services - var requests = TestUtils.getRequestsDone(15, server); + var requests = TestUtils.getRequestsDone(16, server); assertTrue(requests.contains("/v1/cases/%s/exists".formatted(caseUuid))); assertTrue(requests.contains("/v1/cases?duplicateFrom=%s&withExpiration=%s".formatted(caseUuid, true))); // note : it's a new case UUID @@ -1543,7 +1546,7 @@ void testGetStudyCreationRequests(final MockWebServer server) throws Exception { csbiListResponse = mapper.readValue(resultAsString, new TypeReference<>() { }); // assert that all http requests have been sent to remote services - var requests = TestUtils.getRequestsDone(14, server); + var requests = TestUtils.getRequestsDone(15, server); assertTrue(requests.contains("/v1/cases/%s/exists".formatted(NEW_STUDY_CASE_UUID))); assertTrue(requests.stream().anyMatch(r -> r.matches("/v1/networks\\?caseUuid=" + NEW_STUDY_CASE_UUID + "&variantId=" + FIRST_VARIANT_ID + "&reportUuid=.*"))); assertTrue(requests.contains("/v1/cases/%s/disableExpiration".formatted(NEW_STUDY_CASE_UUID))); @@ -1698,6 +1701,11 @@ void testCreateStudyWithDefaultVoltageInitUserHasValidParamsInProfile(final Mock createStudy(mockWebServer, VALID_PARAMS_IN_PROFILE_USER_ID, CASE_UUID, PROFILE_VOLTAGE_INIT_VALID_PARAMETERS_UUID_STRING, true); } + @Test + void testCreateStudyWithDefaultComputationResultFilters(final MockWebServer mockWebServer) throws Exception { + createStudy(mockWebServer, VALID_PARAMS_IN_PROFILE_USER_ID, CASE_UUID, PROFILE_VOLTAGE_INIT_VALID_PARAMETERS_UUID_STRING, true); + } + private void testDuplicateStudy(final MockWebServer mockWebServer, UUID study1Uuid, UUID rootNetworkUuid, String userId) throws Exception { RootNode rootNode = networkModificationTreeService.getStudyTree(study1Uuid, null); UUID modificationNodeUuid = rootNode.getChildren().get(0).getId(); @@ -1819,6 +1827,7 @@ void testDuplicateStudyWithGridLayout(final MockWebServer mockWebServer) throws studyEntity.setPccMinParametersUuid(UUID.randomUUID()); studyEntity.setNetworkVisualizationParametersUuid(UUID.randomUUID()); studyEntity.setSpreadsheetConfigCollectionUuid(UUID.randomUUID()); + studyEntity.setComputationResultFiltersUuid(UUID.randomUUID()); studyRepository.save(studyEntity); testDuplicateStudy(mockWebServer, study1Uuid, firstRootNetworkUuid, NAD_CONFIG_USER_ID); } @@ -1836,6 +1845,7 @@ void testDuplicateStudyWithoutParametersUuid(final MockWebServer mockWebServer) studyEntity.setPccMinParametersUuid(null); studyEntity.setNetworkVisualizationParametersUuid(null); studyEntity.setSpreadsheetConfigCollectionUuid(null); + studyEntity.setComputationResultFiltersUuid(UUID.randomUUID()); studyRepository.save(studyEntity); testDuplicateStudy(mockWebServer, study1Uuid, firstRootNetworkUuid, "userId"); } From 73d3e41fa36671ca5cdd3193bf84d2e3eebf4af8 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 21 Jan 2026 14:16:09 +0100 Subject: [PATCH 09/20] fix to send computationType and computationSubType --- .../ComputationResultFiltersController.java | 20 ++++++++++--------- .../study/server/service/ConsumerService.java | 2 +- .../server/service/StudyConfigService.java | 18 ++++++++--------- .../study/server/service/StudyService.java | 10 +++++----- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 8350765d89..4dc7f588d3 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -7,12 +7,12 @@ package org.gridsuite.study.server.controller; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.gridsuite.study.server.StudyApi; +import org.gridsuite.study.server.dto.ComputationType; import org.gridsuite.study.server.service.StudyService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -40,28 +40,30 @@ public ResponseEntity getComputationResultFilters( return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid)); } - @PostMapping("/{id}/global-filters") + @PostMapping("/{id}/{computationType}/global-filters") @Operation(summary = "Set global filters", description = "Replaces all existing global filters with the provided list for a computation result") @ApiResponse(responseCode = "204", description = "Global filters set successfully") @ApiResponse(responseCode = "404", description = "computation result global filters not found") public ResponseEntity setGlobalFiltersForComputationResult( @PathVariable("studyUuid") UUID studyUuid, - @Parameter(description = "ID of the global filters") @PathVariable UUID id, - @RequestBody String filters) { - studyService.setGlobalFiltersForComputationResult(studyUuid, id, filters); + @PathVariable UUID id, + @PathVariable ComputationType computationType, + @RequestBody String globalFilters) { + studyService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); return ResponseEntity.noContent().build(); } - @PutMapping("/{id}/columns/{columnUuid}") + @PutMapping("/{id}/{computationType}/{computationSubType}/columns") @Operation(summary = "Update a column", description = "Updates an existing column") @ApiResponse(responseCode = "204", description = "Column updated") public ResponseEntity updateColumns( @PathVariable("studyUuid") UUID studyUuid, - @Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id, - @Parameter(description = "ID of the column to update") @PathVariable UUID columnUuid, + @PathVariable UUID id, + @PathVariable ComputationType computationType, + @PathVariable String computationSubType, @Valid @RequestBody String columnInfos) { - studyService.updateColumns(studyUuid, id, columnUuid, columnInfos); + studyService.updateColumns(id, computationType, computationSubType, columnInfos); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java index 9f813e3984..5741aecace 100644 --- a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java +++ b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java @@ -464,7 +464,7 @@ private UUID createDefaultPccMinParameters() { private UUID createDefaultComputationResultFilters() { try { - return studyConfigService.createDefaultComputationResultFilters(); + return studyConfigService.createComputationResultFilters(); } catch (final Exception e) { LOGGER.error("Error while creating pcc min default parameters", e); return null; diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index c4af95685b..c5f213dd18 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -8,6 +8,7 @@ import lombok.Setter; import org.gridsuite.study.server.RemoteServicesProperties; +import org.gridsuite.study.server.dto.ComputationType; import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout; import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.DiagramPosition; import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayout; @@ -373,38 +374,37 @@ public UUID createGridLayoutFromNadDiagram(UUID sourceNadConfigUuid, UUID cloned return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, UUID.class).getBody(); } - public UUID createDefaultComputationResultFilters() { + public UUID createComputationResultFilters() { var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/default") .buildAndExpand().toUriString(); return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); } - public UUID getComputationResultFiltersUuidOrElseCreateDefaults(StudyEntity studyEntity) { + public UUID getOrElseCreateComputationResultFiltersUuid(StudyEntity studyEntity) { if (studyEntity.getComputationResultFiltersUuid() == null) { - studyEntity.setComputationResultFiltersUuid(createDefaultComputationResultFilters()); + studyEntity.setComputationResultFiltersUuid(createComputationResultFilters()); } return studyEntity.getComputationResultFiltersUuid(); } public String getComputationResultFilters(UUID uuid) { Objects.requireNonNull(uuid); - String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI) - .buildAndExpand(uuid).toUriString(); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI).buildAndExpand(uuid).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } - public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid, String globalFilters) { + public void setGlobalFiltersForComputationResult(UUID id, ComputationType computationType, String globalFilters) { var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/global-filters"); - String path = uriBuilder.buildAndExpand(configUuid).toUriString(); + String path = uriBuilder.buildAndExpand(id, computationType).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } - public void updateColumns(UUID configUuid, UUID columnUuid, String columnInfos) { + public void updateColumns(UUID id, ComputationType computationType, String computationSubType, String columnInfos) { var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/columns/{colId}"); - String path = uriBuilder.buildAndExpand(configUuid, columnUuid).toUriString(); + String path = uriBuilder.buildAndExpand(id, computationType, computationSubType).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); 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 b0a182a926..ce16f9822f 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2782,7 +2782,7 @@ public String getSpreadsheetConfigCollection(UUID studyUuid) { @Transactional public String getComputationResultFilters(UUID studyUuid) { StudyEntity studyEntity = getStudy(studyUuid); - return studyConfigService.getComputationResultFilters(studyConfigService.getComputationResultFiltersUuidOrElseCreateDefaults(studyEntity)); + return studyConfigService.getComputationResultFilters(studyConfigService.getOrElseCreateComputationResultFiltersUuid(studyEntity)); } /** @@ -3625,12 +3625,12 @@ public void setGlobalFilters(UUID studyUuid, UUID configUuid, String globalFilte notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); } - public void setGlobalFiltersForComputationResult(UUID studyUuid, UUID configUuid, String globalFilters) { - studyConfigService.setGlobalFiltersForComputationResult(studyUuid, configUuid, globalFilters); + public void setGlobalFiltersForComputationResult(UUID id, ComputationType computationType, String globalFilters) { + studyConfigService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); } - public void updateColumns(UUID studyUuid, UUID configUuid, UUID columnUuid, String columnInfos) { - studyConfigService.updateColumns(configUuid, columnUuid, columnInfos); + public void updateColumns(UUID id, ComputationType computationType, String computationSubType, String columnInfos) { + studyConfigService.updateColumns(id, computationType, computationSubType, columnInfos); } public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { From 79d4156c187bd2288023ab592aaab093751a9dd4 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 21 Jan 2026 16:41:09 +0100 Subject: [PATCH 10/20] use only computationSubType --- .../controller/ComputationResultFiltersController.java | 5 ++--- .../gridsuite/study/server/service/StudyConfigService.java | 6 +++--- .../org/gridsuite/study/server/service/StudyService.java | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 4dc7f588d3..0454f3fd89 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -54,16 +54,15 @@ public ResponseEntity setGlobalFiltersForComputationResult( return ResponseEntity.noContent().build(); } - @PutMapping("/{id}/{computationType}/{computationSubType}/columns") + @PutMapping("/{id}/{computationSubType}/columns") @Operation(summary = "Update a column", description = "Updates an existing column") @ApiResponse(responseCode = "204", description = "Column updated") public ResponseEntity updateColumns( @PathVariable("studyUuid") UUID studyUuid, @PathVariable UUID id, - @PathVariable ComputationType computationType, @PathVariable String computationSubType, @Valid @RequestBody String columnInfos) { - studyService.updateColumns(id, computationType, computationSubType, columnInfos); + studyService.updateColumns(id, computationSubType, columnInfos); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index c5f213dd18..99b4b14e71 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -402,9 +402,9 @@ public void setGlobalFiltersForComputationResult(UUID id, ComputationType comput restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } - public void updateColumns(UUID id, ComputationType computationType, String computationSubType, String columnInfos) { - var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/columns/{colId}"); - String path = uriBuilder.buildAndExpand(id, computationType, computationSubType).toUriString(); + public void updateColumns(UUID id, String computationSubType, String columnInfos) { + var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/columns"); + String path = uriBuilder.buildAndExpand(id, computationSubType).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); 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 ce16f9822f..8a82ea316c 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -3629,8 +3629,8 @@ public void setGlobalFiltersForComputationResult(UUID id, ComputationType comput studyConfigService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); } - public void updateColumns(UUID id, ComputationType computationType, String computationSubType, String columnInfos) { - studyConfigService.updateColumns(id, computationType, computationSubType, columnInfos); + public void updateColumns(UUID id, String computationSubType, String columnInfos) { + studyConfigService.updateColumns(id, computationSubType, columnInfos); } public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { From 8a79ec3f4cf163cc86b541884888abfff54d7792 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 22 Jan 2026 11:39:54 +0100 Subject: [PATCH 11/20] update ComputationResultFiltersController --- .../ComputationResultFiltersController.java | 21 +++++++++++-------- .../server/service/StudyConfigService.java | 15 ++++++------- .../study/server/service/StudyService.java | 12 ++++++++--- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 0454f3fd89..b237e33b5f 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -12,7 +12,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.gridsuite.study.server.StudyApi; -import org.gridsuite.study.server.dto.ComputationType; +import org.gridsuite.study.server.service.StudyConfigService; import org.gridsuite.study.server.service.StudyService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -27,9 +27,11 @@ @Tag(name = "Study server - Computation result filters") public class ComputationResultFiltersController { private final StudyService studyService; + private final StudyConfigService studyConfigService; - public ComputationResultFiltersController(StudyService studyService) { + public ComputationResultFiltersController(StudyService studyService, StudyConfigService studyConfigService) { this.studyService = studyService; + this.studyConfigService = studyConfigService; } @GetMapping() @@ -40,29 +42,30 @@ public ResponseEntity getComputationResultFilters( return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid)); } - @PostMapping("/{id}/{computationType}/global-filters") + @PostMapping("/{computationType}/global-filters") @Operation(summary = "Set global filters", description = "Replaces all existing global filters with the provided list for a computation result") @ApiResponse(responseCode = "204", description = "Global filters set successfully") @ApiResponse(responseCode = "404", description = "computation result global filters not found") public ResponseEntity setGlobalFiltersForComputationResult( @PathVariable("studyUuid") UUID studyUuid, - @PathVariable UUID id, - @PathVariable ComputationType computationType, + @PathVariable String computationType, @RequestBody String globalFilters) { - studyService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); + UUID computationResultFiltersId = studyService.getComputationResultFiltersId(studyUuid); + studyService.setGlobalFiltersForComputationResult(computationResultFiltersId, computationType, globalFilters); return ResponseEntity.noContent().build(); } - @PutMapping("/{id}/{computationSubType}/columns") + @PutMapping("/{computationType}/{computationSubType}/columns") @Operation(summary = "Update a column", description = "Updates an existing column") @ApiResponse(responseCode = "204", description = "Column updated") public ResponseEntity updateColumns( @PathVariable("studyUuid") UUID studyUuid, - @PathVariable UUID id, + @PathVariable String computationType, @PathVariable String computationSubType, @Valid @RequestBody String columnInfos) { - studyService.updateColumns(id, computationSubType, columnInfos); + UUID computationResultFiltersId = studyService.getComputationResultFiltersId(studyUuid); + studyService.updateColumns(computationResultFiltersId, computationType, computationSubType, columnInfos); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index 99b4b14e71..d04dd46e1f 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -8,7 +8,6 @@ import lombok.Setter; import org.gridsuite.study.server.RemoteServicesProperties; -import org.gridsuite.study.server.dto.ComputationType; import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout; import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.DiagramPosition; import org.gridsuite.study.server.dto.diagramgridlayout.diagramlayout.NetworkAreaDiagramLayout; @@ -393,18 +392,20 @@ public String getComputationResultFilters(UUID uuid) { return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } - public void setGlobalFiltersForComputationResult(UUID id, ComputationType computationType, String globalFilters) { - var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/global-filters"); - String path = uriBuilder.buildAndExpand(id, computationType).toUriString(); + public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { + Map uriVariables = Map.of("id", id, "computationType", computationType); + String path = UriComponentsBuilder.fromPath("/v1/computation-result-filters/{id}/{computationType}/global-filters") + .buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } - public void updateColumns(UUID id, String computationSubType, String columnInfos) { - var uriBuilder = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI + "/columns"); - String path = uriBuilder.buildAndExpand(id, computationSubType).toUriString(); + public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { + Map uriVariables = Map.of("id", id, "computationType", computationType, "computationSubType", computationSubType); + String path = UriComponentsBuilder.fromPath("/v1/computation-result-filters/{id}/{computationType}/{computationSubType}/columns") + .buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); 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 8a82ea316c..1b361f7cd9 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2785,6 +2785,12 @@ public String getComputationResultFilters(UUID studyUuid) { return studyConfigService.getComputationResultFilters(studyConfigService.getOrElseCreateComputationResultFiltersUuid(studyEntity)); } + @Transactional + public UUID getComputationResultFiltersId(UUID studyUuid) { + StudyEntity studyEntity = getStudy(studyUuid); + return studyEntity.getComputationResultFiltersUuid(); + } + /** * Set spreadsheet config collection on study or reset to default one if empty body. * Default is the user profile one, or system default if no profile is available. @@ -3625,12 +3631,12 @@ public void setGlobalFilters(UUID studyUuid, UUID configUuid, String globalFilte notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); } - public void setGlobalFiltersForComputationResult(UUID id, ComputationType computationType, String globalFilters) { + public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { studyConfigService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); } - public void updateColumns(UUID id, String computationSubType, String columnInfos) { - studyConfigService.updateColumns(id, computationSubType, columnInfos); + public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { + studyConfigService.updateColumns(id, computationType, computationSubType, columnInfos); } public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { From 0b12f16965293ec7daf515f18804220c5a2f3907 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 22 Jan 2026 15:22:15 +0100 Subject: [PATCH 12/20] clean code --- .../controller/ComputationResultFiltersController.java | 7 ++----- .../study/server/service/StudyConfigService.java | 8 ++++---- .../gridsuite/study/server/studycontroller/StudyTest.java | 1 - 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index b237e33b5f..2a0cdf40ff 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -12,7 +12,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.gridsuite.study.server.StudyApi; -import org.gridsuite.study.server.service.StudyConfigService; import org.gridsuite.study.server.service.StudyService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -27,11 +26,9 @@ @Tag(name = "Study server - Computation result filters") public class ComputationResultFiltersController { private final StudyService studyService; - private final StudyConfigService studyConfigService; - public ComputationResultFiltersController(StudyService studyService, StudyConfigService studyConfigService) { + public ComputationResultFiltersController(StudyService studyService) { this.studyService = studyService; - this.studyConfigService = studyConfigService; } @GetMapping() @@ -57,7 +54,7 @@ public ResponseEntity setGlobalFiltersForComputationResult( } @PutMapping("/{computationType}/{computationSubType}/columns") - @Operation(summary = "Update a column", description = "Updates an existing column") + @Operation(summary = "Update a column", description = "Updates a column") @ApiResponse(responseCode = "204", description = "Column updated") public ResponseEntity updateColumns( @PathVariable("studyUuid") UUID studyUuid, diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index d04dd46e1f..8f80f2e4f9 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -394,8 +394,8 @@ public String getComputationResultFilters(UUID uuid) { public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { Map uriVariables = Map.of("id", id, "computationType", computationType); - String path = UriComponentsBuilder.fromPath("/v1/computation-result-filters/{id}/{computationType}/global-filters") - .buildAndExpand(uriVariables).toUriString(); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + + "/{id}/{computationType}/global-filters").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); @@ -404,8 +404,8 @@ public void setGlobalFiltersForComputationResult(UUID id, String computationType public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { Map uriVariables = Map.of("id", id, "computationType", computationType, "computationSubType", computationSubType); - String path = UriComponentsBuilder.fromPath("/v1/computation-result-filters/{id}/{computationType}/{computationSubType}/columns") - .buildAndExpand(uriVariables).toUriString(); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + + "/{id}/{computationType}/{computationSubType}/columns").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); diff --git a/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java b/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java index 6bbdf4ec69..cc1cfda1d6 100644 --- a/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java +++ b/src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java @@ -929,7 +929,6 @@ private void testDuplicateStudy(UUID study1Uuid, UUID rootNetworkUuid, String us .voltageInitResultUuid(UUID.randomUUID()) .stateEstimationResultUuid(UUID.randomUUID()) .pccMinResultUuid(UUID.randomUUID()) - .pccMinResultUuid(UUID.randomUUID()) .build() ); From bce1a3769481ba58210924381c6bfe16a9a85af6 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 30 Jan 2026 10:39:15 +0100 Subject: [PATCH 13/20] update controller computation result filters --- .../ComputationResultFiltersController.java | 8 +++-- .../study/server/service/ConsumerService.java | 12 +------- .../server/service/StudyConfigService.java | 7 +++-- .../study/server/service/StudyService.java | 11 ++++--- .../server/ComputationResultFiltersTest.java | 30 ++++++++++--------- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 2a0cdf40ff..b3835f4caa 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -31,12 +31,14 @@ public ComputationResultFiltersController(StudyService studyService) { this.studyService = studyService; } - @GetMapping() + @GetMapping("/{computationType}/{computationSubType}") @Operation(summary = "Get study's computation result filters") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The computation result filters")}) public ResponseEntity getComputationResultFilters( - @PathVariable("studyUuid") UUID studyUuid) { - return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid)); + @PathVariable("studyUuid") UUID studyUuid, + @PathVariable("computationType") String computationType, + @PathVariable("computationSubType") String computationSubType) { + return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid, computationType, computationSubType)); } @PostMapping("/{computationType}/global-filters") diff --git a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java index 5741aecace..4ece406120 100644 --- a/src/main/java/org/gridsuite/study/server/service/ConsumerService.java +++ b/src/main/java/org/gridsuite/study/server/service/ConsumerService.java @@ -295,13 +295,12 @@ private void insertStudy(UUID studyUuid, String userId, NetworkInfos networkInfo UUID pccMinParametersUuid = createDefaultPccMinParameters(); UUID spreadsheetConfigCollectionUuid = createDefaultSpreadsheetConfigCollection(userId, userProfileInfos); UUID diagramGridLayoutUuid = studyService.createGridLayoutFromNadDiagram(userId, userProfileInfos); - UUID computationResultFiltersUuid = createDefaultComputationResultFilters(); studyService.insertStudy(studyUuid, userId, networkInfos, caseInfos, loadFlowParametersUuid, shortCircuitParametersUuid, DynamicSimulationService.toEntity(dynamicSimulationParameters, objectMapper), voltageInitParametersUuid, securityAnalysisParametersUuid, sensitivityAnalysisParametersUuid, networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, - importParameters, importReportUuid, computationResultFiltersUuid); + importParameters, importReportUuid); } private UUID createDefaultLoadFlowParameters(String userId, UserProfileInfos userProfileInfos) { @@ -462,15 +461,6 @@ private UUID createDefaultPccMinParameters() { } } - private UUID createDefaultComputationResultFilters() { - try { - return studyConfigService.createComputationResultFilters(); - } catch (final Exception e) { - LOGGER.error("Error while creating pcc min default parameters", e); - return null; - } - } - private UUID createDefaultSpreadsheetConfigCollection(String userId, UserProfileInfos userProfileInfos) { if (userProfileInfos != null && userProfileInfos.getSpreadsheetConfigCollectionId() != null) { // try to access/duplicate the user profile spreadsheet config collection diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index 8f80f2e4f9..42cce0581f 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -46,7 +46,6 @@ public class StudyConfigService { private static final String DIAGRAM_GRID_LAYOUT_WITH_ID_URI = DIAGRAM_GRID_LAYOUT_URI + UUID_PARAM; private static final String COMPUTATION_RESULT_FILTERS_URI = "/computation-result-filters"; - private static final String COMPUTATION_RESULT_FILTERS_WITH_ID_URI = COMPUTATION_RESULT_FILTERS_URI + UUID_PARAM; private static final DiagramPosition DEFAULT_DIAGRAM_POSITION = new DiagramPosition(2, 2, 0, 0); @@ -386,9 +385,11 @@ public UUID getOrElseCreateComputationResultFiltersUuid(StudyEntity studyEntity) return studyEntity.getComputationResultFiltersUuid(); } - public String getComputationResultFilters(UUID uuid) { + public String getComputationResultFilters(UUID uuid, String computationType, String computationSubType) { Objects.requireNonNull(uuid); - String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_WITH_ID_URI).buildAndExpand(uuid).toUriString(); + Map uriVariables = Map.of("id", uuid,"computationType", computationType, "computationSubType", computationSubType); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + + "/{id}/{computationType}/{computationSubType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } 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 1b361f7cd9..08b88b138f 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -617,7 +617,7 @@ public CreatedStudyBasicInfos insertStudy(UUID studyUuid, String userId, Network UUID shortCircuitParametersUuid, DynamicSimulationParametersEntity dynamicSimulationParametersEntity, UUID voltageInitParametersUuid, UUID securityAnalysisParametersUuid, UUID sensitivityAnalysisParametersUuid, UUID networkVisualizationParametersUuid, UUID dynamicSecurityAnalysisParametersUuid, UUID stateEstimationParametersUuid, UUID pccMinParametersUuid, - UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid, UUID computationResultFiltersUuid) { + UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid) { Objects.requireNonNull(studyUuid); Objects.requireNonNull(userId); Objects.requireNonNull(networkInfos.getNetworkUuid()); @@ -632,7 +632,7 @@ public CreatedStudyBasicInfos insertStudy(UUID studyUuid, String userId, Network voltageInitParametersUuid, securityAnalysisParametersUuid, sensitivityAnalysisParametersUuid, networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, - importParameters, importReportUuid, computationResultFiltersUuid); + importParameters, importReportUuid); // Need to deal with the study creation (with a default root network ?) CreatedStudyBasicInfos createdStudyBasicInfos = toCreatedStudyBasicInfos(studyEntity); @@ -1616,7 +1616,7 @@ private StudyEntity saveStudyThenCreateBasicTree(UUID studyUuid, NetworkInfos ne UUID shortCircuitParametersUuid, DynamicSimulationParametersEntity dynamicSimulationParametersEntity, UUID voltageInitParametersUuid, UUID securityAnalysisParametersUuid, UUID sensitivityAnalysisParametersUuid, UUID networkVisualizationParametersUuid, UUID dynamicSecurityAnalysisParametersUuid, UUID stateEstimationParametersUuid, UUID pccMinParametersUuid, - UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid, UUID computationResultFilterUuid) { + UUID spreadsheetConfigCollectionUuid, UUID diagramGridLayoutUuid, Map importParameters, UUID importReportUuid) { StudyEntity studyEntity = StudyEntity.builder() .id(studyUuid) @@ -1634,7 +1634,6 @@ private StudyEntity saveStudyThenCreateBasicTree(UUID studyUuid, NetworkInfos ne .pccMinParametersUuid(pccMinParametersUuid) .spreadsheetConfigCollectionUuid(spreadsheetConfigCollectionUuid) .diagramGridLayoutUuid(diagramGridLayoutUuid) - .computationResultFiltersUuid(computationResultFilterUuid) .monoRoot(true) .build(); @@ -2780,9 +2779,9 @@ public String getSpreadsheetConfigCollection(UUID studyUuid) { } @Transactional - public String getComputationResultFilters(UUID studyUuid) { + public String getComputationResultFilters(UUID studyUuid, String computationType, String computationSubType) { StudyEntity studyEntity = getStudy(studyUuid); - return studyConfigService.getComputationResultFilters(studyConfigService.getOrElseCreateComputationResultFiltersUuid(studyEntity)); + return studyConfigService.getComputationResultFilters(studyConfigService.getOrElseCreateComputationResultFiltersUuid(studyEntity), computationType, computationSubType); } @Transactional diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index eb3b1287ae..341044f9f7 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -45,8 +45,8 @@ class ComputationResultFiltersTest { private static final String COMPUTATION_FILTERS_JSON = "{\"computationResultFilters\":[]}"; private static final UUID COMPUTATION_FILTERS_UUID = UUID.randomUUID(); - private static final UUID COMPUTATION_GLOBAL_FILTERS_UUID = UUID.randomUUID(); - private static final UUID COLUMN_UUID = UUID.randomUUID(); + private static final String COMPUTATION_TYPE = "LoadFlow"; + private static final String COMPUTATION_SUB_TYPE = "LoadFlowResultsVoltageViolations"; private WireMockServer wireMockServer; @Autowired private MockMvc mockMvc; @@ -60,46 +60,48 @@ void setup() { wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); wireMockServer.start(); studyConfigService.setStudyConfigServerBaseUri(wireMockServer.baseUrl()); - wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID)) + wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE)) .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/default")) .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody("\"" + COMPUTATION_FILTERS_UUID + "\""))); - wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_GLOBAL_FILTERS_UUID + "/global-filters")) + wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/global-filters")) .willReturn(aResponse().withStatus(204))); - wireMockServer.stubFor(WireMock.put(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/columns/" + COLUMN_UUID)) + wireMockServer.stubFor(WireMock.put(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE + "/columns")) .willReturn(aResponse().withStatus(204))); } @Test void getComputationResultFilters() throws Exception { StudyEntity study = insertDummyStudy(null); - MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); + MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", + study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID+ "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); wireMockServer.resetRequests(); study = insertDummyStudy(COMPUTATION_FILTERS_UUID); - mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters", study.getId())).andExpectAll(status().isOk()).andReturn(); + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", + study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID+ "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); } @Test void setGlobalFilters() throws Exception { - StudyEntity study = insertDummyStudy(COMPUTATION_GLOBAL_FILTERS_UUID); + StudyEntity study = insertDummyStudy(COMPUTATION_FILTERS_UUID); String json = "{\"globalFilters\":[]}"; - mockMvc.perform(post("/v1/studies/{studyUuid}/computation-result-filters/{id}/global-filters", study.getId(), COMPUTATION_GLOBAL_FILTERS_UUID) + mockMvc.perform(post("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/global-filters", study.getId(), COMPUTATION_TYPE) .contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); } @Test void updateColumn() throws Exception { - StudyEntity study = insertDummyStudy(COLUMN_UUID); + StudyEntity study = insertDummyStudy(COMPUTATION_FILTERS_UUID); String json = "{\"columnsFilters\":[]}"; - mockMvc.perform(put("/v1/studies/{studyUuid}/computation-result-filters/{id}/columns/{columnUuid}", study.getId(), - COMPUTATION_FILTERS_UUID, COLUMN_UUID).contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + mockMvc.perform(put("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}/columns", study.getId(), + COMPUTATION_TYPE, COMPUTATION_SUB_TYPE).contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); } private StudyEntity insertDummyStudy(UUID computationResultFiltersUuid) { From 8cd14194cd1fe95208ab20ad026ebf04a4f14f48 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 30 Jan 2026 10:53:19 +0100 Subject: [PATCH 14/20] fix checkstyle --- .../gridsuite/study/server/service/StudyConfigService.java | 2 +- .../gridsuite/study/server/ComputationResultFiltersTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index 2057282dab..d7ce814173 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -440,7 +440,7 @@ public UUID getOrElseCreateComputationResultFiltersUuid(StudyEntity studyEntity) public String getComputationResultFilters(UUID uuid, String computationType, String computationSubType) { Objects.requireNonNull(uuid); - Map uriVariables = Map.of("id", uuid,"computationType", computationType, "computationSubType", computationSubType); + Map uriVariables = Map.of("id", uuid, "computationType", computationType, "computationSubType", computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/{id}/{computationType}/{computationSubType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 341044f9f7..3330543384 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -77,7 +77,7 @@ void getComputationResultFilters() throws Exception { study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID+ "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); wireMockServer.resetRequests(); study = insertDummyStudy(COMPUTATION_FILTERS_UUID); @@ -85,7 +85,7 @@ void getComputationResultFilters() throws Exception { study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID+ "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); } @Test From 81a7076328048597b7b8f66beb38b0cda63cbe7a Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 30 Jan 2026 11:27:20 +0100 Subject: [PATCH 15/20] resolve conflicts --- src/main/resources/db/changelog/db.changelog-master.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 99c05491a1..b8d3ede1e7 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -365,3 +365,6 @@ databaseChangeLog: - include: file: changesets/changelog_20260123T095727Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20251117T095627Z.xml + relativeToChangelogFile: true From ff14529295756ea3a52dbcf54a32c9550d86117c Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Fri, 30 Jan 2026 18:02:55 +0100 Subject: [PATCH 16/20] update endpoint --- .../ComputationResultFiltersController.java | 17 ++++++--- .../server/service/StudyConfigService.java | 36 +++++++++---------- .../study/server/service/StudyService.java | 23 ++++++++++-- 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index b3835f4caa..356d739fd8 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -31,14 +31,23 @@ public ComputationResultFiltersController(StudyService studyService) { this.studyService = studyService; } + @GetMapping("/{computationType}") + @Operation(summary = "Get study's computation result global filters") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The computation result global filters")}) + public ResponseEntity getComputationResultGlobalFilters( + @PathVariable("studyUuid") UUID studyUuid, + @PathVariable("computationType") String computationType) { + return ResponseEntity.ok().body(studyService.getComputationResultGlobalFilters(studyUuid, computationType)); + } + @GetMapping("/{computationType}/{computationSubType}") - @Operation(summary = "Get study's computation result filters") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The computation result filters")}) - public ResponseEntity getComputationResultFilters( + @Operation(summary = "Get study's computation result column filters") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The computation result column filters")}) + public ResponseEntity getComputationResultColumnFilters( @PathVariable("studyUuid") UUID studyUuid, @PathVariable("computationType") String computationType, @PathVariable("computationSubType") String computationSubType) { - return ResponseEntity.ok().body(studyService.getComputationResultFilters(studyUuid, computationType, computationSubType)); + return ResponseEntity.ok().body(studyService.getComputationResultColumnFilters(studyUuid, computationType, computationSubType)); } @PostMapping("/{computationType}/global-filters") diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index d7ce814173..d5c7a7c360 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -11,16 +11,15 @@ import org.gridsuite.study.server.repository.StudyEntity; 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.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import static org.gridsuite.study.server.StudyConstants.DELIMITER; import static org.gridsuite.study.server.StudyConstants.STUDY_CONFIG_API_VERSION; @@ -425,20 +424,15 @@ public void deleteWorkspacePanelNadConfig(UUID configId, UUID workspaceId, UUID restTemplate.delete(studyConfigServerBaseUri + path); } - public UUID createComputationResultFilters() { - var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/default") - .buildAndExpand().toUriString(); - return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); - } - - public UUID getOrElseCreateComputationResultFiltersUuid(StudyEntity studyEntity) { - if (studyEntity.getComputationResultFiltersUuid() == null) { - studyEntity.setComputationResultFiltersUuid(createComputationResultFilters()); - } - return studyEntity.getComputationResultFiltersUuid(); + public String getComputationResultGlobalFilters(UUID uuid, String computationType) { + Objects.requireNonNull(uuid); + Map uriVariables = Map.of("id", uuid, "computationType", computationType); + String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + + "/{id}/{computationType}").buildAndExpand(uriVariables).toUriString(); + return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } - public String getComputationResultFilters(UUID uuid, String computationType, String computationSubType) { + public String getComputationResultColumnFilters(UUID uuid, String computationType, String computationSubType) { Objects.requireNonNull(uuid); Map uriVariables = Map.of("id", uuid, "computationType", computationType, "computationSubType", computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + @@ -465,4 +459,10 @@ public void updateColumns(UUID id, String computationType, String computationSub HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); restTemplate.put(studyConfigServerBaseUri + path, httpEntity); } + + public UUID createComputationResultsFiltersRootId() { + var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/default") + .buildAndExpand().toUriString(); + return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); + } } 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 5da7bd2a34..e9647ae287 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -41,7 +41,10 @@ import org.gridsuite.study.server.elasticsearch.StudyInfosService; import org.gridsuite.study.server.error.StudyException; import org.gridsuite.study.server.networkmodificationtree.dto.*; -import org.gridsuite.study.server.networkmodificationtree.entities.*; +import org.gridsuite.study.server.networkmodificationtree.entities.NetworkModificationNodeInfoEntity; +import org.gridsuite.study.server.networkmodificationtree.entities.NodeEntity; +import org.gridsuite.study.server.networkmodificationtree.entities.NodeType; +import org.gridsuite.study.server.networkmodificationtree.entities.RootNetworkNodeInfoEntity; import org.gridsuite.study.server.notification.NotificationService; import org.gridsuite.study.server.notification.dto.NetworkImpactsInfos; import org.gridsuite.study.server.repository.*; @@ -2789,9 +2792,23 @@ public String getSpreadsheetConfigCollection(UUID studyUuid) { } @Transactional - public String getComputationResultFilters(UUID studyUuid, String computationType, String computationSubType) { + public String getComputationResultGlobalFilters(UUID studyUuid, String computationType) { StudyEntity studyEntity = getStudy(studyUuid); - return studyConfigService.getComputationResultFilters(studyConfigService.getOrElseCreateComputationResultFiltersUuid(studyEntity), computationType, computationSubType); + if (studyEntity.getComputationResultFiltersUuid() == null) { + UUID rootId = studyConfigService.createComputationResultsFiltersRootId(); + studyEntity.setComputationResultFiltersUuid(rootId); + } + return studyConfigService.getComputationResultGlobalFilters(studyEntity.getComputationResultFiltersUuid(), computationType); + } + + @Transactional + public String getComputationResultColumnFilters(UUID studyUuid, String computationType, String computationSubType) { + StudyEntity studyEntity = getStudy(studyUuid); + if (studyEntity.getComputationResultFiltersUuid() == null) { + UUID rootId = studyConfigService.createComputationResultsFiltersRootId(); + studyEntity.setComputationResultFiltersUuid(rootId); + } + return studyConfigService.getComputationResultColumnFilters(studyEntity.getComputationResultFiltersUuid(), computationType, computationSubType); } @Transactional From 9acb6f5d1926abf0137769ccc6ce07a61bd40b71 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Sun, 1 Feb 2026 21:33:05 +0100 Subject: [PATCH 17/20] enhance coverage code --- .../server/service/StudyConfigService.java | 12 ++++++----- .../server/ComputationResultFiltersTest.java | 21 +++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index d5c7a7c360..906cdb967c 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -49,6 +49,8 @@ public class StudyConfigService { private static final String WORKSPACE_PANELS_URI = "/panels"; private static final String DEFAULT_URI = "/default"; private static final String COMPUTATION_RESULT_FILTERS_URI = "/computation-result-filters"; + private static final String COMPUTATION_TYPE = "computationType"; + private static final String COMPUTATION_SUB_TYPE = "computationSubType"; private final RestTemplate restTemplate; @@ -426,7 +428,7 @@ public void deleteWorkspacePanelNadConfig(UUID configId, UUID workspaceId, UUID public String getComputationResultGlobalFilters(UUID uuid, String computationType) { Objects.requireNonNull(uuid); - Map uriVariables = Map.of("id", uuid, "computationType", computationType); + Map uriVariables = Map.of("id", uuid, COMPUTATION_TYPE, computationType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/{id}/{computationType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); @@ -434,14 +436,14 @@ public String getComputationResultGlobalFilters(UUID uuid, String computationTyp public String getComputationResultColumnFilters(UUID uuid, String computationType, String computationSubType) { Objects.requireNonNull(uuid); - Map uriVariables = Map.of("id", uuid, "computationType", computationType, "computationSubType", computationSubType); + Map uriVariables = Map.of("id", uuid, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/{id}/{computationType}/{computationSubType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { - Map uriVariables = Map.of("id", id, "computationType", computationType); + Map uriVariables = Map.of("id", id, COMPUTATION_TYPE, computationType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/{id}/{computationType}/global-filters").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); @@ -451,7 +453,7 @@ public void setGlobalFiltersForComputationResult(UUID id, String computationType } public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { - Map uriVariables = Map.of("id", id, "computationType", computationType, "computationSubType", computationSubType); + Map uriVariables = Map.of("id", id, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/{id}/{computationType}/{computationSubType}/columns").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); @@ -461,7 +463,7 @@ public void updateColumns(UUID id, String computationType, String computationSub } public UUID createComputationResultsFiltersRootId() { - var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + "/default") + var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + DEFAULT_URI) .buildAndExpand().toUriString(); return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); } diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 3330543384..9d6283620e 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -60,8 +60,10 @@ void setup() { wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); wireMockServer.start(); studyConfigService.setStudyConfigServerBaseUri(wireMockServer.baseUrl()); - wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE)) + wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE)) .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); + wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE)) + .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/default")) .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody("\"" + COMPUTATION_FILTERS_UUID + "\""))); wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/global-filters")) @@ -80,12 +82,27 @@ void getComputationResultFilters() throws Exception { wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); wireMockServer.resetRequests(); - study = insertDummyStudy(COMPUTATION_FILTERS_UUID); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + wireMockServer.resetRequests(); + + study = insertDummyStudy(null); + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", + study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); + JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); + wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); + wireMockServer.resetRequests(); + + study = insertDummyStudy(COMPUTATION_FILTERS_UUID); + mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", + study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); + JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); + wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); + wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); } @Test From f048f19f1f2b19369c0abbadeff60a56149824d5 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Mon, 2 Feb 2026 12:40:33 +0100 Subject: [PATCH 18/20] refacto TU --- .../server/ComputationResultFiltersTest.java | 78 ++++++++++++++----- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 9d6283620e..8cf77cf7ed 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -21,7 +21,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -43,6 +42,8 @@ @DisableElasticsearch @ContextConfigurationWithTestChannel class ComputationResultFiltersTest { + private static final String BASE_URI = "/v1/computation-result-filters/"; + public static final String DEFAULT = "default"; private static final String COMPUTATION_FILTERS_JSON = "{\"computationResultFilters\":[]}"; private static final UUID COMPUTATION_FILTERS_UUID = UUID.randomUUID(); private static final String COMPUTATION_TYPE = "LoadFlow"; @@ -55,21 +56,60 @@ class ComputationResultFiltersTest { @Autowired private StudyRepository studyRepository; + private void stubGetGlobalFilters() { + stubGet(BASE_URI + COMPUTATION_FILTERS_UUID + "/" + ComputationResultFiltersTest.COMPUTATION_TYPE); + } + + private void stubGetColumnFilters() { + stubGet(BASE_URI + COMPUTATION_FILTERS_UUID + "/" + ComputationResultFiltersTest.COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE); + } + + private void stubGet(String url) { + wireMockServer.stubFor(WireMock.get(urlEqualTo(url)) + .willReturn(okJson(COMPUTATION_FILTERS_JSON))); + } + + private void stubCreateDefaultFilters() { + wireMockServer.stubFor(WireMock.post(urlEqualTo(BASE_URI + DEFAULT)).willReturn(okJson("\"" + COMPUTATION_FILTERS_UUID + "\""))); + } + + private void stubSetGlobalFilters() { + wireMockServer.stubFor(WireMock.post(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + + "/" + COMPUTATION_TYPE + "/global-filters")).willReturn(noContent())); + } + + private void stubUpdateColumns() { + wireMockServer.stubFor(WireMock.put(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + "/" + + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE + "/columns")).willReturn(noContent())); + } + + private void verifyDefaultFiltersCalledOnce() { + wireMockServer.verify(1, postRequestedFor(urlEqualTo(BASE_URI + DEFAULT))); + } + + private void verifyDefaultFiltersNotCalled() { + wireMockServer.verify(0, postRequestedFor(urlEqualTo(BASE_URI + DEFAULT))); + } + + private void verifyColumnFiltersCalledOnce() { + wireMockServer.verify(1, getRequestedFor(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + } + + private void verifyGlobalFiltersCalledOnce() { + wireMockServer.verify(1, getRequestedFor(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); + } + @BeforeEach void setup() { wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); wireMockServer.start(); studyConfigService.setStudyConfigServerBaseUri(wireMockServer.baseUrl()); - wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE)) - .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); - wireMockServer.stubFor(WireMock.get(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE)) - .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody(COMPUTATION_FILTERS_JSON))); - wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/default")) - .willReturn(aResponse().withStatus(200).withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).withBody("\"" + COMPUTATION_FILTERS_UUID + "\""))); - wireMockServer.stubFor(WireMock.post(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/global-filters")) - .willReturn(aResponse().withStatus(204))); - wireMockServer.stubFor(WireMock.put(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE + "/columns")) - .willReturn(aResponse().withStatus(204))); + stubCreateDefaultFilters(); + stubGetGlobalFilters(); + stubGetColumnFilters(); + stubSetGlobalFilters(); + stubUpdateColumns(); } @Test @@ -78,31 +118,31 @@ void getComputationResultFilters() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + verifyDefaultFiltersCalledOnce(); + verifyColumnFiltersCalledOnce(); wireMockServer.resetRequests(); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); + verifyDefaultFiltersNotCalled(); + verifyColumnFiltersCalledOnce(); wireMockServer.resetRequests(); study = insertDummyStudy(null); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - wireMockServer.verify(1, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); + verifyDefaultFiltersCalledOnce(); + verifyGlobalFiltersCalledOnce(); wireMockServer.resetRequests(); study = insertDummyStudy(COMPUTATION_FILTERS_UUID); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - wireMockServer.verify(0, postRequestedFor(urlEqualTo("/v1/computation-result-filters/default"))); - wireMockServer.verify(1, getRequestedFor(urlEqualTo("/v1/computation-result-filters/" + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); + verifyDefaultFiltersNotCalled(); + verifyGlobalFiltersCalledOnce(); } @Test From 381bf777aed7f8bd0a42669cd5ec5f9fe1610896 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Wed, 4 Feb 2026 13:11:05 +0100 Subject: [PATCH 19/20] code review remarks --- .../ComputationResultFiltersController.java | 15 ++++--- .../server/service/StudyConfigService.java | 29 ++++++------ .../study/server/service/StudyService.java | 44 +++++++++++-------- .../server/ComputationResultFiltersTest.java | 37 ++++++++-------- 4 files changed, 69 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java index 356d739fd8..abb37ec7ad 100644 --- a/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java +++ b/src/main/java/org/gridsuite/study/server/controller/ComputationResultFiltersController.java @@ -16,6 +16,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.Optional; import java.util.UUID; /** * @author Rehili Ghazwa @@ -37,7 +38,9 @@ public ComputationResultFiltersController(StudyService studyService) { public ResponseEntity getComputationResultGlobalFilters( @PathVariable("studyUuid") UUID studyUuid, @PathVariable("computationType") String computationType) { - return ResponseEntity.ok().body(studyService.getComputationResultGlobalFilters(studyUuid, computationType)); + return Optional.ofNullable(studyService.getComputationResultGlobalFilters(studyUuid, computationType)) + .map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.noContent().build()); } @GetMapping("/{computationType}/{computationSubType}") @@ -47,7 +50,9 @@ public ResponseEntity getComputationResultColumnFilters( @PathVariable("studyUuid") UUID studyUuid, @PathVariable("computationType") String computationType, @PathVariable("computationSubType") String computationSubType) { - return ResponseEntity.ok().body(studyService.getComputationResultColumnFilters(studyUuid, computationType, computationSubType)); + return Optional.ofNullable(studyService.getComputationResultColumnFilters(studyUuid, computationType, computationSubType)) + .map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.noContent().build()); } @PostMapping("/{computationType}/global-filters") @@ -59,8 +64,7 @@ public ResponseEntity setGlobalFiltersForComputationResult( @PathVariable("studyUuid") UUID studyUuid, @PathVariable String computationType, @RequestBody String globalFilters) { - UUID computationResultFiltersId = studyService.getComputationResultFiltersId(studyUuid); - studyService.setGlobalFiltersForComputationResult(computationResultFiltersId, computationType, globalFilters); + studyService.setGlobalFiltersForComputationResult(studyUuid, computationType, globalFilters); return ResponseEntity.noContent().build(); } @@ -72,8 +76,7 @@ public ResponseEntity updateColumns( @PathVariable String computationType, @PathVariable String computationSubType, @Valid @RequestBody String columnInfos) { - UUID computationResultFiltersId = studyService.getComputationResultFiltersId(studyUuid); - studyService.updateColumns(computationResultFiltersId, computationType, computationSubType, columnInfos); + studyService.updateColumns(studyUuid, computationType, computationSubType, columnInfos); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index 906cdb967c..f7a07472b5 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -51,6 +51,7 @@ public class StudyConfigService { private static final String COMPUTATION_RESULT_FILTERS_URI = "/computation-result-filters"; private static final String COMPUTATION_TYPE = "computationType"; private static final String COMPUTATION_SUB_TYPE = "computationSubType"; + private static final String COMPUTATION_RESULT_FILTERS_ID = "computationResultFiltersId"; private final RestTemplate restTemplate; @@ -426,36 +427,36 @@ public void deleteWorkspacePanelNadConfig(UUID configId, UUID workspaceId, UUID restTemplate.delete(studyConfigServerBaseUri + path); } - public String getComputationResultGlobalFilters(UUID uuid, String computationType) { - Objects.requireNonNull(uuid); - Map uriVariables = Map.of("id", uuid, COMPUTATION_TYPE, computationType); + public String getComputationResultGlobalFilters(UUID computationResultFiltersId, String computationType) { + Objects.requireNonNull(computationResultFiltersId); + Map uriVariables = Map.of(COMPUTATION_RESULT_FILTERS_ID, computationResultFiltersId, COMPUTATION_TYPE, computationType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + - "/{id}/{computationType}").buildAndExpand(uriVariables).toUriString(); + "/{computationResultFiltersId}/{computationType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } - public String getComputationResultColumnFilters(UUID uuid, String computationType, String computationSubType) { - Objects.requireNonNull(uuid); - Map uriVariables = Map.of("id", uuid, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); + public String getComputationResultColumnFilters(UUID computationResultFiltersId, String computationType, String computationSubType) { + Objects.requireNonNull(computationResultFiltersId); + Map uriVariables = Map.of(COMPUTATION_RESULT_FILTERS_ID, computationResultFiltersId, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + - "/{id}/{computationType}/{computationSubType}").buildAndExpand(uriVariables).toUriString(); + "/{computationResultFiltersId}/{computationType}/{computationSubType}").buildAndExpand(uriVariables).toUriString(); return restTemplate.getForObject(studyConfigServerBaseUri + path, String.class); } - public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { - Map uriVariables = Map.of("id", id, COMPUTATION_TYPE, computationType); + public void setGlobalFiltersForComputationResult(UUID computationResultFiltersUuid, String computationType, String globalFilters) { + Map uriVariables = Map.of(COMPUTATION_RESULT_FILTERS_ID, computationResultFiltersUuid, COMPUTATION_TYPE, computationType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + - "/{id}/{computationType}/global-filters").buildAndExpand(uriVariables).toUriString(); + "/{computationResultFiltersId}/{computationType}/global-filters").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(globalFilters, headers); restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); } - public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { - Map uriVariables = Map.of("id", id, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); + public void updateColumns(UUID computationResultFiltersId, String computationType, String computationSubType, String columnInfos) { + Map uriVariables = Map.of(COMPUTATION_RESULT_FILTERS_ID, computationResultFiltersId, COMPUTATION_TYPE, computationType, COMPUTATION_SUB_TYPE, computationSubType); String path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + - "/{id}/{computationType}/{computationSubType}/columns").buildAndExpand(uriVariables).toUriString(); + "/{computationResultFiltersId}/{computationType}/{computationSubType}/columns").buildAndExpand(uriVariables).toUriString(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity httpEntity = new HttpEntity<>(columnInfos, headers); 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 e9647ae287..89426f90fc 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2794,27 +2794,21 @@ public String getSpreadsheetConfigCollection(UUID studyUuid) { @Transactional public String getComputationResultGlobalFilters(UUID studyUuid, String computationType) { StudyEntity studyEntity = getStudy(studyUuid); - if (studyEntity.getComputationResultFiltersUuid() == null) { - UUID rootId = studyConfigService.createComputationResultsFiltersRootId(); - studyEntity.setComputationResultFiltersUuid(rootId); + UUID computationResultFiltersId = studyEntity.getComputationResultFiltersUuid(); + if (Objects.isNull(computationResultFiltersId)) { + return null; } - return studyConfigService.getComputationResultGlobalFilters(studyEntity.getComputationResultFiltersUuid(), computationType); + return studyConfigService.getComputationResultGlobalFilters(computationResultFiltersId, computationType); } @Transactional public String getComputationResultColumnFilters(UUID studyUuid, String computationType, String computationSubType) { StudyEntity studyEntity = getStudy(studyUuid); - if (studyEntity.getComputationResultFiltersUuid() == null) { - UUID rootId = studyConfigService.createComputationResultsFiltersRootId(); - studyEntity.setComputationResultFiltersUuid(rootId); + UUID computationResultFiltersId = studyEntity.getComputationResultFiltersUuid(); + if (Objects.isNull(computationResultFiltersId)) { + return null; } - return studyConfigService.getComputationResultColumnFilters(studyEntity.getComputationResultFiltersUuid(), computationType, computationSubType); - } - - @Transactional - public UUID getComputationResultFiltersId(UUID studyUuid) { - StudyEntity studyEntity = getStudy(studyUuid); - return studyEntity.getComputationResultFiltersUuid(); + return studyConfigService.getComputationResultColumnFilters(computationResultFiltersId, computationType, computationSubType); } /** @@ -3671,12 +3665,26 @@ public void setGlobalFilters(UUID studyUuid, UUID configUuid, String globalFilte notificationService.emitSpreadsheetConfigChanged(studyUuid, configUuid); } - public void setGlobalFiltersForComputationResult(UUID id, String computationType, String globalFilters) { - studyConfigService.setGlobalFiltersForComputationResult(id, computationType, globalFilters); + @Transactional + public void setGlobalFiltersForComputationResult(UUID studyUuid, String computationType, String globalFilters) { + UUID computationResultFiltersId = getComputationResultFiltersId(studyUuid); + studyConfigService.setGlobalFiltersForComputationResult(computationResultFiltersId, computationType, globalFilters); + } + + @Transactional + public void updateColumns(UUID studyUuid, String computationType, String computationSubType, String columnInfos) { + UUID computationResultFiltersId = getComputationResultFiltersId(studyUuid); + studyConfigService.updateColumns(computationResultFiltersId, computationType, computationSubType, columnInfos); } - public void updateColumns(UUID id, String computationType, String computationSubType, String columnInfos) { - studyConfigService.updateColumns(id, computationType, computationSubType, columnInfos); + public UUID getComputationResultFiltersId(UUID studyUuid) { + StudyEntity studyEntity = getStudy(studyUuid); + UUID rootId = studyEntity.getComputationResultFiltersUuid(); + if (Objects.isNull(rootId)) { + rootId = studyConfigService.createComputationResultsFiltersRootId(); + studyEntity.setComputationResultFiltersUuid(rootId); + } + return rootId; } public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) { diff --git a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java index 8cf77cf7ed..b17e27c83d 100644 --- a/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java +++ b/src/test/java/org/gridsuite/study/server/ComputationResultFiltersTest.java @@ -29,6 +29,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.gridsuite.study.server.utils.assertions.Assertions.assertThat; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; @@ -91,11 +92,6 @@ private void verifyDefaultFiltersNotCalled() { wireMockServer.verify(0, postRequestedFor(urlEqualTo(BASE_URI + DEFAULT))); } - private void verifyColumnFiltersCalledOnce() { - wireMockServer.verify(1, getRequestedFor(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + - "/" + COMPUTATION_TYPE + "/" + COMPUTATION_SUB_TYPE))); - } - private void verifyGlobalFiltersCalledOnce() { wireMockServer.verify(1, getRequestedFor(urlEqualTo(BASE_URI + COMPUTATION_FILTERS_UUID + "/" + COMPUTATION_TYPE))); } @@ -116,41 +112,44 @@ void setup() { void getComputationResultFilters() throws Exception { StudyEntity study = insertDummyStudy(null); MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", - study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); - JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - verifyDefaultFiltersCalledOnce(); - verifyColumnFiltersCalledOnce(); - wireMockServer.resetRequests(); + study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isNoContent()).andReturn(); + assertThat(mvcResult.getResponse().getContentAsString()).isEmpty(); + study = insertDummyStudy(COMPUTATION_FILTERS_UUID); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}", study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); verifyDefaultFiltersNotCalled(); - verifyColumnFiltersCalledOnce(); wireMockServer.resetRequests(); study = insertDummyStudy(null); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", - study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); - JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - verifyDefaultFiltersCalledOnce(); - verifyGlobalFiltersCalledOnce(); - wireMockServer.resetRequests(); + study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isNoContent()).andReturn(); + assertThat(mvcResult.getResponse().getContentAsString()).isEmpty(); study = insertDummyStudy(COMPUTATION_FILTERS_UUID); mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/computation-result-filters/{computationType}", study.getId(), COMPUTATION_TYPE)).andExpectAll(status().isOk()).andReturn(); JSONAssert.assertEquals(COMPUTATION_FILTERS_JSON, mvcResult.getResponse().getContentAsString(), JSONCompareMode.NON_EXTENSIBLE); - verifyDefaultFiltersNotCalled(); verifyGlobalFiltersCalledOnce(); + wireMockServer.resetRequests(); } @Test void setGlobalFilters() throws Exception { - StudyEntity study = insertDummyStudy(COMPUTATION_FILTERS_UUID); + StudyEntity study = insertDummyStudy(null); String json = "{\"globalFilters\":[]}"; mockMvc.perform(post("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/global-filters", study.getId(), COMPUTATION_TYPE) .contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + verifyDefaultFiltersCalledOnce(); + wireMockServer.resetRequests(); + + study = insertDummyStudy(COMPUTATION_FILTERS_UUID); + json = "{\"globalFilters\":[]}"; + mockMvc.perform(post("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/global-filters", study.getId(), COMPUTATION_TYPE) + .contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + verifyDefaultFiltersNotCalled(); + wireMockServer.resetRequests(); } @Test @@ -159,6 +158,8 @@ void updateColumn() throws Exception { String json = "{\"columnsFilters\":[]}"; mockMvc.perform(put("/v1/studies/{studyUuid}/computation-result-filters/{computationType}/{computationSubType}/columns", study.getId(), COMPUTATION_TYPE, COMPUTATION_SUB_TYPE).contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isNoContent()); + verifyDefaultFiltersNotCalled(); + wireMockServer.resetRequests(); } private StudyEntity insertDummyStudy(UUID computationResultFiltersUuid) { From d74cad8c6b1b5bda81f48f5412ffdba4e354a205 Mon Sep 17 00:00:00 2001 From: Rehili Ghazwa Date: Thu, 5 Feb 2026 11:37:06 +0100 Subject: [PATCH 20/20] rename to omputationResultsFiltersId --- .../study/server/service/StudyConfigService.java | 2 +- .../gridsuite/study/server/service/StudyService.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java index f7a07472b5..b307336a7c 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyConfigService.java @@ -463,7 +463,7 @@ public void updateColumns(UUID computationResultFiltersId, String computationTyp restTemplate.put(studyConfigServerBaseUri + path, httpEntity); } - public UUID createComputationResultsFiltersRootId() { + public UUID createComputationResultsFiltersId() { var path = UriComponentsBuilder.fromPath(DELIMITER + STUDY_CONFIG_API_VERSION + COMPUTATION_RESULT_FILTERS_URI + DEFAULT_URI) .buildAndExpand().toUriString(); return restTemplate.exchange(studyConfigServerBaseUri + path, HttpMethod.POST, null, UUID.class).getBody(); 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 89426f90fc..755639e3a4 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -3679,12 +3679,12 @@ public void updateColumns(UUID studyUuid, String computationType, String computa public UUID getComputationResultFiltersId(UUID studyUuid) { StudyEntity studyEntity = getStudy(studyUuid); - UUID rootId = studyEntity.getComputationResultFiltersUuid(); - if (Objects.isNull(rootId)) { - rootId = studyConfigService.createComputationResultsFiltersRootId(); - studyEntity.setComputationResultFiltersUuid(rootId); + UUID computationResultFiltersId = studyEntity.getComputationResultFiltersUuid(); + if (Objects.isNull(computationResultFiltersId)) { + computationResultFiltersId = studyConfigService.createComputationResultsFiltersId(); + studyEntity.setComputationResultFiltersUuid(computationResultFiltersId); } - return rootId; + return computationResultFiltersId; } public void renameSpreadsheetConfig(UUID studyUuid, UUID configUuid, String newName) {