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
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
<dependency>
<groupId>org.gridsuite</groupId>
<artifactId>gridsuite-filter</artifactId>
<!-- TODO : remove version when lib is released -->
<version>1.9.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/org/gridsuite/filter/server/FilterController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -52,6 +54,13 @@ public ResponseEntity<List<IFilterAttributes>> 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<List<FilterAttributes>> getFilters(@RequestParam List<UUID> 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"),
Expand Down Expand Up @@ -192,6 +201,18 @@ public ResponseEntity<List<FilterEquipments>> 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<FilteredIdentifiables> evaluateFilters(@RequestParam("ids") List<UUID> 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 = {
Expand Down
47 changes: 46 additions & 1 deletion src/main/java/org/gridsuite/filter/server/FilterService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<IFilterAttributes> getFilters() {
Expand All @@ -71,6 +78,16 @@ public List<IFilterAttributes> getFilters() {
.collect(Collectors.toList());
}

public List<FilterAttributes> getFiltersAttributes(List<UUID> filterUuids, String userId) {
List<FilterAttributes> filterAttributes = filterRepositories.entrySet().stream()
.flatMap(entry -> entry.getValue().getFiltersAttributes(filterUuids))
.toList();
// call directory server to add name information
Map<UUID, String> 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<AbstractFilter> getFilter(UUID id) {
return getFilterFromRepository(id);
Expand Down Expand Up @@ -249,6 +266,34 @@ public List<IdentifiableAttributes> evaluateFilter(AbstractFilter filter, UUID n
return getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader);
}

@Transactional(readOnly = true)
public FilteredIdentifiables evaluateFilters(List<UUID> filters, UUID networkUuid, String variantId) {
FilteredIdentifiables filteredIdentifiables = new FilteredIdentifiables();
Map<String, IdentifiableAttributes> result = new TreeMap<>();
Map<String, IdentifiableAttributes> notFound = new TreeMap<>();
Network network = getNetwork(networkUuid, variantId);
filters.forEach((UUID filterUuid) -> {
Optional<AbstractFilter> 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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would implement the same safety than upper

}
);
filteredIdentifiables.setEquipmentIds(result.values().stream().toList());
filteredIdentifiables.setNotFoundIds(notFound.values().stream().toList());
return filteredIdentifiables;
}

@Transactional(readOnly = true)
public Optional<List<IdentifiableAttributes>> exportFilter(UUID id, UUID networkUuid, String variantId) {
Objects.requireNonNull(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public Stream<FilterAttributes> getFiltersAttributes() {
return getRepository().getFiltersMetadata().stream().map(this::metadataToAttribute);
}

public Stream<FilterAttributes> getFiltersAttributes(List<UUID> ids) {
return getRepository().findFiltersMetaDataById(ids).stream().map(this::metadataToAttribute);
}

FilterAttributes metadataToAttribute(FilterMetadata f) {
return new FilterAttributes(f, getFilterType(), getEquipmentType(f.getId()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<UUID, String> getElementsName(List<UUID> ids, String userId) {
Map<UUID, String> 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<String> entity = new HttpEntity<>(headers);

List<ElementAttributes> elementAttributes = restTemplate.exchange(uriComponent.toUriString(),
HttpMethod.GET, entity, new ParameterizedTypeReference<List<ElementAttributes>>() { }).getBody();
if (elementAttributes != null) {
for (ElementAttributes elementAttribute : elementAttributes) {
result.put(elementAttribute.getElementUuid(), elementAttribute.getElementName());
}
}

return result;
}
}
5 changes: 5 additions & 0 deletions src/main/resources/application-local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ powsybl:
services:
network-store-server:
base-uri: http://localhost:8080

gridsuite:
services:
directory-server:
base-uri: http://localhost:5026
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -421,6 +422,34 @@ private void checkIdentifiableAttributes(List<IdentifiableAttributes> identifiab
}
}

@Test
public void testEvaluateFilters() throws Exception {
UUID filterId = UUID.randomUUID();
ArrayList<AbstractExpertRule> 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<String> filterIds = List.of(filterId.toString());
MultiValueMap<String, String> 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<IdentifiableAttributes> 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();
Expand Down
Loading