Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,17 @@ public ResponseEntity<List<NodeInfos>> getNodesInfos(
.body(networkModificationTreeService.getNodesInfos(nodeUuids));
}

@GetMapping(value = "/nodes/uuids-by-network-modification", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "For each given network modification, find the study node whose modification group ultimately contains it")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Network modification uuid -> node uuid, unresolved modifications are omitted"),
})
public ResponseEntity<Map<UUID, UUID>> getNodeUuidsByNetworkModification(
@Parameter(description = "Network modification UUIDs") @RequestParam("uuids") List<UUID> networkModificationUuids) {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON)
.body(studyService.getNodeUuidsByNetworkModifications(networkModificationUuids));
}

@PostMapping(value = "/studies/{studyUuid}/tree/nodes/{id}")
@Operation(summary = "Create a node as before / after the given node ID")
@ApiResponses(value = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,31 @@ public Map<UUID, UUID> findParentComposites(List<UUID> modificationsUuids) {
).getBody();
}

/**
* @return modification uuid -> uuid of the top-level group ultimately containing it, walking up through as
* many nested composite modifications as needed; modifications not reachable from any group have no entry
*/
public Map<UUID, UUID> findRootGroups(List<UUID> modificationsUuids) {
Objects.requireNonNull(modificationsUuids);
var path = UriComponentsBuilder
.fromUriString(getNetworkModificationServerURI(false) + COMPOSITE_PATH + "root-groups")
.queryParam(UUIDS, modificationsUuids)
.buildAndExpand()
.toUriString();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<Void> httpEntity = new HttpEntity<>(headers);

return restTemplate.exchange(
path,
HttpMethod.GET,
httpEntity,
new ParameterizedTypeReference<Map<UUID, UUID>>() { }
).getBody();
}

/**
* @return references data of the modifications in the group :
* - element uuid in directory server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1460,4 +1460,10 @@ public UUID getNodeUuidByModificationGroup(UUID groupUuid) {
var node = networkModificationNodeInfoRepository.findByModificationGroupUuidIn(List.of(groupUuid));
return node.isEmpty() ? null : node.getFirst().getIdNode();
}

@Transactional(readOnly = true)
public Map<UUID, UUID> getNodeUuidsByModificationGroups(List<UUID> groupUuids) {
return networkModificationNodeInfoRepository.findByModificationGroupUuidIn(groupUuids).stream()
.collect(Collectors.toMap(NetworkModificationNodeInfoEntity::getModificationGroupUuid, NetworkModificationNodeInfoEntity::getIdNode));
}
}
19 changes: 19 additions & 0 deletions src/main/java/org/gridsuite/study/server/service/StudyService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,25 @@ private RootNetworkExportInfos toRootNetworkExportInfos(RootNetworkInfos rootNet
);
}

/**
* For each given network modification, find the study node whose modification group ultimately contains it
* (walking up through as many nested composite modifications as needed).
*
* @return network modification uuid -> node uuid; modifications not reachable from any node's modification
* group are omitted
*/
public Map<UUID, UUID> getNodeUuidsByNetworkModifications(List<UUID> networkModificationUuids) {
Map<UUID, UUID> rootGroupByModification = networkModificationService.findRootGroups(networkModificationUuids);
if (rootGroupByModification.isEmpty()) {
return Map.of();
}
Map<UUID, UUID> nodeByGroup = networkModificationTreeService.getNodeUuidsByModificationGroups(
rootGroupByModification.values().stream().distinct().toList());
return rootGroupByModification.entrySet().stream()
.filter(entry -> nodeByGroup.containsKey(entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, entry -> nodeByGroup.get(entry.getValue())));
}

private NodeTreeExportInfos toNodeTreeExportInfos(AbstractNode node) {
List<NodeTreeExportInfos> children = CollectionUtils.emptyIfNull(node.getChildren()).stream().map(this::toNodeTreeExportInfos).toList();
UUID modificationGroupUuid = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -122,4 +127,21 @@ void testUpdateNetworkModificationsMetadata() {

verify(restTemplate).exchange(eq(expectedUrl), eq(HttpMethod.PUT), org.mockito.ArgumentMatchers.<HttpEntity<String>>any(), eq(Void.class));
}

@Test
void testFindRootGroups() {
UUID firstUuid = UUID.randomUUID();
UUID secondUuid = UUID.randomUUID();
UUID groupUuid = UUID.randomUUID();
String expectedUrl = NETWORK_MODIFICATION_SERVER_URI + "/v1/network-composite-modifications/root-groups?uuids=" + firstUuid + "&uuids=" + secondUuid;
Map<UUID, UUID> expected = Map.of(firstUuid, groupUuid, secondUuid, groupUuid);
when(restTemplate.exchange(
eq(expectedUrl),
eq(HttpMethod.GET),
any(HttpEntity.class),
Mockito.<ParameterizedTypeReference<Map<UUID, UUID>>>any()))
.thenReturn(ResponseEntity.ok(expected));

assertThat(networkModificationService.findRootGroups(List.of(firstUuid, secondUuid))).isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.gridsuite.study.server.notification.NotificationService;
import org.gridsuite.study.server.utils.MatcherReportLog;
import org.gridsuite.study.server.utils.TestUtils;
import org.gridsuite.study.server.utils.wiremock.WireMockUtils;
import org.junit.jupiter.api.Test;
import org.springframework.data.util.Pair;
import org.springframework.http.HttpHeaders;
Expand Down Expand Up @@ -1102,4 +1103,33 @@ void testGetNodesInfos() throws Exception {
assertEquals(new NodeInfos(node1.getId(), "node1", study1Uuid), infosByNodeUuid.get(node1.getId()));
assertEquals(new NodeInfos(node2.getId(), "node2", study2Uuid), infosByNodeUuid.get(node2.getId()));
}

@Test
void testGetNodeUuidsByNetworkModification() throws Exception {
String userId = "userId";
UUID studyUuid = createStudyWithStubs(userId, CASE_UUID);
UUID rootUuid = networkModificationTreeService.getStudyTree(studyUuid, null).getId();
UUID modificationGroupUuid = UUID.randomUUID();
NetworkModificationNode node = createNetworkModificationNode(studyUuid, rootUuid, modificationGroupUuid, VARIANT_ID, "node", userId);

UUID modificationInNodeUuid = UUID.randomUUID();
UUID unresolvedModificationUuid = UUID.randomUUID();

// the network-modification-server walks a modification up to its top-level group
UUID rootGroupsStubId = wireMockServer.stubFor(WireMock.get(WireMock.urlPathEqualTo("/v1/network-composite-modifications/root-groups"))
.willReturn(WireMock.ok(mapper.writeValueAsString(Map.of(modificationInNodeUuid, modificationGroupUuid)))
.withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE))).getId();

MvcResult result = mockMvc.perform(get("/v1/nodes/uuids-by-network-modification")
.param("uuids", modificationInNodeUuid.toString(), unresolvedModificationUuid.toString()))
.andExpect(status().isOk())
.andReturn();

Map<UUID, UUID> nodeUuidByModification = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { });

// the modification sitting in the node's modification group resolves to that node; the other is omitted
assertEquals(Map.of(modificationInNodeUuid, node.getId()), nodeUuidByModification);

WireMockUtils.verifyGetRequest(wireMockServer, rootGroupsStubId, "/v1/network-composite-modifications/root-groups", Map.of());
}
}
Loading