Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
60 changes: 59 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,28 @@ 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))
.collect(Collectors.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())));


if (filterAttributes.size() != filterUuids.size()) {
List<UUID> foundUuids = filterAttributes.stream().map(FilterAttributes::getId).toList();
List<UUID> notFoundUuids = filterUuids.stream().filter(f -> !foundUuids.contains(f)).toList();
notFoundUuids.forEach(uuid ->
{
FilterAttributes filterAttr = new FilterAttributes();
filterAttr.setId(uuid);
filterAttributes.add(filterAttr);
});
}
return filterAttributes;
}

@Transactional(readOnly = true)
public Optional<AbstractFilter> getFilter(UUID id) {
return getFilterFromRepository(id);
Expand Down Expand Up @@ -249,6 +278,35 @@ 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) {
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.notFoundIds() != null) {
filterIdentiables.notFoundIds().forEach(element -> notFound.put(element.getId(), element));
}

if (filterIdentiables.equipmentIds() != null) {
filterIdentiables.equipmentIds().forEach(element -> result.put(element.getId(), element));
}
}
);
return new FilteredIdentifiables(result.values().stream().toList(), notFound.values().stream().toList());
}

@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
@@ -0,0 +1,14 @@
/**
* 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.dto;

import java.util.UUID;

// partial class from ElementAttributes (Directory-server)
public record ElementAttributes(UUID elementUuid, String elementName) {
}
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.server.dto.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.elementUuid(), elementAttribute.elementName());
}
}

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.equipmentIds().size()
&& result.equipmentIds().containsAll(expected)
&& expected.containsAll(result.equipmentIds()));
}

@Test
public void testExportFilters() throws Exception {
UUID filterId = UUID.randomUUID();
Expand Down
Loading