From 26c8b4485f8794798cd46d3e27caac6734c87722 Mon Sep 17 00:00:00 2001 From: Radouane Khouadri Date: Sat, 16 May 2026 15:46:09 +0200 Subject: [PATCH] move endpoints that update geo data to supervision controller Signed-off-by: Radouane Khouadri --- .../geodata/server/GeoDataController.java | 28 +--- .../geodata/server/SupervisionController.java | 56 ++++++++ .../geodata/server/GeoDataControllerTest.java | 56 +------- .../server/SupervisionControllerTest.java | 125 ++++++++++++++++++ 4 files changed, 190 insertions(+), 75 deletions(-) create mode 100644 src/main/java/org/gridsuite/geodata/server/SupervisionController.java create mode 100644 src/test/java/org/gridsuite/geodata/server/SupervisionControllerTest.java diff --git a/src/main/java/org/gridsuite/geodata/server/GeoDataController.java b/src/main/java/org/gridsuite/geodata/server/GeoDataController.java index 3e5bea5..6b7ee2d 100644 --- a/src/main/java/org/gridsuite/geodata/server/GeoDataController.java +++ b/src/main/java/org/gridsuite/geodata/server/GeoDataController.java @@ -17,7 +17,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.gridsuite.geodata.server.dto.LineGeoData; import org.gridsuite.geodata.server.dto.SubstationGeoData; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -41,11 +40,14 @@ public class GeoDataController { static final String API_VERSION = "v1"; - @Autowired - private GeoDataService geoDataService; + private final GeoDataService geoDataService; - @Autowired - private NetworkStoreService networkStoreService; + private final NetworkStoreService networkStoreService; + + public GeoDataController(GeoDataService geoDataService, NetworkStoreService networkStoreService) { + this.geoDataService = geoDataService; + this.networkStoreService = networkStoreService; + } private static Set toCountrySet(@RequestParam(required = false) List countries) { return countries != null ? countries.stream().map(Country::valueOf).collect(Collectors.toSet()) : Collections.emptySet(); @@ -82,20 +84,4 @@ public CompletableFuture>> getLines(@Parameter( return geoDataService.getLinesData(network, countrySet, lineIds).thenApply( lines -> ResponseEntity.ok().body(lines)); } - - @PostMapping(value = "/substations") - @Operation(summary = "Save substations geographical data") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Substations geographical data have been correctly saved")}) - public ResponseEntity saveSubstations(@RequestBody List substationGeoData) { - geoDataService.saveSubstations(substationGeoData); - return ResponseEntity.ok().build(); - } - - @PostMapping(value = "/lines") - @Operation(summary = "Save lines geographical data") - @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Lines geographical data have been correctly saved")}) - public ResponseEntity saveLines(@RequestBody List linesGeoData) { - geoDataService.saveLines(linesGeoData); - return ResponseEntity.ok().build(); - } } diff --git a/src/main/java/org/gridsuite/geodata/server/SupervisionController.java b/src/main/java/org/gridsuite/geodata/server/SupervisionController.java new file mode 100644 index 0000000..a6b0c9a --- /dev/null +++ b/src/main/java/org/gridsuite/geodata/server/SupervisionController.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2019, 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.geodata.server; + +import io.swagger.v3.oas.annotations.Operation; +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.geodata.server.dto.LineGeoData; +import org.gridsuite.geodata.server.dto.SubstationGeoData; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author Radouane Khouadri + */ +@RestController +@RequestMapping(value = SupervisionController.API_VERSION + "/supervision") +@Tag(name = "Geo data - Supervision") +@ComponentScan(basePackageClasses = {SupervisionController.class, GeoDataService.class}) +public class SupervisionController { + + static final String API_VERSION = "v1"; + + private final GeoDataService geoDataService; + + public SupervisionController(GeoDataService geoDataService) { + this.geoDataService = geoDataService; + } + + @PostMapping(value = "/substations") + @Operation(summary = "Save substations geographical data") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Substations geographical data have been correctly saved")}) + public ResponseEntity saveSubstations(@RequestBody List substationGeoData) { + geoDataService.saveSubstations(substationGeoData); + return ResponseEntity.ok().build(); + } + + @PostMapping(value = "/lines") + @Operation(summary = "Save lines geographical data") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Lines geographical data have been correctly saved")}) + public ResponseEntity saveLines(@RequestBody List linesGeoData) { + geoDataService.saveLines(linesGeoData); + return ResponseEntity.ok().build(); + } +} diff --git a/src/test/java/org/gridsuite/geodata/server/GeoDataControllerTest.java b/src/test/java/org/gridsuite/geodata/server/GeoDataControllerTest.java index 81288d4..0d04ba1 100644 --- a/src/test/java/org/gridsuite/geodata/server/GeoDataControllerTest.java +++ b/src/test/java/org/gridsuite/geodata/server/GeoDataControllerTest.java @@ -6,19 +6,14 @@ */ package org.gridsuite.geodata.server; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.io.ByteStreams; import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.VariantManagerConstants; -import com.powsybl.iidm.network.extensions.Coordinate; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.network.store.client.RestClientImpl; import com.powsybl.ws.commons.error.BaseExceptionHandler; -import org.gridsuite.geodata.server.dto.LineGeoData; -import org.gridsuite.geodata.server.dto.SubstationGeoData; import org.gridsuite.geodata.server.repositories.LineRepository; import org.gridsuite.geodata.server.repositories.SubstationRepository; import org.hamcrest.core.StringContains; @@ -33,10 +28,6 @@ import java.io.IOException; import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Objects; import java.util.UUID; import static com.powsybl.network.store.model.NetworkStoreApi.VERSION; @@ -44,7 +35,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.http.MediaType.APPLICATION_JSON; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** @@ -54,9 +46,6 @@ @Import(BaseExceptionHandler.class) class GeoDataControllerTest { - @Autowired - private ObjectMapper objectMapper; - @Autowired private MockMvc mvc; @@ -75,16 +64,9 @@ class GeoDataControllerTest { @MockitoBean private RestClientImpl restClient; - private static final String GEO_DATA_SUBSTATIONS = "/geo_data_substations.json"; - private static final String GEO_DATA_LINES = "/geo_data_lines.json"; - private static final String VARIANT_ID = "First_variant"; private static final String WRONG_VARIANT_ID = "Wrong_variant"; - private static String toString(String resourceName) throws IOException { - return new String(ByteStreams.toByteArray(Objects.requireNonNull(GeoDataControllerTest.class.getResourceAsStream(resourceName))), StandardCharsets.UTF_8); - } - @Test void test() throws Exception { UUID networkUuid = UUID.fromString("7928181c-7977-4592-ba19-88027e4254e4"); @@ -145,40 +127,6 @@ void test() throws Exception { .andExpect(content().string(StringContains.containsString("Variant '" + WRONG_VARIANT_ID + "' not found"))) .andExpect(status().isInternalServerError()); - String substationJson = objectMapper.writeValueAsString(Collections.singleton( - SubstationGeoData.builder() - .id("testID") - .country(Country.FR) - .coordinate(new Coordinate(1, 1)) - .build())); - - mvc.perform(post("/" + VERSION + "/substations") - .contentType(APPLICATION_JSON) - .content(substationJson)) - .andExpect(status().isOk()); - - mvc.perform(post("/" + VERSION + "/lines") - .contentType(APPLICATION_JSON) - .content(objectMapper.writeValueAsString(Collections.singleton( - LineGeoData.builder() - .country1(Country.FR) - .country2(Country.BE) - .substationStart("subFR") - .substationEnd("subBE") - .coordinates(new ArrayList<>()) - .build())))) - .andExpect(status().isOk()); - - mvc.perform(post("/" + VERSION + "/substations") - .contentType(APPLICATION_JSON) - .content(toString(GEO_DATA_SUBSTATIONS))) - .andExpect(status().isOk()); - - mvc.perform(post("/" + VERSION + "/lines") - .contentType(APPLICATION_JSON) - .content(toString(GEO_DATA_LINES))) - .andExpect(status().isOk()); - mockMvcResultActions = mvc.perform(post("/" + VERSION + "/substations/infos?networkUuid=" + networkUuid + "&variantId=" + VARIANT_ID + "&country=" + Country.FR) .contentType(APPLICATION_JSON) .content("[\"P1\", \"P2\"]")) diff --git a/src/test/java/org/gridsuite/geodata/server/SupervisionControllerTest.java b/src/test/java/org/gridsuite/geodata/server/SupervisionControllerTest.java new file mode 100644 index 0000000..c38bcff --- /dev/null +++ b/src/test/java/org/gridsuite/geodata/server/SupervisionControllerTest.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2019, 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.geodata.server; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.io.ByteStreams; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.VariantManagerConstants; +import com.powsybl.iidm.network.extensions.Coordinate; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.network.store.client.NetworkStoreService; +import com.powsybl.network.store.client.PreloadingStrategy; +import com.powsybl.network.store.client.RestClientImpl; +import com.powsybl.ws.commons.error.BaseExceptionHandler; +import org.gridsuite.geodata.server.dto.LineGeoData; +import org.gridsuite.geodata.server.dto.SubstationGeoData; +import org.gridsuite.geodata.server.repositories.LineRepository; +import org.gridsuite.geodata.server.repositories.SubstationRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Objects; +import java.util.UUID; + +import static com.powsybl.network.store.model.NetworkStoreApi.VERSION; +import static org.mockito.BDDMockito.given; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Radouane Khouadri + */ +@WebMvcTest(SupervisionController.class) +@Import(BaseExceptionHandler.class) +class SupervisionControllerTest { + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private MockMvc mvc; + + @MockitoBean + private NetworkStoreService service; + + @MockitoBean + private SubstationRepository substationRepository; + + @MockitoBean + private LineRepository lineRepository; + + @MockitoBean + private GeoDataObserver geoDataObserver; + + @MockitoBean + private RestClientImpl restClient; + + private static final String GEO_DATA_SUBSTATIONS = "/geo_data_substations.json"; + private static final String GEO_DATA_LINES = "/geo_data_lines.json"; + + private static final String VARIANT_ID = "First_variant"; + + private static String toString(String resourceName) throws IOException { + return new String(ByteStreams.toByteArray(Objects.requireNonNull(SupervisionControllerTest.class.getResourceAsStream(resourceName))), StandardCharsets.UTF_8); + } + + @Test + void test() throws Exception { + UUID networkUuid = UUID.fromString("7928181c-7977-4592-ba19-88027e4254e4"); + + Network testNetwork = EurostagTutorialExample1Factory.create(); + testNetwork.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_ID); + given(service.getNetwork(networkUuid)).willReturn(testNetwork); + given(service.getNetwork(networkUuid, PreloadingStrategy.NONE)).willReturn(testNetwork); + given(service.getNetwork(networkUuid, PreloadingStrategy.COLLECTION)).willReturn(testNetwork); + + String substationJson = objectMapper.writeValueAsString(Collections.singleton( + SubstationGeoData.builder() + .id("testID") + .country(Country.FR) + .coordinate(new Coordinate(1, 1)) + .build())); + + mvc.perform(post("/" + VERSION + "/supervision/substations") + .contentType(APPLICATION_JSON) + .content(substationJson)) + .andExpect(status().isOk()); + + mvc.perform(post("/" + VERSION + "/supervision/lines") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(Collections.singleton( + LineGeoData.builder() + .country1(Country.FR) + .country2(Country.BE) + .substationStart("subFR") + .substationEnd("subBE") + .coordinates(new ArrayList<>()) + .build())))) + .andExpect(status().isOk()); + + mvc.perform(post("/" + VERSION + "/supervision/substations") + .contentType(APPLICATION_JSON) + .content(toString(GEO_DATA_SUBSTATIONS))) + .andExpect(status().isOk()); + + mvc.perform(post("/" + VERSION + "/supervision/lines") + .contentType(APPLICATION_JSON) + .content(toString(GEO_DATA_LINES))) + .andExpect(status().isOk()); + } +}