diff --git a/pom.xml b/pom.xml index 3a689f32..dd8c892f 100644 --- a/pom.xml +++ b/pom.xml @@ -107,6 +107,10 @@ + + org.gridsuite + gridsuite-actions + org.gridsuite gridsuite-filter diff --git a/src/main/java/org/gridsuite/actions/server/ContingencyListController.java b/src/main/java/org/gridsuite/actions/server/ContingencyListController.java index 31d62bc2..9d2291d5 100644 --- a/src/main/java/org/gridsuite/actions/server/ContingencyListController.java +++ b/src/main/java/org/gridsuite/actions/server/ContingencyListController.java @@ -11,7 +11,13 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import org.gridsuite.actions.server.dto.*; +import org.gridsuite.actions.dto.*; +import org.gridsuite.actions.dto.contingency.FilterBasedContingencyList; +import org.gridsuite.actions.dto.contingency.IdBasedContingencyList; +import org.gridsuite.actions.dto.contingency.PersistentContingencyList; +import org.gridsuite.actions.dto.evaluation.ContingencyIdsByGroup; +import org.gridsuite.actions.dto.evaluation.ContingencyInfos; +import org.gridsuite.actions.dto.evaluation.ContingencyListExportResult; import org.springframework.context.annotation.ComponentScan; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.MediaType; diff --git a/src/main/java/org/gridsuite/actions/server/ContingencyListService.java b/src/main/java/org/gridsuite/actions/server/ContingencyListService.java index cd85191c..462a603d 100644 --- a/src/main/java/org/gridsuite/actions/server/ContingencyListService.java +++ b/src/main/java/org/gridsuite/actions/server/ContingencyListService.java @@ -8,26 +8,27 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.contingency.Contingency; -import com.powsybl.contingency.ContingencyElement; -import com.powsybl.contingency.list.ContingencyList; import com.powsybl.contingency.list.IdentifierContingencyList; -import com.powsybl.iidm.network.Connectable; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.Terminal; import com.powsybl.iidm.network.identifiers.IdBasedNetworkElementIdentifier; import com.powsybl.iidm.network.identifiers.NetworkElementIdentifier; import com.powsybl.iidm.network.identifiers.NetworkElementIdentifierContingencyList; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; -import org.gridsuite.actions.server.dto.*; +import org.gridsuite.actions.ContingencyListEvaluator; +import org.gridsuite.actions.dto.*; +import org.gridsuite.actions.dto.contingency.FilterBasedContingencyList; +import org.gridsuite.actions.dto.contingency.IdBasedContingencyList; +import org.gridsuite.actions.dto.contingency.PersistentContingencyList; +import org.gridsuite.actions.dto.evaluation.ContingencyIdsByGroup; +import org.gridsuite.actions.dto.evaluation.ContingencyInfos; +import org.gridsuite.actions.dto.evaluation.ContingencyListExportResult; import org.gridsuite.actions.server.entities.*; import org.gridsuite.actions.server.repositories.FilterBasedContingencyListRepository; import org.gridsuite.actions.server.repositories.IdBasedContingencyListRepository; import org.gridsuite.actions.server.service.FilterService; -import org.gridsuite.actions.server.utils.ContingencyListType; -import org.gridsuite.actions.server.utils.ContingencyListUtils; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; +import org.gridsuite.actions.utils.ContingencyListType; import org.springframework.context.annotation.ComponentScan; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.HttpStatus; @@ -58,16 +59,20 @@ public class ContingencyListService { private final FilterService filterService; + private final ContingencyListEvaluator contingencyListEvaluator; + public ContingencyListService(IdBasedContingencyListRepository idBasedContingencyListRepository, FilterBasedContingencyListRepository filterBasedContingencyListRepository, NetworkStoreService networkStoreService, NotificationService notificationService, - FilterService filterService) { + FilterService filterService, + ContingencyListEvaluator contingencyListEvaluator) { this.idBasedContingencyListRepository = idBasedContingencyListRepository; this.filterBasedContingencyListRepository = filterBasedContingencyListRepository; this.networkStoreService = networkStoreService; this.notificationService = notificationService; this.filterService = filterService; + this.contingencyListEvaluator = contingencyListEvaluator; } ContingencyListMetadata fromContingencyListEntity(AbstractContingencyEntity entity, ContingencyListType type) { @@ -92,10 +97,6 @@ List getContingencyListsMetadata(List ids) { ).flatMap(Function.identity()).collect(Collectors.toList()); } - public List evaluateFiltersNetwork(UUID networkUuid, String variantUuid, FilterBasedContingencyList filterBasedContingencyList) { - return filterService.evaluateFilters(networkUuid, variantUuid, filterBasedContingencyList); - } - @Transactional(readOnly = true) public Optional getIdBasedContingencyList(UUID id, Network network) { return doGetIdBasedContingencyList(id, network); @@ -133,27 +134,11 @@ private Optional doGetFilterBasedContingencyLi return filterBasedContingencyListRepository.findById(id); } - private List getPowsyblContingencies(PersistentContingencyList contingencyList, Network network, UUID networkUuid, String variantUuid) { - ContingencyList powsyblContingencyList; - if (Objects.requireNonNull(contingencyList.getMetadata().getType()) == ContingencyListType.FILTERS) { - FilterBasedContingencyList filterBasedContingencyList = (FilterBasedContingencyList) contingencyList; - List identifiers = evaluateFiltersNetwork(networkUuid, variantUuid, filterBasedContingencyList); - powsyblContingencyList = ContingencyList.of(identifiers.stream() - .map(id -> - new Contingency(id.getId(), List.of(ContingencyListUtils.toContingencyElement(id)))) - .toArray(Contingency[]::new) - ); - } else { - powsyblContingencyList = contingencyList.toPowsyblContingencyList(network); - } - return powsyblContingencyList == null ? Collections.emptyList() : powsyblContingencyList.getContingencies(network); - } - - private Integer getContingencyCount(Network network, List ids, UUID networkUuid, String variantId) { + private Integer getContingencyCount(Network network, List ids) { return ids.stream() .map(uuid -> { Optional contingencyList = getAnyContingencyList(uuid, network); - return contingencyList.map(l -> getContingencies(l, network, networkUuid, variantId).size()).orElse(0); + return contingencyList.map(l -> getContingencies(l, network).size()).orElse(0); }) .reduce(0, Integer::sum); } @@ -163,14 +148,14 @@ public Map getContingencyCountByGroup(ContingencyIdsByGroup con Network network = getNetworkFromUuid(networkUuid, variantId); return contingencyIdsByGroup.getIds().entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, - e -> getContingencyCount(network, e.getValue(), networkUuid, variantId)) + e -> getContingencyCount(network, e.getValue())) ); } @Transactional(readOnly = true) public Integer getContingencyCount(List ids, UUID networkUuid, String variantId) { Network network = getNetworkFromUuid(networkUuid, variantId); - return getContingencyCount(network, ids, networkUuid, variantId); + return getContingencyCount(network, ids); } @Transactional(readOnly = true) @@ -182,15 +167,15 @@ public ContingencyListExportResult exportContingencyList(List contingencyL contingencyListIds.forEach(contingencyListId -> { Optional contingencyList = getAnyContingencyList(contingencyListId, network); contingencyList.ifPresentOrElse( - list -> contingencies.addAll(getContingencies(list, network, networkUuid, variantId)), + list -> contingencies.addAll(getContingencies(list, network)), () -> notFoundIds.add(contingencyListId) ); }); return new ContingencyListExportResult(contingencies, notFoundIds); } - private List getContingencies(PersistentContingencyList persistentContingencyList, Network network, UUID networkUuid, String variantId) { - return evaluateContingencyList(persistentContingencyList, network, networkUuid, variantId) + private List getContingencies(PersistentContingencyList persistentContingencyList, Network network) { + return contingencyListEvaluator.evaluateContingencyList(persistentContingencyList, network) .stream() .map(ContingencyInfos::getContingency) .filter(Objects::nonNull) @@ -200,7 +185,7 @@ private List getContingencies(PersistentContingencyList persistentC @Transactional(readOnly = true) public List exportContingencyInfosList(List ids, UUID networkUuid, String variantId) { Network network = getNetworkFromUuid(networkUuid, variantId); - return ids.stream().map(id -> evaluateContingencyList(findContingencyList(id, network), network, networkUuid, variantId)).flatMap(Collection::stream).toList(); + return ids.stream().map(id -> contingencyListEvaluator.evaluateContingencyList(findContingencyList(id, network), network)).flatMap(Collection::stream).toList(); } private PersistentContingencyList findContingencyList(UUID id, Network network) { @@ -214,47 +199,6 @@ private Optional getAnyContingencyList(UUID id, Netwo .or(() -> doGetFilterBasedContingencyList(id)); } - private List evaluateContingencyList(PersistentContingencyList persistentContingencyList, Network network, UUID networkUuid, String variantId) { - List contingencies = getPowsyblContingencies(persistentContingencyList, network, networkUuid, variantId); - Map> notFoundElements = persistentContingencyList.getNotFoundElements(network); - - // For a gridsuite contingency with all equipments not found the powsybl contingency is not created - List contingencyInfos = new ArrayList<>(); - notFoundElements.entrySet().stream() - .filter(stringSetEntry -> contingencies.stream().noneMatch(c -> c.getId().equals(stringSetEntry.getKey()))) - .map(stringSetEntry -> new ContingencyInfos(stringSetEntry.getKey(), null, stringSetEntry.getValue(), null)) - .forEach(contingencyInfos::add); - - contingencies.stream() - .map(contingency -> new ContingencyInfos(contingency.getId(), contingency, notFoundElements.get(contingency.getId()), getDisconnectedElements(contingency, network))) - .forEach(contingencyInfos::add); - - return contingencyInfos; - } - - private Set getDisconnectedElements(Contingency contingency, Network network) { - return contingency.getElements().stream() - .filter(contingencyElement -> { - var connectable = network.getConnectable(contingencyElement.getId()); - return connectable != null && isDisconnected(connectable); - }) - .map(ContingencyElement::getId) - .collect(Collectors.toSet()); - } - - private boolean isDisconnected(Connectable connectable) { - List terminals = connectable.getTerminals(); - // check if the connectable are connected with terminal.isConnected() - boolean atleastOneIsConnected = false; - for (Terminal terminal : terminals) { - if (terminal != null && terminal.isConnected()) { - atleastOneIsConnected = true; - break; - } - } - return !atleastOneIsConnected; - } - private Network getNetworkFromUuid(UUID networkUuid, String variantId) { Network network; if (networkUuid == null) { diff --git a/src/main/java/org/gridsuite/actions/server/configs/ActionsConfig.java b/src/main/java/org/gridsuite/actions/server/configs/ActionsConfig.java new file mode 100644 index 00000000..3ae008d5 --- /dev/null +++ b/src/main/java/org/gridsuite/actions/server/configs/ActionsConfig.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2026, 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.actions.server.configs; + +import org.gridsuite.actions.ContingencyListEvaluator; +import org.gridsuite.actions.FilterProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Kevin Le Saulnier + */ +@Configuration +public class ActionsConfig { + @Bean + public ContingencyListEvaluator contingencyListEvaluator( + FilterProvider filterProvider + ) { + return new ContingencyListEvaluator(filterProvider); + } +} diff --git a/src/main/java/org/gridsuite/actions/server/dto/AbstractContingencyList.java b/src/main/java/org/gridsuite/actions/server/dto/AbstractContingencyList.java deleted file mode 100644 index f75f6bec..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/AbstractContingencyList.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2023, 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.actions.server.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.utils.ContingencyListType; - -import java.time.Instant; - -import java.util.UUID; - -/** - * @author Etienne Homer - */ -@Getter -@NoArgsConstructor -@AllArgsConstructor(access = AccessLevel.PROTECTED) -public abstract class AbstractContingencyList implements PersistentContingencyList { - - private ContingencyListMetadataImpl metadata; - - @Override public ContingencyListMetadata getMetadata() { - return metadata; - } - - public UUID getId() { - return metadata.getId(); - } - - public Instant getModificationDate() { - return metadata.getModificationDate(); - } - - public ContingencyListType getType() { - return metadata.getType(); - } -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/ContingencyIdsByGroup.java b/src/main/java/org/gridsuite/actions/server/dto/ContingencyIdsByGroup.java deleted file mode 100644 index ba35b242..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/ContingencyIdsByGroup.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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.actions.server.dto; - -import lombok.Builder; -import lombok.Data; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * @author Antoine Bouhours - */ -@Data -@Builder -public class ContingencyIdsByGroup { - Map> ids; -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/ContingencyInfos.java b/src/main/java/org/gridsuite/actions/server/dto/ContingencyInfos.java deleted file mode 100644 index eb172e52..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/ContingencyInfos.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2023, 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.actions.server.dto; - -import com.powsybl.contingency.Contingency; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.util.Set; - -/** - * @author Seddik Yengui - */ - -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ContingencyInfos { - private String id; - private Contingency contingency; - private Set notFoundElements; - private Set notConnectedElements; -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListExportResult.java b/src/main/java/org/gridsuite/actions/server/dto/ContingencyListExportResult.java deleted file mode 100644 index 879f2687..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListExportResult.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2024, 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.actions.server.dto; - -import com.powsybl.contingency.Contingency; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.UUID; - -/** - * @author Jamal KHEYYAD - */ -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Builder -public class ContingencyListExportResult { - List contingenciesFound; - List contingenciesNotFound; -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadata.java b/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadata.java deleted file mode 100644 index 623c079a..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadata.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (c) 2023, 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.actions.server.dto; - -import org.gridsuite.actions.server.utils.ContingencyListType; - -import java.time.Instant; -import java.util.UUID; - -/** - * @author Etienne Homer - */ -public interface ContingencyListMetadata { - - UUID getId(); - - Instant getModificationDate(); - - ContingencyListType getType(); -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadataImpl.java b/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadataImpl.java deleted file mode 100644 index 1a6526cc..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/ContingencyListMetadataImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2020, 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.actions.server.dto; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.utils.ContingencyListType; - -import java.time.Instant; -import java.util.UUID; - -/** - * @author Chamseddine benhamed - * @author Etienne Homer - */ -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Schema(description = "Contingency list infos") -public class ContingencyListMetadataImpl implements ContingencyListMetadata { - - @Schema(description = "List id") - private UUID id; - - @Schema(description = "List type") - private ContingencyListType type; - - @Schema(description = "Modification Date") - Instant modificationDate; - -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/EquipmentTypesByFilter.java b/src/main/java/org/gridsuite/actions/server/dto/EquipmentTypesByFilter.java deleted file mode 100644 index 64a8e687..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/EquipmentTypesByFilter.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * 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.actions.server.dto; - -import com.powsybl.iidm.network.IdentifiableType; -import org.gridsuite.actions.server.entities.EquipmentTypesByFilterEntity; - -import java.util.Set; -import java.util.UUID; - -/** - * Store a list of equipment types for a given filter ID - * - * @author Florent MILLOT - */ -public record EquipmentTypesByFilter(UUID filterId, Set equipmentTypes) { - public EquipmentTypesByFilterEntity toEntity() { - return new EquipmentTypesByFilterEntity(null, filterId, Set.copyOf(equipmentTypes)); - } -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/FilterAttributes.java b/src/main/java/org/gridsuite/actions/server/dto/FilterAttributes.java deleted file mode 100644 index 1534d555..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/FilterAttributes.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * 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.actions.server.dto; -import org.gridsuite.filter.utils.EquipmentType; - -import java.util.UUID; - -/** - * @author Bassel El Cheikh - */ - -// partial class from FilterAttributes (Filter-server) - -public record FilterAttributes(UUID id, EquipmentType equipmentType, String name) { -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/FilterBasedContingencyList.java b/src/main/java/org/gridsuite/actions/server/dto/FilterBasedContingencyList.java deleted file mode 100644 index 871dafbc..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/FilterBasedContingencyList.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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.actions.server.dto; - -import com.powsybl.contingency.list.ContingencyList; -import com.powsybl.iidm.network.Network; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.utils.ContingencyListType; - -import java.time.Instant; -import java.util.*; - -/** - * @author Bassel El Cheikh - */ - -@Getter -@NoArgsConstructor -@Schema(description = "filter based contingency list") -public class FilterBasedContingencyList extends AbstractContingencyList { - - @Schema(description = "filters list") - private List filters; - - @Schema(description = "Selected equipment types for substation and voltage level filter") - private List selectedEquipmentTypesByFilter; - - public FilterBasedContingencyList(UUID uuid, Instant date, List filtersId, List selectedEquipmentTypesByFilter) { - super(new ContingencyListMetadataImpl(uuid, ContingencyListType.FILTERS, date)); - this.filters = new ArrayList<>(); - this.filters.addAll(filtersId); - this.selectedEquipmentTypesByFilter = new ArrayList<>(); - this.selectedEquipmentTypesByFilter.addAll(selectedEquipmentTypesByFilter); - } - - @Override - public ContingencyList toPowsyblContingencyList(Network network) { - return null; - } - - @Override - public Map> getNotFoundElements(Network network) { - return Map.of(); - } -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/IdBasedContingencyList.java b/src/main/java/org/gridsuite/actions/server/dto/IdBasedContingencyList.java deleted file mode 100644 index 2be54cc1..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/IdBasedContingencyList.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2023, 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.actions.server.dto; - -import com.powsybl.contingency.list.ContingencyList; -import com.powsybl.contingency.list.IdentifierContingencyList; -import com.powsybl.iidm.network.Network; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.utils.ContingencyListType; - -import java.time.Instant; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * @author Etienne Homer - */ -@Getter -@NoArgsConstructor -@Schema(description = "Id based contingency list") -public class IdBasedContingencyList extends AbstractContingencyList { - - @Schema(description = "Identifier list") - private IdentifierContingencyList identifierContingencyList; - private Map> notFoundElements; - - public IdBasedContingencyList(UUID uuid, Instant date, IdentifierContingencyList identifierContingencyList) { - this(uuid, date, identifierContingencyList, Map.of()); - } - - public IdBasedContingencyList(UUID uuid, Instant date, IdentifierContingencyList identifierContingencyList, Map> notFoundElements) { - super(new ContingencyListMetadataImpl(uuid, ContingencyListType.IDENTIFIERS, date)); - this.identifierContingencyList = identifierContingencyList; - this.notFoundElements = notFoundElements; - } - - @Override - public ContingencyList toPowsyblContingencyList(Network network) { - return identifierContingencyList; - } - - //TODO this a temporary workaround to get elements not found in the network - // this should be deleted when a fix is added to powsybl - @Override - public Map> getNotFoundElements(Network network) { - return notFoundElements; - } -} diff --git a/src/main/java/org/gridsuite/actions/server/dto/NumericalFilter.java b/src/main/java/org/gridsuite/actions/server/dto/NumericalFilter.java index 34f69a76..68928566 100644 --- a/src/main/java/org/gridsuite/actions/server/dto/NumericalFilter.java +++ b/src/main/java/org/gridsuite/actions/server/dto/NumericalFilter.java @@ -8,7 +8,9 @@ import com.powsybl.iidm.criteria.SingleNominalVoltageCriterion; import com.powsybl.iidm.criteria.VoltageInterval; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; import org.gridsuite.actions.server.utils.NumericalFilterOperator; /** diff --git a/src/main/java/org/gridsuite/actions/server/dto/PersistentContingencyList.java b/src/main/java/org/gridsuite/actions/server/dto/PersistentContingencyList.java deleted file mode 100644 index 58885d21..00000000 --- a/src/main/java/org/gridsuite/actions/server/dto/PersistentContingencyList.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2023, 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.actions.server.dto; - -import com.powsybl.contingency.list.ContingencyList; -import com.powsybl.iidm.network.Network; - -import java.util.Map; -import java.util.Set; - -/** - * @author Etienne Homer - */ -public interface PersistentContingencyList { - ContingencyListMetadata getMetadata(); - - ContingencyList toPowsyblContingencyList(Network network); - - //TODO this a temporary workaround to get elements not found in the network - // this should be deleted when a fix is added to powsybl - Map> getNotFoundElements(Network network); -} diff --git a/src/main/java/org/gridsuite/actions/server/entities/EquipmentTypesByFilterEntity.java b/src/main/java/org/gridsuite/actions/server/entities/EquipmentTypesByFilterEntity.java index 18340873..fcf67d57 100644 --- a/src/main/java/org/gridsuite/actions/server/entities/EquipmentTypesByFilterEntity.java +++ b/src/main/java/org/gridsuite/actions/server/entities/EquipmentTypesByFilterEntity.java @@ -13,7 +13,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.dto.EquipmentTypesByFilter; +import org.gridsuite.actions.dto.EquipmentTypesByFilter; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; @@ -55,4 +55,7 @@ public EquipmentTypesByFilter toDto() { return new EquipmentTypesByFilter(filterId, equipmentTypes); } + public static EquipmentTypesByFilterEntity fromDto(EquipmentTypesByFilter equipmentTypesByFilter) { + return new EquipmentTypesByFilterEntity(null, equipmentTypesByFilter.filterId(), Set.copyOf(equipmentTypesByFilter.equipmentTypes())); + } } diff --git a/src/main/java/org/gridsuite/actions/server/entities/FilterBasedContingencyListEntity.java b/src/main/java/org/gridsuite/actions/server/entities/FilterBasedContingencyListEntity.java index c5b28646..a601a314 100644 --- a/src/main/java/org/gridsuite/actions/server/entities/FilterBasedContingencyListEntity.java +++ b/src/main/java/org/gridsuite/actions/server/entities/FilterBasedContingencyListEntity.java @@ -10,7 +10,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.gridsuite.actions.server.dto.FilterBasedContingencyList; +import org.gridsuite.actions.dto.contingency.FilterBasedContingencyList; import org.springframework.util.CollectionUtils; import java.util.ArrayList; @@ -53,14 +53,14 @@ private void init(FilterBasedContingencyList contingencyList) { filtersIds = new ArrayList<>(); contingencyList.getFilters().forEach(filterAttributes -> filtersIds.add(filterAttributes.id())); selectedEquipmentTypesByFilter = new ArrayList<>(); - contingencyList.getSelectedEquipmentTypesByFilter().forEach(equipmentTypesByElement -> selectedEquipmentTypesByFilter.add(equipmentTypesByElement.toEntity())); + contingencyList.getSelectedEquipmentTypesByFilter().forEach(equipmentTypesByElement -> selectedEquipmentTypesByFilter.add(EquipmentTypesByFilterEntity.fromDto(equipmentTypesByElement))); } public FilterBasedContingencyListEntity update(FilterBasedContingencyList contingencyList) { filtersIds.clear(); contingencyList.getFilters().forEach(filterAttributes -> filtersIds.add(filterAttributes.id())); selectedEquipmentTypesByFilter.clear(); - contingencyList.getSelectedEquipmentTypesByFilter().forEach(equipmentTypesByElement -> selectedEquipmentTypesByFilter.add(equipmentTypesByElement.toEntity())); + contingencyList.getSelectedEquipmentTypesByFilter().forEach(equipmentTypesByElement -> selectedEquipmentTypesByFilter.add(EquipmentTypesByFilterEntity.fromDto(equipmentTypesByElement))); return this; } } diff --git a/src/main/java/org/gridsuite/actions/server/entities/IdBasedContingencyListEntity.java b/src/main/java/org/gridsuite/actions/server/entities/IdBasedContingencyListEntity.java index 50a39a6c..cf15efd7 100644 --- a/src/main/java/org/gridsuite/actions/server/entities/IdBasedContingencyListEntity.java +++ b/src/main/java/org/gridsuite/actions/server/entities/IdBasedContingencyListEntity.java @@ -12,7 +12,7 @@ import com.powsybl.iidm.network.identifiers.NetworkElementIdentifierContingencyList; import lombok.Getter; import lombok.NoArgsConstructor; -import org.gridsuite.actions.server.dto.IdBasedContingencyList; +import org.gridsuite.actions.dto.contingency.IdBasedContingencyList; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; diff --git a/src/main/java/org/gridsuite/actions/server/service/DefaultFilterProvider.java b/src/main/java/org/gridsuite/actions/server/service/DefaultFilterProvider.java new file mode 100644 index 00000000..e979740c --- /dev/null +++ b/src/main/java/org/gridsuite/actions/server/service/DefaultFilterProvider.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2026, 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.actions.server.service; + +import org.gridsuite.actions.FilterProvider; +import org.gridsuite.filter.AbstractFilter; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +/** + * @author Kevin Le Saulnier + */ +@Service +public class DefaultFilterProvider implements FilterProvider { + + private final FilterService filterService; + + public DefaultFilterProvider(FilterService filterService) { + this.filterService = filterService; + } + + @Override + public List getFilters(List filtersUuids) { + return filterService.getFilters(filtersUuids); + } +} diff --git a/src/main/java/org/gridsuite/actions/server/service/FilterService.java b/src/main/java/org/gridsuite/actions/server/service/FilterService.java index 505edf13..5e38ab9e 100644 --- a/src/main/java/org/gridsuite/actions/server/service/FilterService.java +++ b/src/main/java/org/gridsuite/actions/server/service/FilterService.java @@ -8,10 +8,8 @@ package org.gridsuite.actions.server.service; import lombok.Getter; -import org.gridsuite.actions.server.dto.FilterAttributes; -import org.gridsuite.actions.server.dto.FilterBasedContingencyList; -import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; +import org.gridsuite.actions.dto.FilterAttributes; +import org.gridsuite.filter.AbstractFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -23,13 +21,13 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.UUID; +import java.util.stream.Collectors; @Service public class FilterService { - public static final String FILTER_END_POINT_EVALUATE_IDS = "/filters/evaluate/identifiables"; public static final String FILTER_END_POINT_INFOS_IDS = "/filters/infos"; + public static final String FILTER_END_POINT_METADATA = "/filters/metadata"; public static final String DELIMITER = "/"; public static final String FILTER_API_VERSION = "v1"; @@ -44,24 +42,6 @@ public FilterService(@Value("${gridsuite.services.filter-server.base-uri:http:// this.restTemplate = restTemplateBuilder.build(); } - public List evaluateFilters(UUID networkUuid, String variantUuid, FilterBasedContingencyList filterBasedContingencyList) { - Objects.requireNonNull(networkUuid); - Objects.requireNonNull(filterBasedContingencyList); - String endPointUrl = getBaseUri() + DELIMITER + FILTER_API_VERSION + FILTER_END_POINT_EVALUATE_IDS; - - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(endPointUrl); - uriComponentsBuilder.queryParam("networkUuid", networkUuid); - uriComponentsBuilder.queryParam("variantUuid", variantUuid); - var uriComponent = uriComponentsBuilder.buildAndExpand(); - - var headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity request = new HttpEntity<>(filterBasedContingencyList, headers); - - ResponseEntity response = restTemplate.postForEntity(uriComponent.toUriString(), request, FilteredIdentifiables.class); - return response.getBody() != null ? response.getBody().equipmentIds() : List.of(); - } - public List getFiltersAttributes(List filtersUuid, String userId) { if (filtersUuid.isEmpty()) { return new ArrayList<>(); @@ -75,8 +55,17 @@ public List getFiltersAttributes(List filtersUuid, Strin headers.set("userId", userId); HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity >response = restTemplate.exchange(uriComponent.toUriString(), + ResponseEntity> response = restTemplate.exchange(uriComponent.toUriString(), HttpMethod.GET, entity, new ParameterizedTypeReference<>() { }); return response.getBody() != null ? response.getBody() : new ArrayList<>(); } + + public List getFilters(List filtersUuids) { + var ids = !filtersUuids.isEmpty() ? "?ids=" + filtersUuids.stream().map(UUID::toString).collect(Collectors.joining(",")) : ""; + String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_API_VERSION + FILTER_END_POINT_METADATA + ids) + .buildAndExpand() + .toUriString(); + ResponseEntity> response = restTemplate.exchange(getBaseUri() + path, HttpMethod.GET, null, new ParameterizedTypeReference<>() { }); + return response.getBody() != null ? response.getBody() : new ArrayList<>(); + } } diff --git a/src/main/java/org/gridsuite/actions/server/utils/ContingencyListType.java b/src/main/java/org/gridsuite/actions/server/utils/ContingencyListType.java deleted file mode 100644 index f929bc19..00000000 --- a/src/main/java/org/gridsuite/actions/server/utils/ContingencyListType.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2020, 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.actions.server.utils; - -/** - * @author Chamseddine benhamed - */ - -public enum ContingencyListType { - IDENTIFIERS, - FILTERS -} diff --git a/src/main/java/org/gridsuite/actions/server/utils/ContingencyListUtils.java b/src/main/java/org/gridsuite/actions/server/utils/ContingencyListUtils.java deleted file mode 100644 index c7af1882..00000000 --- a/src/main/java/org/gridsuite/actions/server/utils/ContingencyListUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.gridsuite.actions.server.utils; - -import com.powsybl.contingency.*; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; - -/** - * @author Bassel El Cheikh - */ - -public final class ContingencyListUtils { - - private ContingencyListUtils() { - // Utility class no constructor - } - - public static ContingencyElement toContingencyElement(IdentifiableAttributes id) { - switch (id.getType()) { - case LINE -> { - return new LineContingency(id.getId()); - } - case TWO_WINDINGS_TRANSFORMER -> { - return new TwoWindingsTransformerContingency(id.getId()); - } - case THREE_WINDINGS_TRANSFORMER -> { - return new ThreeWindingsTransformerContingency(id.getId()); - } - case GENERATOR -> { - return new GeneratorContingency(id.getId()); - } - case BATTERY -> { - return new BatteryContingency(id.getId()); - } - case LOAD -> { - return new LoadContingency(id.getId()); - } - case SHUNT_COMPENSATOR -> { - return new ShuntCompensatorContingency(id.getId()); - } - case STATIC_VAR_COMPENSATOR -> { - return new StaticVarCompensatorContingency(id.getId()); - } - case HVDC_LINE -> { - return new HvdcLineContingency(id.getId()); - } - case DANGLING_LINE -> { - return new DanglingLineContingency(id.getId()); - } - case BUSBAR_SECTION -> { - return new BusbarSectionContingency(id.getId()); - } - default -> throw new IllegalStateException("Unexpected value: " + id.getType()); - } - } -} diff --git a/src/main/java/org/gridsuite/actions/server/utils/FiltersUtils.java b/src/main/java/org/gridsuite/actions/server/utils/FiltersUtils.java deleted file mode 100644 index b8e62047..00000000 --- a/src/main/java/org/gridsuite/actions/server/utils/FiltersUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2021, 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.actions.server.utils; - -import com.powsybl.iidm.network.*; -import org.apache.commons.collections4.CollectionUtils; -import java.util.List; -import java.util.Optional; - -/** - * @author Franck Lecuyer - */ -public final class FiltersUtils { - private FiltersUtils() { - throw new AssertionError("Utility class should not be instantiated"); - } - - // single country match - public static boolean injectionMatch(Terminal terminal, List countries) { - Optional country = terminal.getVoltageLevel().getSubstation().flatMap(Substation::getCountry); - return CollectionUtils.isEmpty(countries) || country.map(c -> countries.contains(c.name())).orElse(false); - } - - // crossed country match with 2 filters (countries and countries2) - private static boolean filterByCountries(Terminal terminal1, Terminal terminal2, List countries, List countries2) { - return - // terminal 1 matches filter 1 and terminal 2 matches filter 2 - injectionMatch(terminal1, countries) && - injectionMatch(terminal2, countries2) - || // or the opposite - injectionMatch(terminal1, countries2) && - injectionMatch(terminal2, countries); - } - - public static boolean hvdcLineMatch(HvdcLine line, List countries, List countries2) { - return filterByCountries(line.getConverterStation1().getTerminal(), line.getConverterStation2().getTerminal(), countries, countries2); - } - - public static boolean lineMatch(Line line, List countries, List countries2) { - return filterByCountries(line.getTerminal1(), line.getTerminal2(), countries, countries2); - } - - public static boolean transfoMatch(TwoWindingsTransformer transfo, List countries) { - return filterByCountries(transfo.getTerminal1(), transfo.getTerminal2(), countries, List.of()); - } -} diff --git a/src/test/java/org/gridsuite/actions/server/ContingencyListControllerTest.java b/src/test/java/org/gridsuite/actions/server/ContingencyListControllerTest.java index 56bc9a9a..dd22e8f3 100644 --- a/src/test/java/org/gridsuite/actions/server/ContingencyListControllerTest.java +++ b/src/test/java/org/gridsuite/actions/server/ContingencyListControllerTest.java @@ -32,12 +32,15 @@ import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; -import org.gridsuite.actions.server.dto.*; +import org.gridsuite.actions.ContingencyListEvaluator; +import org.gridsuite.actions.dto.*; +import org.gridsuite.actions.dto.contingency.FilterBasedContingencyList; +import org.gridsuite.actions.dto.contingency.IdBasedContingencyList; +import org.gridsuite.actions.dto.evaluation.ContingencyIdsByGroup; +import org.gridsuite.actions.dto.evaluation.ContingencyInfos; import org.gridsuite.actions.server.repositories.IdBasedContingencyListRepository; import org.gridsuite.actions.server.service.FilterService; import org.gridsuite.actions.server.utils.MatcherJson; -import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,7 +64,9 @@ import static com.powsybl.network.store.model.NetworkStoreApi.VERSION; import static org.gridsuite.filter.utils.EquipmentType.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.*; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -110,6 +115,8 @@ class ContingencyListControllerTest { @MockitoSpyBean private FilterService filterService; + @MockitoSpyBean + private ContingencyListEvaluator contingencyListEvaluator; @AfterEach void tearDown() { @@ -192,7 +199,7 @@ private String genModifiedFilterBasedContingencyList(List uuids) throws Js return "{\"filters\":" + objectMapper.writeValueAsString(filtersAttributes) + ", \"selectedEquipmentTypesByFilter\":[]}"; } - private UUID addNewFilterBasedContingencyList(String filters) throws Exception { + private FilterBasedContingencyList addNewFilterBasedContingencyList(String filters) throws Exception { String res = mvc.perform(post("/" + VERSION + "/filters-contingency-lists") .content(filters) @@ -207,7 +214,7 @@ private UUID addNewFilterBasedContingencyList(String filters) throws Exception { assertNull(list.toPowsyblContingencyList(network)); assertEquals(Map.of(), list.getNotFoundElements(network)); - return list.getId(); + return list; } private static void compareFilterBasedContingencyList(FilterBasedContingencyList expected, FilterBasedContingencyList current) { @@ -313,7 +320,7 @@ void testFilterBasedContingencyList() throws Exception { // create test String list = genFilterBasedContingencyList(filters); - UUID id = addNewFilterBasedContingencyList(list); + FilterBasedContingencyList filterBasedContingencyList = addNewFilterBasedContingencyList(list); // test get MappingBuilder requestPatternBuilder = WireMock.get(WireMock.urlPathEqualTo("/v1/filters/infos")) @@ -325,30 +332,22 @@ void testFilterBasedContingencyList() throws Exception { wireMockServer.stubFor(requestPatternBuilder.willReturn(WireMock.ok())); - mvc.perform(get("/" + VERSION + "/filters-contingency-lists/" + id) + mvc.perform(get("/" + VERSION + "/filters-contingency-lists/" + filterBasedContingencyList.getId()) .header(USER_ID_HEADER, USER_ID_HEADER) .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(APPLICATION_JSON)); - // test count - requestPatternBuilder = WireMock.post(WireMock.urlPathEqualTo("/v1/filters/evaluate/identifiables")) - .withQueryParam("networkUuid", WireMock.equalTo(NETWORK_UUID.toString())) - .withRequestBody(WireMock.containing(filters.get(0).toString()) - .and(WireMock.containing(filters.get(1).toString())) - .and(WireMock.containing(filters.get(2).toString())) - .and(WireMock.containing(IdentifiableType.GENERATOR.name()))); - - wireMockServer.stubFor(requestPatternBuilder.willReturn(WireMock.ok())); + doReturn(List.of()).when(contingencyListEvaluator).evaluateContingencyList(any(), any()); - String res = mvc.perform(get("/" + VERSION + "/contingency-lists/count?ids=" + id + "&networkUuid=" + NETWORK_UUID + "&variantId=" + VARIANT_ID_1) + String res = mvc.perform(get("/" + VERSION + "/contingency-lists/count?ids=" + filterBasedContingencyList.getId() + "&networkUuid=" + NETWORK_UUID + "&variantId=" + VARIANT_ID_1) .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); assertEquals(0, Integer.parseInt(res)); // duplicate test - String newUuid = mvc.perform(post("/" + VERSION + "/filters-contingency-lists?duplicateFrom=" + id)) + String newUuid = mvc.perform(post("/" + VERSION + "/filters-contingency-lists?duplicateFrom=" + filterBasedContingencyList.getId())) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); assertNotNull(newUuid); @@ -356,7 +355,7 @@ void testFilterBasedContingencyList() throws Exception { .andExpect(status().isNotFound()); // delete lists - mvc.perform(delete("/" + VERSION + "/contingency-lists/" + id)) + mvc.perform(delete("/" + VERSION + "/contingency-lists/" + filterBasedContingencyList.getId())) .andExpect(status().isOk()); newUuid = newUuid.replace("\"", ""); @@ -575,22 +574,14 @@ void modifyIdBasedContingencyList() throws Exception { @Test void testCountContingencyList() throws Exception { - // insert 1 contingency list with 3 filters - UUID id = setupCountContingencyTest(); + UUID filterBasedContingencyListId = setupCountContingencyTest(); - // count them (incl a wrong uuid) - Initial variant - String res = mvc.perform(get("/" + VERSION + "/contingency-lists/count?ids=" + UUID.randomUUID() + "&ids=" + id + "&networkUuid=" + NETWORK_UUID + "&variantId=" + VariantManagerConstants.INITIAL_VARIANT_ID) - .contentType(APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); + // count them (incl a wrong uuid) + String res = mvc.perform(get("/" + VERSION + "/contingency-lists/count?ids=" + filterBasedContingencyListId + "&ids=" + UUID.randomUUID() + "&networkUuid=" + NETWORK_UUID + "&variantId=" + VariantManagerConstants.INITIAL_VARIANT_ID) + .contentType(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); assertEquals(2, Integer.parseInt(res)); - - // count them (incl a wrong uuid) - first variant (without generator) - res = mvc.perform(get("/" + VERSION + "/contingency-lists/count?ids=" + UUID.randomUUID() + "&ids=" + id + "&networkUuid=" + NETWORK_UUID + "&variantId=" + VARIANT_ID_1) - .contentType(APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - assertEquals(1, Integer.parseInt(res)); } private UUID setupCountContingencyTest() throws Exception { @@ -599,34 +590,29 @@ private UUID setupCountContingencyTest() throws Exception { UUID.randomUUID()); String list = genFilterBasedContingencyList(filters); - UUID id = addNewFilterBasedContingencyList(list); - - MappingBuilder requestPatternBuilder = WireMock.post(WireMock.urlPathEqualTo("/v1/filters/evaluate/identifiables")) - .withQueryParam("networkUuid", WireMock.equalTo(NETWORK_UUID.toString())) - .withRequestBody(WireMock.containing(filters.get(0).toString()) - .and(WireMock.containing(filters.get(1).toString())) - .and(WireMock.containing(filters.get(2).toString())) - .and(WireMock.containing(IdentifiableType.GENERATOR.name()))); - - List identifiablesList = List.of( - new IdentifiableAttributes("GEN", IdentifiableType.GENERATOR, 0d), - new IdentifiableAttributes("GEN2", IdentifiableType.GENERATOR, 0d)); - - FilteredIdentifiables filteredIdentifiables = new FilteredIdentifiables(identifiablesList, List.of()); - wireMockServer.stubFor(requestPatternBuilder.willReturn( - WireMock.ok() - .withHeader("Content-Type", "application/json") - .withBody(objectMapper.writeValueAsString(filteredIdentifiables)))); - return id; + FilterBasedContingencyList filterBasedContingencyList = addNewFilterBasedContingencyList(list); + + // mock filter evaluation which is tested in filter lib + ContingencyInfos contingencyInfosMock = mock(ContingencyInfos.class); + Contingency contingencyMock = mock(Contingency.class); + when(contingencyInfosMock.getContingency()).thenReturn(contingencyMock); + + ContingencyInfos contingencyInfosMock2 = mock(ContingencyInfos.class); + Contingency contingencyMock2 = mock(Contingency.class); + when(contingencyInfosMock2.getContingency()).thenReturn(contingencyMock2); + + doReturn(List.of(contingencyInfosMock, contingencyInfosMock2)).when(contingencyListEvaluator).evaluateContingencyList(any(), any()); + + return filterBasedContingencyList.getId(); } @Test void testCountContingencyListByGroup() throws Exception { // insert 1 contingency list with 3 filters - UUID id = setupCountContingencyTest(); + UUID filterBasedContingencyListId = setupCountContingencyTest(); - // count them (incl a wrong uuid) - Initial variant - ContingencyIdsByGroup contingencyIdsByGroup = ContingencyIdsByGroup.builder().ids(Map.of(CONTINGENCY_1, List.of(id, UUID.randomUUID()), CONTINGENCY_2, List.of(UUID.randomUUID()))).build(); + // count them (incl a wrong uuid) + ContingencyIdsByGroup contingencyIdsByGroup = ContingencyIdsByGroup.builder().ids(Map.of(CONTINGENCY_1, List.of(filterBasedContingencyListId, UUID.randomUUID()), CONTINGENCY_2, List.of(UUID.randomUUID()))).build(); Map res = objectMapper.readValue(mvc.perform(post("/" + VERSION + "/contingency-lists/count-by-group?networkUuid=" + NETWORK_UUID + "&variantId=" + VariantManagerConstants.INITIAL_VARIANT_ID) .contentType(APPLICATION_JSON) .content(objectMapper.writeValueAsString(contingencyIdsByGroup))) @@ -636,16 +622,5 @@ void testCountContingencyListByGroup() throws Exception { }); assertEquals(2, res.get(CONTINGENCY_1)); assertEquals(0, res.get(CONTINGENCY_2)); - - // count them (incl a wrong uuid) - first variant (without generator) - res = objectMapper.readValue(mvc.perform(post("/" + VERSION + "/contingency-lists/count-by-group?networkUuid=" + NETWORK_UUID + "&variantId=" + VARIANT_ID_1) - .contentType(APPLICATION_JSON) - .content(objectMapper.writeValueAsString(contingencyIdsByGroup))) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(), - new TypeReference<>() { - }); - assertEquals(1, res.get(CONTINGENCY_1)); - assertEquals(0, res.get(CONTINGENCY_2)); } } diff --git a/src/test/java/org/gridsuite/actions/server/utils/ContingencyListUtilsTest.java b/src/test/java/org/gridsuite/actions/server/utils/ContingencyListUtilsTest.java deleted file mode 100644 index 90ee61a6..00000000 --- a/src/test/java/org/gridsuite/actions/server/utils/ContingencyListUtilsTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2021, 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.actions.server.utils; - -import com.powsybl.contingency.*; -import com.powsybl.iidm.network.IdentifiableType; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Bassel El Cheikh - */ - -class ContingencyListUtilsTest { - @ParameterizedTest - @MethodSource({ - "provideArgumentsForTests" - }) - void testConversionFromIdentifiableAttributesToContingency(String id, IdentifiableType type, Class expectedClass) { - IdentifiableAttributes identifierAttributes = new IdentifiableAttributes(id, type, null); - assertEquals(expectedClass, ContingencyListUtils.toContingencyElement(identifierAttributes).getClass()); - } - - static Stream provideArgumentsForTests() { - return Stream.of( - Arguments.of("id", IdentifiableType.LINE, LineContingency.class), - Arguments.of("id", IdentifiableType.TWO_WINDINGS_TRANSFORMER, TwoWindingsTransformerContingency.class), - Arguments.of("id", IdentifiableType.THREE_WINDINGS_TRANSFORMER, ThreeWindingsTransformerContingency.class), - Arguments.of("id", IdentifiableType.GENERATOR, GeneratorContingency.class), - Arguments.of("id", IdentifiableType.BATTERY, BatteryContingency.class), - Arguments.of("id", IdentifiableType.LOAD, LoadContingency.class), - Arguments.of("id", IdentifiableType.SHUNT_COMPENSATOR, ShuntCompensatorContingency.class), - Arguments.of("id", IdentifiableType.STATIC_VAR_COMPENSATOR, StaticVarCompensatorContingency.class), - Arguments.of("id", IdentifiableType.HVDC_LINE, HvdcLineContingency.class), - Arguments.of("id", IdentifiableType.DANGLING_LINE, DanglingLineContingency.class), - Arguments.of("id", IdentifiableType.BUSBAR_SECTION, BusbarSectionContingency.class) - ); - } - -} diff --git a/src/test/java/org/gridsuite/actions/server/utils/FiltersUtilsTest.java b/src/test/java/org/gridsuite/actions/server/utils/FiltersUtilsTest.java deleted file mode 100644 index 1489b1c9..00000000 --- a/src/test/java/org/gridsuite/actions/server/utils/FiltersUtilsTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2021, 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.actions.server.utils; - -import com.powsybl.iidm.network.*; -import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; -import com.powsybl.iidm.network.test.HvdcTestNetwork; -import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Franck Lecuyer - */ -class FiltersUtilsTest { - @Test - void testInjection() { - Network network = EurostagTutorialExample1Factory.createWithMoreGenerators(new NetworkFactoryImpl()); - // just test Generator for common injection equipment - // Injection eqpt can have 1 single country filter - Generator generator = network.getGenerator("GEN"); - assertNotNull(generator); - assertTrue(FiltersUtils.injectionMatch(generator.getTerminal(), List.of("FR", "BE"))); - assertFalse(FiltersUtils.injectionMatch(generator.getTerminal(), List.of("DE"))); - assertTrue(FiltersUtils.injectionMatch(generator.getTerminal(), List.of())); - } - - @Test - void testHvdcLine() { - Network network = HvdcTestNetwork.createVsc(new NetworkFactoryImpl()); - network.getSubstation("S2").setCountry(Country.IT); - // S1 = FR, S2 = IT - HvdcLine hvdc = network.getHvdcLine("L"); - assertNotNull(hvdc); - // HVDC can have 2 country filters - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of(), List.of())); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of("FR"), List.of())); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of(), List.of("FR"))); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of("IT"), List.of())); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of(), List.of("IT"))); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of("FR"), List.of("IT"))); - assertTrue(FiltersUtils.hvdcLineMatch(hvdc, List.of("ES", "FR"), List.of("ZA", "IT"))); - - assertFalse(FiltersUtils.hvdcLineMatch(hvdc, List.of("ES"), List.of("ZA"))); - assertFalse(FiltersUtils.hvdcLineMatch(hvdc, List.of(), List.of("ZA"))); - assertFalse(FiltersUtils.hvdcLineMatch(hvdc, List.of("FR", "IT"), List.of("ZA"))); - } - - @Test - void testLine() { - Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl()); - network.getSubstation("P2").setCountry(Country.PT); - Line line1 = network.getLine("NHV1_NHV2_1"); - assertNotNull(line1); - // Line can have 2 country filters - assertTrue(FiltersUtils.lineMatch(line1, List.of(), List.of())); - assertTrue(FiltersUtils.lineMatch(line1, List.of("FR"), List.of())); - assertTrue(FiltersUtils.lineMatch(line1, List.of(), List.of("FR"))); - assertTrue(FiltersUtils.lineMatch(line1, List.of("PT"), List.of())); - assertTrue(FiltersUtils.lineMatch(line1, List.of(), List.of("PT"))); - assertTrue(FiltersUtils.lineMatch(line1, List.of("FR"), List.of("PT"))); - assertTrue(FiltersUtils.lineMatch(line1, List.of("ES", "FR"), List.of("ZA", "PT"))); - - assertFalse(FiltersUtils.lineMatch(line1, List.of("ES"), List.of("ZA"))); - assertFalse(FiltersUtils.lineMatch(line1, List.of(), List.of("ZA"))); - assertFalse(FiltersUtils.lineMatch(line1, List.of("DE"), List.of())); - assertFalse(FiltersUtils.lineMatch(line1, List.of("FR", "PT"), List.of("ZA"))); - } - - @Test - void test2WTransfo() { - Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl()); - network.getSubstation("P2").setCountry(Country.PT); - TwoWindingsTransformer transfo1 = network.getTwoWindingsTransformer("NGEN_NHV1"); // belongs to FR - TwoWindingsTransformer transfo2 = network.getTwoWindingsTransformer("NHV2_NLOAD"); // belongs to PT - // Transfo can have 1 single country filter - assertNotNull(transfo1); - assertTrue(FiltersUtils.transfoMatch(transfo1, List.of())); - assertTrue(FiltersUtils.transfoMatch(transfo1, List.of("FR"))); - assertFalse(FiltersUtils.transfoMatch(transfo1, List.of("PT"))); - assertFalse(FiltersUtils.transfoMatch(transfo1, List.of("ES", "ZA", "DE", "PT"))); - - assertNotNull(transfo2); - assertTrue(FiltersUtils.transfoMatch(transfo2, List.of())); - assertTrue(FiltersUtils.transfoMatch(transfo2, List.of("PT"))); - assertFalse(FiltersUtils.transfoMatch(transfo2, List.of("FR"))); - assertFalse(FiltersUtils.transfoMatch(transfo2, List.of("ES", "ZA", "DE", "FR"))); - } -}