Skip to content

Commit 6def29d

Browse files
authored
Add endpoint to process filters and return Identifiables attributes list (#167)
Signed-off-by: basseche <[email protected]>
1 parent abc3dff commit 6def29d

File tree

10 files changed

+325
-5
lines changed

10 files changed

+325
-5
lines changed

pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343

4444
<properties>
4545
<gridsuite-dependencies.version>43.1.0</gridsuite-dependencies.version>
46-
46+
<!-- TODO gridsuite-filter.version remove when upgrading gridsuite dependencies -->
47+
<gridsuite-filter.version>1.9.0</gridsuite-filter.version>
4748
<string-template.version>4.3.1</string-template.version>
4849
<liquibase-hibernate-package>org.gridsuite.filter.server</liquibase-hibernate-package>
4950
<sonar.coverage.exclusions>**/migrations/**/*</sonar.coverage.exclusions>
@@ -105,6 +106,7 @@
105106
<dependency>
106107
<groupId>org.gridsuite</groupId>
107108
<artifactId>gridsuite-filter</artifactId>
109+
<version>${gridsuite-filter.version}</version>
108110
</dependency>
109111
<dependency>
110112
<groupId>com.fasterxml.jackson.core</groupId>
@@ -218,6 +220,11 @@
218220
<artifactId>spring-boot-starter-test</artifactId>
219221
<scope>test</scope>
220222
</dependency>
223+
<dependency>
224+
<groupId>org.wiremock</groupId>
225+
<artifactId>wiremock-jetty12</artifactId>
226+
<scope>test</scope>
227+
</dependency>
221228
</dependencies>
222229

223230
</project>

src/main/java/org/gridsuite/filter/server/FilterController.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
import org.gridsuite.filter.AbstractFilter;
1515
import org.gridsuite.filter.IFilterAttributes;
1616
import org.gridsuite.filter.identifierlistfilter.FilterEquipments;
17+
import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables;
1718
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes;
19+
import org.gridsuite.filter.server.dto.FilterAttributes;
1820
import org.gridsuite.filter.server.dto.IdsByGroup;
1921
import org.springframework.context.annotation.ComponentScan;
2022
import org.springframework.http.MediaType;
@@ -52,6 +54,13 @@ public ResponseEntity<List<IFilterAttributes>> getFilters() {
5254
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getFilters());
5355
}
5456

57+
@GetMapping(value = "/filters/infos", produces = MediaType.APPLICATION_JSON_VALUE)
58+
@Operation(summary = "Get filters infos")
59+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Get filters infos of given ids")})
60+
public ResponseEntity<List<FilterAttributes>> getFilters(@RequestParam List<UUID> filterUuids, @RequestHeader String userId) {
61+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getFiltersAttributes(filterUuids, userId));
62+
}
63+
5564
@GetMapping(value = "/filters/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
5665
@Operation(summary = "Get filter by id")
5766
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter"),
@@ -192,6 +201,18 @@ public ResponseEntity<List<FilterEquipments>> exportFilters(@RequestParam("ids")
192201
.body(ret);
193202
}
194203

204+
@GetMapping(value = "/filters/evaluate/identifiables", produces = MediaType.APPLICATION_JSON_VALUE)
205+
@Operation(summary = "Export matched identifiables elements to JSON format")
206+
@ApiResponses(value = {
207+
@ApiResponse(responseCode = "200", description = "The list of matched elements")
208+
})
209+
public ResponseEntity<FilteredIdentifiables> evaluateFilters(@RequestParam("ids") List<UUID> ids,
210+
@RequestParam(value = "networkUuid") UUID networkUuid,
211+
@RequestParam(value = "variantUuid", required = false) String variantUuid) {
212+
FilteredIdentifiables identifiableAttributes = service.evaluateFilters(ids, networkUuid, variantUuid);
213+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(identifiableAttributes);
214+
}
215+
195216
@PostMapping(value = "/filters/evaluate", produces = MediaType.APPLICATION_JSON_VALUE)
196217
@Operation(summary = "Export matched elements to JSON format")
197218
@ApiResponses(value = {

src/main/java/org/gridsuite/filter/server/FilterService.java

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import org.gridsuite.filter.IFilterAttributes;
1717
import org.gridsuite.filter.identifierlistfilter.FilterEquipments;
1818
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes;
19+
import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables;
20+
import org.gridsuite.filter.server.dto.FilterAttributes;
1921
import org.gridsuite.filter.server.dto.IdsByGroup;
2022
import org.gridsuite.filter.server.entities.AbstractFilterEntity;
2123
import org.gridsuite.filter.server.repositories.FilterRepository;
@@ -24,6 +26,7 @@
2426
import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy;
2527
import org.gridsuite.filter.server.repositories.proxies.expertfiler.ExpertFilterRepositoryProxy;
2628
import org.gridsuite.filter.server.repositories.proxies.identifierlistfilter.IdentifierListFilterRepositoryProxy;
29+
import org.gridsuite.filter.server.service.DirectoryService;
2730
import org.gridsuite.filter.utils.FilterServiceUtils;
2831
import org.gridsuite.filter.utils.FilterType;
2932
import org.gridsuite.filter.utils.expertfilter.FilterCycleDetector;
@@ -54,15 +57,19 @@ public class FilterService {
5457

5558
private final NotificationService notificationService;
5659

60+
private final DirectoryService directoryService;
61+
5762
public FilterService(final IdentifierListFilterRepository identifierListFilterRepository,
5863
final ExpertFilterRepository expertFilterRepository,
5964
NetworkStoreService networkStoreService,
60-
NotificationService notificationService) {
65+
NotificationService notificationService,
66+
DirectoryService directoryService) {
6167
filterRepositories.put(FilterType.IDENTIFIER_LIST.name(), new IdentifierListFilterRepositoryProxy(identifierListFilterRepository));
6268

6369
filterRepositories.put(FilterType.EXPERT.name(), new ExpertFilterRepositoryProxy(expertFilterRepository));
6470
this.networkStoreService = networkStoreService;
6571
this.notificationService = notificationService;
72+
this.directoryService = directoryService;
6673
}
6774

6875
public List<IFilterAttributes> getFilters() {
@@ -71,6 +78,26 @@ public List<IFilterAttributes> getFilters() {
7178
.collect(Collectors.toList());
7279
}
7380

81+
public List<FilterAttributes> getFiltersAttributes(List<UUID> filterUuids, String userId) {
82+
List<FilterAttributes> filterAttributes = filterRepositories.entrySet().stream()
83+
.flatMap(entry -> entry.getValue().getFiltersAttributes(filterUuids))
84+
.collect(Collectors.toList());
85+
// call directory server to add name information
86+
Map<UUID, String> elementsName = directoryService.getElementsName(filterAttributes.stream().map(FilterAttributes::getId).toList(), userId);
87+
filterAttributes.forEach(attribute -> attribute.setName(elementsName.get(attribute.getId())));
88+
89+
if (filterAttributes.size() != filterUuids.size()) {
90+
List<UUID> foundUuids = filterAttributes.stream().map(FilterAttributes::getId).toList();
91+
List<UUID> notFoundUuids = filterUuids.stream().filter(filterUuid -> !foundUuids.contains(filterUuid)).toList();
92+
notFoundUuids.forEach(uuid -> {
93+
FilterAttributes filterAttr = new FilterAttributes();
94+
filterAttr.setId(uuid);
95+
filterAttributes.add(filterAttr);
96+
});
97+
}
98+
return filterAttributes;
99+
}
100+
74101
@Transactional(readOnly = true)
75102
public Optional<AbstractFilter> getFilter(UUID id) {
76103
return getFilterFromRepository(id);
@@ -249,6 +276,35 @@ public List<IdentifiableAttributes> evaluateFilter(AbstractFilter filter, UUID n
249276
return getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader);
250277
}
251278

279+
@Transactional(readOnly = true)
280+
public FilteredIdentifiables evaluateFilters(List<UUID> filters, UUID networkUuid, String variantId) {
281+
Map<String, IdentifiableAttributes> result = new TreeMap<>();
282+
Map<String, IdentifiableAttributes> notFound = new TreeMap<>();
283+
Network network = getNetwork(networkUuid, variantId);
284+
285+
filters.forEach((UUID filterUuid) -> {
286+
Optional<AbstractFilter> optFilter = getFilterFromRepository(filterUuid);
287+
if (optFilter.isEmpty()) {
288+
return;
289+
}
290+
AbstractFilter filter = optFilter.get();
291+
Objects.requireNonNull(filter);
292+
FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories);
293+
FilteredIdentifiables filterIdentiables = filter.toFilteredIdentifiables(FilterServiceUtils.getIdentifiableAttributes(filter, network, filterLoader));
294+
295+
// unduplicate equipments and merge in common lists
296+
if (filterIdentiables.notFoundIds() != null) {
297+
filterIdentiables.notFoundIds().forEach(element -> notFound.put(element.getId(), element));
298+
}
299+
300+
if (filterIdentiables.equipmentIds() != null) {
301+
filterIdentiables.equipmentIds().forEach(element -> result.put(element.getId(), element));
302+
}
303+
}
304+
);
305+
return new FilteredIdentifiables(result.values().stream().toList(), notFound.values().stream().toList());
306+
}
307+
252308
@Transactional(readOnly = true)
253309
public Optional<List<IdentifiableAttributes>> exportFilter(UUID id, UUID networkUuid, String variantId) {
254310
Objects.requireNonNull(id);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
package org.gridsuite.filter.server.configs;
9+
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.web.client.RestTemplate;
13+
14+
/**
15+
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
16+
*/
17+
18+
@Configuration
19+
public class RestTemplateConfig {
20+
21+
@Bean
22+
public RestTemplate restTemplate() {
23+
return new RestTemplate();
24+
}
25+
}
26+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
package org.gridsuite.filter.server.dto;
9+
10+
import java.util.UUID;
11+
12+
/**
13+
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
14+
*/
15+
16+
// partial class from ElementAttributes (Directory-server)
17+
public record ElementAttributes(UUID elementUuid, String elementName) {
18+
}

src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class FilterAttributes implements IFilterAttributes {
3030
Date modificationDate;
3131
FilterType type;
3232
EquipmentType equipmentType;
33+
String name;
3334

3435
public FilterAttributes(FilterMetadata filterMetadata, FilterType type, EquipmentType equipmentType) {
3536
id = filterMetadata.getId();

src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public Stream<FilterAttributes> getFiltersAttributes() {
7272
return getRepository().getFiltersMetadata().stream().map(this::metadataToAttribute);
7373
}
7474

75+
public Stream<FilterAttributes> getFiltersAttributes(List<UUID> ids) {
76+
return getRepository().findFiltersMetaDataById(ids).stream().map(this::metadataToAttribute);
77+
}
78+
7579
FilterAttributes metadataToAttribute(FilterMetadata f) {
7680
return new FilterAttributes(f, getFilterType(), getEquipmentType(f.getId()));
7781
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
package org.gridsuite.filter.server.service;
9+
10+
import lombok.Getter;
11+
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.beans.factory.annotation.Value;
14+
import org.springframework.core.ParameterizedTypeReference;
15+
import org.springframework.http.HttpEntity;
16+
import org.springframework.http.HttpHeaders;
17+
import org.springframework.http.HttpMethod;
18+
import org.springframework.stereotype.Service;
19+
import org.springframework.web.client.RestTemplate;
20+
import org.springframework.web.util.UriComponentsBuilder;
21+
import org.gridsuite.filter.server.dto.ElementAttributes;
22+
23+
import java.util.HashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
import java.util.UUID;
27+
28+
/**
29+
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
30+
*/
31+
32+
@Service
33+
public class DirectoryService {
34+
public static final String DELIMITER = "/";
35+
public static final String DIRECTORY_API_VERSION = "v1";
36+
public static final String ELEMENT_END_POINT_INFOS = "/elements";
37+
38+
@Getter
39+
private final String baseUri;
40+
private final RestTemplate restTemplate;
41+
42+
@Autowired
43+
public DirectoryService(@Value("${gridsuite.services.directory-server.base-uri:http://directory-server/}") String baseUri,
44+
RestTemplate restTemplate) {
45+
this.baseUri = baseUri;
46+
this.restTemplate = restTemplate;
47+
}
48+
49+
public Map<UUID, String> getElementsName(List<UUID> ids, String userId) {
50+
Map<UUID, String> result = new HashMap<>();
51+
String endPointUrl = getBaseUri() + DELIMITER + DIRECTORY_API_VERSION + ELEMENT_END_POINT_INFOS;
52+
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(endPointUrl);
53+
uriComponentsBuilder.queryParam("ids", ids);
54+
var uriComponent = uriComponentsBuilder.buildAndExpand();
55+
56+
HttpHeaders headers = new HttpHeaders();
57+
headers.set("userId", userId);
58+
59+
HttpEntity<String> entity = new HttpEntity<>(headers);
60+
61+
List<ElementAttributes> elementAttributes = restTemplate.exchange(uriComponent.toUriString(),
62+
HttpMethod.GET, entity, new ParameterizedTypeReference<List<ElementAttributes>>() { }).getBody();
63+
if (elementAttributes != null) {
64+
for (ElementAttributes elementAttribute : elementAttributes) {
65+
result.put(elementAttribute.elementUuid(), elementAttribute.elementName());
66+
}
67+
}
68+
69+
return result;
70+
}
71+
}

src/main/resources/application-local.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ powsybl:
1313
services:
1414
network-store-server:
1515
base-uri: http://localhost:8080
16+
17+
gridsuite:
18+
services:
19+
directory-server:
20+
base-uri: http://localhost:5026

0 commit comments

Comments
 (0)