Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 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
10 changes: 9 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@

<properties>
<gridsuite-dependencies.version>43.1.0</gridsuite-dependencies.version>

<!-- TODO gridsuite-filter.version remove when upgrading gridsuite dependencies -->
<gridsuite-filter.version>1.9.0</gridsuite-filter.version>
<string-template.version>4.3.1</string-template.version>
<liquibase-hibernate-package>org.gridsuite.filter.server</liquibase-hibernate-package>
<sonar.coverage.exclusions>**/migrations/**/*</sonar.coverage.exclusions>
Expand Down Expand Up @@ -105,6 +106,8 @@
<dependency>
<groupId>org.gridsuite</groupId>
<artifactId>gridsuite-filter</artifactId>
<!-- TODO : remove version when lib is released -->
<version>${gridsuite-filter.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down Expand Up @@ -218,6 +221,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-jetty12</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
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 = "Get filters infos of given ids")})
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
58 changes: 57 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,26 @@ 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(filterUuid -> !foundUuids.contains(filterUuid)).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 +276,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,26 @@
/*
* 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;

/**
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
*/

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* 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;

/**
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
*/

// 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,71 @@
/*
* 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;

/**
* @author Bassel El Cheikh <bassel.el-cheikh at rte-france.com>
*/

@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
Loading