Skip to content
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
</dependency>

<!-- Compilation dependencies -->
<dependency>
<groupId>org.gridsuite</groupId>
<artifactId>gridsuite-actions</artifactId>
</dependency>
<dependency>
<groupId>org.gridsuite</groupId>
<artifactId>gridsuite-filter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
100 changes: 22 additions & 78 deletions src/main/java/org/gridsuite/actions/server/ContingencyListService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -92,10 +97,6 @@ List<ContingencyListMetadata> getContingencyListsMetadata(List<UUID> ids) {
).flatMap(Function.identity()).collect(Collectors.toList());
}

public List<IdentifiableAttributes> evaluateFiltersNetwork(UUID networkUuid, String variantUuid, FilterBasedContingencyList filterBasedContingencyList) {
return filterService.evaluateFilters(networkUuid, variantUuid, filterBasedContingencyList);
}

@Transactional(readOnly = true)
public Optional<PersistentContingencyList> getIdBasedContingencyList(UUID id, Network network) {
return doGetIdBasedContingencyList(id, network);
Expand Down Expand Up @@ -133,27 +134,11 @@ private Optional<FilterBasedContingencyListEntity> doGetFilterBasedContingencyLi
return filterBasedContingencyListRepository.findById(id);
}

private List<Contingency> getPowsyblContingencies(PersistentContingencyList contingencyList, Network network, UUID networkUuid, String variantUuid) {
ContingencyList powsyblContingencyList;
if (Objects.requireNonNull(contingencyList.getMetadata().getType()) == ContingencyListType.FILTERS) {
FilterBasedContingencyList filterBasedContingencyList = (FilterBasedContingencyList) contingencyList;
List<IdentifiableAttributes> 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<UUID> ids, UUID networkUuid, String variantId) {
private Integer getContingencyCount(Network network, List<UUID> ids) {
return ids.stream()
.map(uuid -> {
Optional<PersistentContingencyList> 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);
}
Expand All @@ -163,14 +148,14 @@ public Map<String, Integer> 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<UUID> ids, UUID networkUuid, String variantId) {
Network network = getNetworkFromUuid(networkUuid, variantId);
return getContingencyCount(network, ids, networkUuid, variantId);
return getContingencyCount(network, ids);
}

@Transactional(readOnly = true)
Expand All @@ -182,15 +167,15 @@ public ContingencyListExportResult exportContingencyList(List<UUID> contingencyL
contingencyListIds.forEach(contingencyListId -> {
Optional<PersistentContingencyList> 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<Contingency> getContingencies(PersistentContingencyList persistentContingencyList, Network network, UUID networkUuid, String variantId) {
return evaluateContingencyList(persistentContingencyList, network, networkUuid, variantId)
private List<Contingency> getContingencies(PersistentContingencyList persistentContingencyList, Network network) {
return contingencyListEvaluator.evaluateContingencyList(persistentContingencyList, network)
.stream()
.map(ContingencyInfos::getContingency)
.filter(Objects::nonNull)
Expand All @@ -200,7 +185,7 @@ private List<Contingency> getContingencies(PersistentContingencyList persistentC
@Transactional(readOnly = true)
public List<ContingencyInfos> exportContingencyInfosList(List<UUID> 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) {
Expand All @@ -214,47 +199,6 @@ private Optional<PersistentContingencyList> getAnyContingencyList(UUID id, Netwo
.or(() -> doGetFilterBasedContingencyList(id));
}

private List<ContingencyInfos> evaluateContingencyList(PersistentContingencyList persistentContingencyList, Network network, UUID networkUuid, String variantId) {
List<Contingency> contingencies = getPowsyblContingencies(persistentContingencyList, network, networkUuid, variantId);
Map<String, Set<String>> notFoundElements = persistentContingencyList.getNotFoundElements(network);

// For a gridsuite contingency with all equipments not found the powsybl contingency is not created
List<ContingencyInfos> 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<String> 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<? extends Terminal> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <kevin.le-saulnier at rte-france.com>
*/
@Configuration
public class ActionsConfig {
@Bean
public ContingencyListEvaluator contingencyListEvaluator(
FilterProvider filterProvider
) {
return new ContingencyListEvaluator(filterProvider);
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading