diff --git a/pom.xml b/pom.xml
index b0adb2f4..4985bb7f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,6 +105,8 @@
org.gridsuite
gridsuite-filter
+
+ 1.9.0-SNAPSHOT
com.fasterxml.jackson.core
diff --git a/src/main/java/org/gridsuite/filter/server/FilterController.java b/src/main/java/org/gridsuite/filter/server/FilterController.java
index c6ef88e5..53318c21 100644
--- a/src/main/java/org/gridsuite/filter/server/FilterController.java
+++ b/src/main/java/org/gridsuite/filter/server/FilterController.java
@@ -14,7 +14,9 @@
import org.gridsuite.filter.AbstractFilter;
import org.gridsuite.filter.IFilterAttributes;
import org.gridsuite.filter.identifierlistfilter.FilterEquipments;
+import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables;
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes;
+import org.gridsuite.filter.server.dto.FilterAttributes;
import org.gridsuite.filter.server.dto.IdsByGroup;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
@@ -52,6 +54,13 @@ public ResponseEntity> getFilters() {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getFilters());
}
+ @GetMapping(value = "/filters/infos", produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(summary = "Get filters infos")
+ @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "All filters")})
+ public ResponseEntity> getFilters(@RequestParam List filterUuids, @RequestHeader String userId) {
+ return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getFiltersAttributes(filterUuids, userId));
+ }
+
@GetMapping(value = "/filters/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get filter by id")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter"),
@@ -192,6 +201,18 @@ public ResponseEntity> exportFilters(@RequestParam("ids")
.body(ret);
}
+ @GetMapping(value = "/filters/evaluate/identifiables", produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(summary = "Export matched identifiables elements to JSON format")
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "200", description = "The list of matched elements")
+ })
+ public ResponseEntity evaluateFilters(@RequestParam("ids") List ids,
+ @RequestParam(value = "networkUuid") UUID networkUuid,
+ @RequestParam(value = "variantUuid", required = false) String variantUuid) {
+ FilteredIdentifiables identifiableAttributes = service.evaluateFilters(ids, networkUuid, variantUuid);
+ return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(identifiableAttributes);
+ }
+
@PostMapping(value = "/filters/evaluate", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Export matched elements to JSON format")
@ApiResponses(value = {
diff --git a/src/main/java/org/gridsuite/filter/server/FilterService.java b/src/main/java/org/gridsuite/filter/server/FilterService.java
index 4f0914a3..da396e4b 100644
--- a/src/main/java/org/gridsuite/filter/server/FilterService.java
+++ b/src/main/java/org/gridsuite/filter/server/FilterService.java
@@ -16,6 +16,8 @@
import org.gridsuite.filter.IFilterAttributes;
import org.gridsuite.filter.identifierlistfilter.FilterEquipments;
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes;
+import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables;
+import org.gridsuite.filter.server.dto.FilterAttributes;
import org.gridsuite.filter.server.dto.IdsByGroup;
import org.gridsuite.filter.server.entities.AbstractFilterEntity;
import org.gridsuite.filter.server.repositories.FilterRepository;
@@ -24,6 +26,7 @@
import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy;
import org.gridsuite.filter.server.repositories.proxies.expertfiler.ExpertFilterRepositoryProxy;
import org.gridsuite.filter.server.repositories.proxies.identifierlistfilter.IdentifierListFilterRepositoryProxy;
+import org.gridsuite.filter.server.service.DirectoryService;
import org.gridsuite.filter.utils.FilterServiceUtils;
import org.gridsuite.filter.utils.FilterType;
import org.gridsuite.filter.utils.expertfilter.FilterCycleDetector;
@@ -54,15 +57,19 @@ public class FilterService {
private final NotificationService notificationService;
+ private final DirectoryService directoryService;
+
public FilterService(final IdentifierListFilterRepository identifierListFilterRepository,
final ExpertFilterRepository expertFilterRepository,
NetworkStoreService networkStoreService,
- NotificationService notificationService) {
+ NotificationService notificationService,
+ DirectoryService directoryService) {
filterRepositories.put(FilterType.IDENTIFIER_LIST.name(), new IdentifierListFilterRepositoryProxy(identifierListFilterRepository));
filterRepositories.put(FilterType.EXPERT.name(), new ExpertFilterRepositoryProxy(expertFilterRepository));
this.networkStoreService = networkStoreService;
this.notificationService = notificationService;
+ this.directoryService = directoryService;
}
public List getFilters() {
@@ -71,6 +78,16 @@ public List getFilters() {
.collect(Collectors.toList());
}
+ public List getFiltersAttributes(List filterUuids, String userId) {
+ List filterAttributes = filterRepositories.entrySet().stream()
+ .flatMap(entry -> entry.getValue().getFiltersAttributes(filterUuids))
+ .toList();
+ // call directory server to add name information
+ Map elementsName = directoryService.getElementsName(filterAttributes.stream().map(FilterAttributes::getId).toList(), userId);
+ filterAttributes.forEach(attribute -> attribute.setName(elementsName.get(attribute.getId())));
+ return filterAttributes;
+ }
+
@Transactional(readOnly = true)
public Optional getFilter(UUID id) {
return getFilterFromRepository(id);
@@ -249,6 +266,34 @@ public List evaluateFilter(AbstractFilter filter, UUID n
return getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader);
}
+ @Transactional(readOnly = true)
+ public FilteredIdentifiables evaluateFilters(List filters, UUID networkUuid, String variantId) {
+ FilteredIdentifiables filteredIdentifiables = new FilteredIdentifiables();
+ Map result = new TreeMap<>();
+ Map notFound = new TreeMap<>();
+ Network network = getNetwork(networkUuid, variantId);
+ filters.forEach((UUID filterUuid) -> {
+ Optional optFilter = getFilterFromRepository(filterUuid);
+ if (optFilter.isEmpty()) {
+ return;
+ }
+ AbstractFilter filter = optFilter.get();
+ Objects.requireNonNull(filter);
+ FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories);
+ FilteredIdentifiables filterIdentiables = filter.toFilteredIdentifiables(FilterServiceUtils.getIdentifiableAttributes(filter, network, filterLoader));
+
+ // unduplicate equipments and merge in common lists
+ if (filterIdentiables.getNotFoundIds() != null) {
+ filterIdentiables.getNotFoundIds().forEach(element -> notFound.put(element.getId(), element));
+ }
+ filterIdentiables.getEquipmentIds().forEach(element -> result.put(element.getId(), element));
+ }
+ );
+ filteredIdentifiables.setEquipmentIds(result.values().stream().toList());
+ filteredIdentifiables.setNotFoundIds(notFound.values().stream().toList());
+ return filteredIdentifiables;
+ }
+
@Transactional(readOnly = true)
public Optional> exportFilter(UUID id, UUID networkUuid, String variantId) {
Objects.requireNonNull(id);
diff --git a/src/main/java/org/gridsuite/filter/server/configs/RestTemplateConfig.java b/src/main/java/org/gridsuite/filter/server/configs/RestTemplateConfig.java
new file mode 100644
index 00000000..4b3c6fe8
--- /dev/null
+++ b/src/main/java/org/gridsuite/filter/server/configs/RestTemplateConfig.java
@@ -0,0 +1,22 @@
+/*
+ * 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.filter.server.configs;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig {
+
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+}
+
diff --git a/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java b/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java
index 5c93a764..a7fb46b2 100644
--- a/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java
+++ b/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java
@@ -30,6 +30,7 @@ public class FilterAttributes implements IFilterAttributes {
Date modificationDate;
FilterType type;
EquipmentType equipmentType;
+ String name;
public FilterAttributes(FilterMetadata filterMetadata, FilterType type, EquipmentType equipmentType) {
id = filterMetadata.getId();
diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java
index caf7676d..36fafd74 100644
--- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java
+++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java
@@ -72,6 +72,10 @@ public Stream getFiltersAttributes() {
return getRepository().getFiltersMetadata().stream().map(this::metadataToAttribute);
}
+ public Stream getFiltersAttributes(List ids) {
+ return getRepository().findFiltersMetaDataById(ids).stream().map(this::metadataToAttribute);
+ }
+
FilterAttributes metadataToAttribute(FilterMetadata f) {
return new FilterAttributes(f, getFilterType(), getEquipmentType(f.getId()));
}
diff --git a/src/main/java/org/gridsuite/filter/server/service/DirectoryService.java b/src/main/java/org/gridsuite/filter/server/service/DirectoryService.java
new file mode 100644
index 00000000..c65b75bc
--- /dev/null
+++ b/src/main/java/org/gridsuite/filter/server/service/DirectoryService.java
@@ -0,0 +1,67 @@
+/*
+ * 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.filter.server.service;
+
+import lombok.Getter;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.gridsuite.filter.utils.ElementAttributes;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@Service
+public class DirectoryService {
+ public static final String DELIMITER = "/";
+ public static final String DIRECTORY_API_VERSION = "v1";
+ public static final String ELEMENT_END_POINT_INFOS = "/elements";
+
+ @Getter
+ private final String baseUri;
+ private final RestTemplate restTemplate;
+
+ @Autowired
+ public DirectoryService(@Value("${gridsuite.services.directory-server.base-uri:http://directory-server/}") String baseUri,
+ RestTemplate restTemplate) {
+ this.baseUri = baseUri;
+ this.restTemplate = restTemplate;
+ }
+
+ public Map getElementsName(List ids, String userId) {
+ Map result = new HashMap<>();
+ String endPointUrl = getBaseUri() + DELIMITER + DIRECTORY_API_VERSION + ELEMENT_END_POINT_INFOS;
+ UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(endPointUrl);
+ uriComponentsBuilder.queryParam("ids", ids);
+ var uriComponent = uriComponentsBuilder.buildAndExpand();
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("userId", userId);
+
+ HttpEntity entity = new HttpEntity<>(headers);
+
+ List elementAttributes = restTemplate.exchange(uriComponent.toUriString(),
+ HttpMethod.GET, entity, new ParameterizedTypeReference>() { }).getBody();
+ if (elementAttributes != null) {
+ for (ElementAttributes elementAttribute : elementAttributes) {
+ result.put(elementAttribute.getElementUuid(), elementAttribute.getElementName());
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml
index 8d5a72ef..1ddc43bc 100644
--- a/src/main/resources/application-local.yaml
+++ b/src/main/resources/application-local.yaml
@@ -13,3 +13,8 @@ powsybl:
services:
network-store-server:
base-uri: http://localhost:8080
+
+gridsuite:
+ services:
+ directory-server:
+ base-uri: http://localhost:5026
diff --git a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java
index 983082e7..922cca4d 100644
--- a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java
+++ b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java
@@ -25,6 +25,7 @@
import org.gridsuite.filter.expertfilter.ExpertFilter;
import org.gridsuite.filter.expertfilter.expertrule.*;
import org.gridsuite.filter.identifierlistfilter.FilterEquipments;
+import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables;
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes;
import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter;
import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes;
@@ -421,6 +422,34 @@ private void checkIdentifiableAttributes(List identifiab
}
}
+ @Test
+ public void testEvaluateFilters() throws Exception {
+ UUID filterId = UUID.randomUUID();
+ ArrayList rules = new ArrayList<>();
+ EnumExpertRule country1Filter = EnumExpertRule.builder().field(FieldType.COUNTRY_1).operator(OperatorType.IN)
+ .values(new TreeSet<>(Set.of("FR"))).build();
+ rules.add(country1Filter);
+ CombinatorExpertRule parentRule = CombinatorExpertRule.builder().combinator(CombinatorType.AND).rules(rules).build();
+ ExpertFilter lineFilter = new ExpertFilter(filterId, new Date(), EquipmentType.LINE, parentRule);
+ insertFilter(filterId, lineFilter);
+
+ // Apply filter by calling endPoint
+ List filterIds = List.of(filterId.toString());
+ MultiValueMap params = new LinkedMultiValueMap<>();
+ params.addAll("ids", filterIds);
+ params.add("networkUuid", NETWORK_UUID.toString());
+ FilteredIdentifiables result = objectMapper.readValue(mvc.perform(get(URL_TEMPLATE + "/evaluate/identifiables")
+ .params(params).contentType(APPLICATION_JSON)).andExpect(status().isOk())
+ .andReturn().getResponse().getContentAsString(), new TypeReference<>() { });
+
+ List expected = new ArrayList<>();
+ expected.add(new IdentifiableAttributes("NHV1_NHV2_1", IdentifiableType.LINE, null));
+ expected.add(new IdentifiableAttributes("NHV1_NHV2_2", IdentifiableType.LINE, null));
+ assertTrue(expected.size() == result.getEquipmentIds().size()
+ && result.getEquipmentIds().containsAll(expected)
+ && expected.containsAll(result.getEquipmentIds()));
+ }
+
@Test
public void testExportFilters() throws Exception {
UUID filterId = UUID.randomUUID();