Skip to content

Commit 8ff803b

Browse files
author
Slimane AMAR
committed
Merge branch 'main' of https://github.com/powsybl/powsybl-study-server into robustify_node_invalidation_when_deleting_remote_data
2 parents 504829d + a1d389b commit 8ff803b

13 files changed

+177
-46
lines changed

src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ protected ResponseEntity<Object> handleStudyException(StudyException exception)
3434
STUDY_NOT_FOUND,
3535
NODE_NOT_FOUND,
3636
ROOT_NETWORK_NOT_FOUND,
37+
LOADFLOW_NOT_FOUND,
3738
SECURITY_ANALYSIS_NOT_FOUND,
3839
SENSITIVITY_ANALYSIS_NOT_FOUND,
3940
SHORT_CIRCUIT_ANALYSIS_NOT_FOUND,
@@ -80,7 +81,8 @@ protected ResponseEntity<Object> handleStudyException(StudyException exception)
8081
BAD_MODIFICATION_TYPE,
8182
BAD_JSON_FORMAT,
8283
TIME_SERIES_BAD_TYPE,
83-
TIMELINE_BAD_TYPE
84+
TIMELINE_BAD_TYPE,
85+
BAD_PARAMETER
8486
-> ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exception.getMessage());
8587
case NETWORK_NOT_FOUND,
8688
NETWORK_INDEXATION_FAILED,

src/main/java/org/gridsuite/study/server/StudyConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ private StudyConstants() {
4444

4545
public static final String DELIMITER = "/";
4646
public static final String QUERY_PARAM_VARIANT_ID = "variantId";
47+
public static final String QUERY_PARAM_NETWORK_UUID = "networkUuid";
4748
public static final String QUERY_PARAM_EQUIPMENT_TYPE = "equipmentType";
4849
public static final String QUERY_PARAM_ELEMENT_TYPE = "elementType";
4950
public static final String QUERY_PARAM_SIDE = "side";
@@ -88,7 +89,6 @@ private StudyConstants() {
8889
public static final String PATH_PARAM_PARAMETERS = "parameters";
8990
public static final String DYNA_FLOW_PROVIDER = "DynaFlow";
9091

91-
9292
public enum SldDisplayMode {
9393
FEEDER_POSITION,
9494
STATE_VARIABLE

src/main/java/org/gridsuite/study/server/StudyException.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public enum Type {
7272
GET_NETWORK_NOMINAL_VOLTAGES_FAILED,
7373
BAD_JSON_FORMAT,
7474
UNKNOWN_ACTION_TYPE,
75+
BAD_PARAMETER,
7576
MISSING_PARAMETER,
7677
LOAD_SCALING_FAILED,
7778
DELETE_VOLTAGE_LEVEL_ON_LINE,

src/main/java/org/gridsuite/study/server/controller/StudyController.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import jakarta.servlet.http.HttpServletResponse;
1818
import org.apache.commons.lang3.StringUtils;
1919
import org.gridsuite.study.server.StudyApi;
20-
import org.gridsuite.study.server.StudyConstants.*;
2120
import org.gridsuite.study.server.StudyException;
2221
import org.gridsuite.study.server.StudyException.Type;
2322
import org.gridsuite.study.server.dto.*;
@@ -56,6 +55,7 @@
5655
import org.springframework.util.CollectionUtils;
5756
import org.springframework.web.bind.WebDataBinder;
5857
import org.springframework.web.bind.annotation.*;
58+
import org.springframework.web.multipart.MultipartFile;
5959

6060
import javax.annotation.Nullable;
6161
import java.beans.PropertyEditorSupport;
@@ -764,6 +764,16 @@ public ResponseEntity<LoadFlowComputationInfos> getLoadFlowComputationInfos(@Par
764764
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(rootNetworkNodeInfoService.getLoadFlowComputationInfos(nodeUuid, rootNetworkUuid));
765765
}
766766

767+
@GetMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/loadflow/modifications")
768+
@Operation(summary = "Get the loadflow modifications on study node and root network")
769+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The loadflow computation infos"),
770+
@ApiResponse(responseCode = "404", description = "The loadflow computation has not been found")})
771+
public ResponseEntity<String> getLoadFlowModifications(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid,
772+
@Parameter(description = "rootNetworkUuid") @PathVariable("rootNetworkUuid") UUID rootNetworkUuid,
773+
@Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) {
774+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(rootNetworkNodeInfoService.getLoadFlowModifications(nodeUuid, rootNetworkUuid));
775+
}
776+
767777
@PutMapping(value = "/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/loadflow/stop")
768778
@Operation(summary = "stop loadflow on study")
769779
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The loadflow has been stopped")})
@@ -2087,6 +2097,14 @@ public ResponseEntity<Void> setNetworkVisualizationParametersValues(
20872097
return ResponseEntity.ok().build();
20882098
}
20892099

2100+
@PostMapping(value = "/studies/network-visualizations/nad-positions-config", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
2101+
@Operation(summary = "create a nad positions configuration using data from a csv")
2102+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The nad positions configuration created")})
2103+
public ResponseEntity<Void> createNadPositionsConfigFromCsv(@RequestParam("file") MultipartFile file) {
2104+
studyService.createNadPositionsConfigFromCsv(file);
2105+
return ResponseEntity.ok().build();
2106+
}
2107+
20902108
@GetMapping(value = "/optional-services")
20912109
@Operation(summary = "Get all the optional services and their status")
20922110
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "List of optional services")})

src/main/java/org/gridsuite/study/server/service/LoadFlowService.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ public String getLoadFlowResult(UUID resultUuid, String filters, Sort sort) {
139139
return result;
140140
}
141141

142+
public String getLoadFlowModifications(UUID resultUuid) {
143+
String result;
144+
145+
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + LOADFLOW_API_VERSION + "/results/{resultUuid}/modifications");
146+
String path = uriComponentsBuilder.buildAndExpand(resultUuid).toUriString();
147+
148+
try {
149+
result = restTemplate.getForObject(loadFlowServerBaseUri + path, String.class);
150+
} catch (HttpStatusCodeException e) {
151+
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
152+
throw new StudyException(LOADFLOW_NOT_FOUND);
153+
}
154+
throw e;
155+
}
156+
return result;
157+
}
158+
142159
public LoadFlowStatus getLoadFlowStatus(UUID resultUuid) {
143160
LoadFlowStatus result;
144161

src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,15 @@ public LoadFlowComputationInfos getLoadFlowComputationInfos(UUID nodeUuid, UUID
655655
return new LoadFlowComputationInfos(isWithRatioTapChangers);
656656
}
657657

658+
@Transactional(readOnly = true)
659+
public String getLoadFlowModifications(UUID nodeUuid, UUID rootNetworkUuid) {
660+
UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, LOAD_FLOW);
661+
if (resultUuid == null) {
662+
throw new StudyException(LOADFLOW_NOT_FOUND);
663+
}
664+
return loadFlowService.getLoadFlowModifications(resultUuid);
665+
}
666+
658667
@Transactional(readOnly = true)
659668
public SecurityAnalysisStatus getSecurityAnalysisStatus(UUID nodeUuid, UUID rootNetworkUuid) {
660669
UUID resultUuid = getComputationResultUuid(nodeUuid, rootNetworkUuid, SECURITY_ANALYSIS);

src/main/java/org/gridsuite/study/server/service/SingleLineDiagramService.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@
1111
* @author Kevin Le Saulnier <kevin.lesaulnier at rte-france.com>
1212
*/
1313

14-
import static org.gridsuite.study.server.StudyConstants.*;
15-
import static org.gridsuite.study.server.StudyException.Type.*;
16-
import static org.gridsuite.study.server.utils.StudyUtils.handleHttpError;
17-
18-
import java.util.List;
19-
import java.util.Objects;
20-
import java.util.UUID;
21-
2214
import org.apache.commons.lang3.StringUtils;
2315
import org.gridsuite.study.server.StudyException;
2416
import org.gridsuite.study.server.dto.DiagramParameters;
@@ -28,10 +20,21 @@
2820
import org.springframework.core.ParameterizedTypeReference;
2921
import org.springframework.http.*;
3022
import org.springframework.stereotype.Service;
23+
import org.springframework.util.LinkedMultiValueMap;
24+
import org.springframework.util.MultiValueMap;
3125
import org.springframework.web.client.HttpStatusCodeException;
3226
import org.springframework.web.client.RestTemplate;
27+
import org.springframework.web.multipart.MultipartFile;
3328
import org.springframework.web.util.UriComponentsBuilder;
3429

30+
import java.util.List;
31+
import java.util.Objects;
32+
import java.util.UUID;
33+
34+
import static org.gridsuite.study.server.StudyConstants.*;
35+
import static org.gridsuite.study.server.StudyException.Type.*;
36+
import static org.gridsuite.study.server.utils.StudyUtils.handleHttpError;
37+
3538
@Service
3639
public class SingleLineDiagramService {
3740

@@ -188,26 +191,14 @@ public String getNetworkAreaDiagram(UUID networkUuid, String variantId, String n
188191
} catch (HttpStatusCodeException e) {
189192
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
190193
throw new StudyException(SVG_NOT_FOUND, VOLTAGE_LEVEL + NOT_FOUND);
194+
} else if (HttpStatus.BAD_REQUEST.equals(e.getStatusCode())) {
195+
throw new StudyException(BAD_PARAMETER, e.getMessage());
191196
} else {
192197
throw e;
193198
}
194199
}
195200
}
196201

197-
public UUID createDiagramConfig(NetworkAreaDiagramLayoutDetails nadLayoutDetails) {
198-
var path = UriComponentsBuilder
199-
.fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/config")
200-
.buildAndExpand()
201-
.toUriString();
202-
203-
HttpHeaders headers = new HttpHeaders();
204-
headers.setContentType(MediaType.APPLICATION_JSON);
205-
206-
HttpEntity<NetworkAreaDiagramLayoutDetails> httpEntity = new HttpEntity<>(nadLayoutDetails, headers);
207-
208-
return restTemplate.exchange(singleLineDiagramServerBaseUri + path, HttpMethod.POST, httpEntity, UUID.class).getBody();
209-
}
210-
211202
public void createMultipleDiagramConfigs(List<NadConfigInfos> nadConfigs) {
212203
var path = UriComponentsBuilder
213204
.fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION + "/network-area-diagram/configs")
@@ -268,4 +259,21 @@ public UUID duplicateNadConfig(UUID sourceNadConfigUuid) {
268259
throw handleHttpError(e, DUPLICATE_DIAGRAM_GRID_LAYOUT_FAILED);
269260
}
270261
}
262+
263+
public void createNadPositionsConfigFromCsv(MultipartFile file) {
264+
var path = UriComponentsBuilder.fromPath(DELIMITER + SINGLE_LINE_DIAGRAM_API_VERSION +
265+
"/network-area-diagram/config/positions").buildAndExpand()
266+
.toUriString();
267+
268+
HttpHeaders headers = new HttpHeaders();
269+
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
270+
271+
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
272+
body.add("file_name", file.getOriginalFilename());
273+
body.add("file", file.getResource());
274+
275+
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
276+
277+
restTemplate.exchange(singleLineDiagramServerBaseUri + path, HttpMethod.POST, requestEntity, Void.class);
278+
}
271279
}

src/main/java/org/gridsuite/study/server/service/StudyConfigService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
import org.springframework.web.client.RestTemplate;
2424
import org.springframework.web.util.UriComponentsBuilder;
2525

26-
import java.util.Collections;
27-
import java.util.List;
28-
import java.util.Objects;
29-
import java.util.UUID;
26+
import java.util.*;
3027

3128
import static org.gridsuite.study.server.StudyConstants.DELIMITER;
3229
import static org.gridsuite.study.server.StudyConstants.STUDY_CONFIG_API_VERSION;

src/main/java/org/gridsuite/study/server/service/StudyService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.springframework.stereotype.Service;
7171
import org.springframework.transaction.annotation.Transactional;
7272
import org.springframework.web.client.HttpStatusCodeException;
73+
import org.springframework.web.multipart.MultipartFile;
7374

7475
import java.io.UncheckedIOException;
7576
import java.net.URLEncoder;
@@ -82,7 +83,7 @@
8283
import java.util.stream.Collectors;
8384
import java.util.stream.Stream;
8485

85-
import static org.gridsuite.study.server.StudyConstants.DYNA_FLOW_PROVIDER;
86+
import static org.gridsuite.study.server.StudyConstants.*;
8687
import static org.gridsuite.study.server.StudyException.Type.*;
8788
import static org.gridsuite.study.server.dto.ComputationType.*;
8889
import static org.gridsuite.study.server.dto.InvalidateNodeTreeParameters.ALL_WITH_BLOCK_NODES;
@@ -3462,4 +3463,9 @@ public UUID saveDiagramGridLayout(UUID studyUuid, DiagramGridLayout diagramGridL
34623463
private void removeDiagramGridLayout(@Nullable UUID diagramGridLayoutUuid) {
34633464
diagramGridLayoutService.removeDiagramGridLayout(diagramGridLayoutUuid);
34643465
}
3466+
3467+
@Transactional
3468+
public void createNadPositionsConfigFromCsv(MultipartFile file) {
3469+
singleLineDiagramService.createNadPositionsConfigFromCsv(file);
3470+
}
34653471
}

src/test/java/org/gridsuite/study/server/LoadFlowTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class LoadFlowTest {
145145
private static final String LOADFLOW_RESULT_DESTINATION = "loadflow.result";
146146
private static final String LOADFLOW_STOPPED_DESTINATION = "loadflow.stopped";
147147
private static final String LOADFLOW_FAILED_DESTINATION = "loadflow.run.dlx";
148+
private static final String LOADFLOW_MODIFICATIONS = "loadflow modifications mock";
148149

149150
@Autowired
150151
private MockMvc mockMvc;
@@ -274,6 +275,10 @@ public MockResponse dispatch(RecordedRequest request) {
274275
return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), COMPUTING_STATUS_JSON);
275276
} else if (path.matches("/v1/results/" + LOADFLOW_RESULT_UUID + "/computation")) {
276277
return new MockResponse(404);
278+
} else if (path.matches("/v1/results/" + LOADFLOW_RESULT_UUID + "/modifications")) {
279+
return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), "loadflow modifications mock");
280+
} else if (path.matches("/v1/results/" + LOADFLOW_ERROR_RESULT_UUID + "/modifications")) {
281+
return new MockResponse(404);
277282
} else if (path.matches("/v1/results/invalidate-status\\?resultUuid=" + LOADFLOW_RESULT_UUID)) {
278283
return new MockResponse(200);
279284
} else if (path.matches("/v1/results/invalidate-status\\?resultUuid=" + LOADFLOW_RESULT_UUID + "&resultUuid=" + LOADFLOW_OTHER_NODE_RESULT_UUID)) {
@@ -958,6 +963,42 @@ void testInvalidateNodesAfterLoadflow(final MockWebServer server) throws Excepti
958963
assertEquals(NodeBuildStatusEmbeddable.from(BuildStatus.NOT_BUILT), rootNetworkNodeInfoService.getRootNetworkNodeInfo(node3.getId(), rootNetworkUuid).map(RootNetworkNodeInfoEntity::getNodeBuildStatus).orElseThrow());
959964
}
960965

966+
@Test
967+
void testGetLoadFlowModification(final MockWebServer server) throws Exception {
968+
StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_LOADFLOW_UUID, LOADFLOW_PARAMETERS_UUID);
969+
UUID studyUuid = studyEntity.getId();
970+
UUID rootNetworkUuid = studyTestUtils.getOneRootNetworkUuid(studyUuid);
971+
RootNode rootNode = getRootNode(studyUuid);
972+
NetworkModificationNode node1 = createNetworkModificationConstructionNode(studyUuid, rootNode.getId(), UUID.randomUUID(), VARIANT_ID, "N1");
973+
updateLoadflowResultUuid(node1.getId(), rootNetworkUuid, UUID.fromString(LOADFLOW_RESULT_UUID));
974+
975+
MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/loadflow/modifications", studyUuid, rootNetworkUuid, node1.getId()))
976+
.andExpect(status().isOk())
977+
.andReturn();
978+
979+
assertEquals(LOADFLOW_MODIFICATIONS, mvcResult.getResponse().getContentAsString());
980+
981+
assertRequestsDone(server, List.of("/v1/results/" + LOADFLOW_RESULT_UUID + "/modifications"));
982+
}
983+
984+
@Test
985+
void testGetLoadFlowModificationNotFound(final MockWebServer server) throws Exception {
986+
StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_LOADFLOW_UUID, LOADFLOW_PARAMETERS_UUID);
987+
UUID studyUuid = studyEntity.getId();
988+
UUID rootNetworkUuid = studyTestUtils.getOneRootNetworkUuid(studyUuid);
989+
RootNode rootNode = getRootNode(studyUuid);
990+
NetworkModificationNode node1 = createNetworkModificationConstructionNode(studyUuid, rootNode.getId(), UUID.randomUUID(), VARIANT_ID, "N1");
991+
992+
mockMvc.perform(get("/v1/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/loadflow/modifications", studyUuid, rootNetworkUuid, node1.getId()))
993+
.andExpect(status().isNotFound());
994+
995+
updateLoadflowResultUuid(node1.getId(), rootNetworkUuid, UUID.fromString(LOADFLOW_ERROR_RESULT_UUID));
996+
mockMvc.perform(get("/v1/studies/{studyUuid}/root-networks/{rootNetworkUuid}/nodes/{nodeUuid}/loadflow/modifications", studyUuid, rootNetworkUuid, node1.getId()))
997+
.andExpect(status().isNotFound());
998+
999+
assertRequestsDone(server, List.of("/v1/results/" + LOADFLOW_ERROR_RESULT_UUID + "/modifications"));
1000+
}
1001+
9611002
private void updateNodeBuildStatus(UUID nodeId, UUID rootNetworkUuid, BuildStatus buildStatus) {
9621003
RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = rootNetworkNodeInfoRepository.findByNodeInfoIdAndRootNetworkId(nodeId, rootNetworkUuid).orElseThrow();
9631004
rootNetworkNodeInfoEntity.setNodeBuildStatus(NodeBuildStatusEmbeddable.from(buildStatus));

0 commit comments

Comments
 (0)