From 6c238ea9cc6264d36d67dcdd994e46dad57d54ff Mon Sep 17 00:00:00 2001 From: Sylvain Bouzols Date: Fri, 7 Feb 2025 16:17:55 +0100 Subject: [PATCH] Fix byFilter deletion network impacts reduction (#590) Signed-off-by: sBouzols Co-authored-by: Slimane AMAR --- .../modifications/NetworkStoreListener.java | 49 ++++++++++++++----- .../AbstractByFilterDeletionTest.java | 9 +++- .../EquipmentByFilterDeletionTest.java | 24 ++++++++- .../server/utils/NetworkCreation.java | 12 +++++ 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/gridsuite/modification/server/modifications/NetworkStoreListener.java b/src/main/java/org/gridsuite/modification/server/modifications/NetworkStoreListener.java index e155587dc..9885aa302 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/NetworkStoreListener.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/NetworkStoreListener.java @@ -23,6 +23,7 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.gridsuite.modification.NetworkModificationException.Type.MODIFICATION_ERROR; @@ -270,27 +271,32 @@ private void flushEquipmentInfos() { private List reduceNetworkImpacts() { List reducedImpacts = new ArrayList<>(); Set impactedSubstationsIds = new HashSet<>(); + List deletionImpacts = getDeletionSimpleImpacts(); - // Impacts type collection + // All network is impacted by deletions + if (getImpactedSubstationIds(deletionImpacts).size() >= collectionThreshold) { + return getFullNetworkImpact(); + } + + // Group simple impacts over same element type into collection impact + // And compute impactedSubstationsIds on the way for (IdentifiableType elementType : IdentifiableType.values()) { - List impacts = getSimpleImpacts(elementType); - if (impacts.size() >= collectionThreshold) { + List impactsByType = getCreationModificationSimpleImpacts(elementType); + if (impactsByType.size() >= collectionThreshold) { reducedImpacts.add(CollectionElementImpact.builder() .elementType(elementType) .build()); } else { - impactedSubstationsIds.addAll(impacts.stream().flatMap(i -> i.getSubstationIds().stream()).toList()); + impactedSubstationsIds.addAll(getImpactedSubstationIds(impactsByType)); } } - // All network is impacted ? + // All network is impacted by modifications and/or creations if (impactedSubstationsIds.size() >= collectionThreshold) { - return List.of(CollectionElementImpact.builder() - .elementType(IdentifiableType.SUBSTATION) - .build()); + return getFullNetworkImpact(); } - // Impacts type simple for substation only + // Create simple impacts for substation type only reducedImpacts.addAll( impactedSubstationsIds.stream().map(id -> SimpleElementImpact.builder() @@ -302,13 +308,30 @@ private List reduceNetworkImpacts() { ).toList() ); - // Impacts type simple for deletion only - reducedImpacts.addAll(simpleImpacts.stream().filter(SimpleElementImpact::isDeletion).distinct().toList()); + // Fuse both reduced impacts + return Stream.concat(reducedImpacts.stream(), deletionImpacts.stream()).toList(); + } + + private List getFullNetworkImpact() { + return List.of(CollectionElementImpact.builder() + .elementType(IdentifiableType.SUBSTATION) + .build()); + } - return reducedImpacts; + private Set getImpactedSubstationIds(List impacts) { + Set impactedSubstationsIds = new HashSet<>(); + impactedSubstationsIds.addAll(impacts.stream().flatMap(i -> i.getSubstationIds().stream()).toList()); + return impactedSubstationsIds; + } + + private List getDeletionSimpleImpacts() { + return simpleImpacts.stream() + .filter(SimpleElementImpact::isDeletion) + .distinct() + .toList(); } - private List getSimpleImpacts(IdentifiableType elementType) { + private List getCreationModificationSimpleImpacts(IdentifiableType elementType) { return simpleImpacts.stream() .filter(i -> !i.isDeletion() && i.getElementType() == elementType) .distinct() diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/AbstractByFilterDeletionTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/AbstractByFilterDeletionTest.java index 30d65c772..767a81349 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/AbstractByFilterDeletionTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/AbstractByFilterDeletionTest.java @@ -30,6 +30,8 @@ abstract class AbstractByFilterDeletionTest extends AbstractNetworkModificationTest { protected static final UUID FILTER_ID_1 = UUID.randomUUID(); protected static final UUID FILTER_ID_2 = UUID.randomUUID(); + protected static final UUID FILTER_ID_3 = UUID.randomUUID(); + protected static final String EQUIPMENT_WRONG_ID_1 = "wrongId1"; protected abstract IdentifiableType getIdentifiableType(); @@ -149,10 +151,15 @@ protected ModificationInfos buildModification() { .name("filter2") .build(); + var filter3 = FilterInfos.builder() + .id(FILTER_ID_3) + .name("filter3") + .build(); + return ByFilterDeletionInfos.builder() .stashed(false) .equipmentType(getIdentifiableType()) - .filters(List.of(filter1, filter2)) + .filters(List.of(filter1, filter2, filter3)) .build(); } diff --git a/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/EquipmentByFilterDeletionTest.java b/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/EquipmentByFilterDeletionTest.java index 0f36d442c..661e700ef 100644 --- a/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/EquipmentByFilterDeletionTest.java +++ b/src/test/java/org/gridsuite/modification/server/modifications/byfilterdeletion/EquipmentByFilterDeletionTest.java @@ -13,6 +13,7 @@ import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.modification.server.impacts.AbstractBaseImpact; import org.gridsuite.modification.server.service.FilterService; import org.gridsuite.modification.server.utils.NetworkCreation; import org.junit.jupiter.api.BeforeEach; @@ -22,6 +23,8 @@ import java.util.List; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.modification.server.impacts.TestImpactUtils.createCollectionElementImpact; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -31,6 +34,9 @@ class EquipmentByFilterDeletionTest extends AbstractByFilterDeletionTest { private static final String LOAD_ID_2 = "load2"; private static final String LOAD_ID_3 = "load3"; private static final String LOAD_ID_4 = "load4"; + private static final String LOAD_ID_7 = "load7"; + private static final String LOAD_ID_11 = "load11"; + private static final String LOAD_ID_12 = "load12"; @BeforeEach void specificSetUp() { @@ -49,6 +55,9 @@ protected void assertAfterNetworkModificationCreation() { assertNull(getNetwork().getLoad(LOAD_ID_2)); assertNull(getNetwork().getLoad(LOAD_ID_3)); assertNull(getNetwork().getLoad(LOAD_ID_4)); + assertNull(getNetwork().getLoad(LOAD_ID_7)); + assertNull(getNetwork().getLoad(LOAD_ID_11)); + assertNull(getNetwork().getLoad(LOAD_ID_12)); } @Override @@ -57,6 +66,9 @@ protected void assertAfterNetworkModificationDeletion() { assertNotNull(getNetwork().getLoad(LOAD_ID_2)); assertNotNull(getNetwork().getLoad(LOAD_ID_3)); assertNotNull(getNetwork().getLoad(LOAD_ID_4)); + assertNotNull(getNetwork().getLoad(LOAD_ID_7)); + assertNotNull(getNetwork().getLoad(LOAD_ID_11)); + assertNotNull(getNetwork().getLoad(LOAD_ID_12)); } @Override @@ -84,6 +96,16 @@ protected List getTestFilters() { .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(LOAD_ID_3, null), new IdentifierListFilterEquipmentAttributes(LOAD_ID_4, null))) .build(); - return List.of(filter1, filter2); + IdentifierListFilter filter3 = IdentifierListFilter.builder().id(FILTER_ID_3).modificationDate(new Date()).equipmentType(EquipmentType.LOAD) + .filterEquipmentsAttributes(List.of(new IdentifierListFilterEquipmentAttributes(LOAD_ID_7, null), + new IdentifierListFilterEquipmentAttributes(LOAD_ID_11, null), + new IdentifierListFilterEquipmentAttributes(LOAD_ID_12, null))) + .build(); + return List.of(filter1, filter2, filter3); + } + + @Override + protected void assertResultImpacts(List impacts) { + assertThat(impacts).containsExactly(createCollectionElementImpact(IdentifiableType.SUBSTATION)); } } diff --git a/src/test/java/org/gridsuite/modification/server/utils/NetworkCreation.java b/src/test/java/org/gridsuite/modification/server/utils/NetworkCreation.java index 32e8691e9..6886f233a 100644 --- a/src/test/java/org/gridsuite/modification/server/utils/NetworkCreation.java +++ b/src/test/java/org/gridsuite/modification/server/utils/NetworkCreation.java @@ -435,6 +435,18 @@ public static Network createLoadNetwork(UUID uuid, NetworkFactory networkFactory createSwitch(v32, "v32d1", "v32d1", SwitchKind.DISCONNECTOR, true, false, false, 0, 2); createSwitch(v32, "v32d2", "v32d2", SwitchKind.DISCONNECTOR, true, false, false, 1, 3); + Substation s4 = createSubstation(network, "s4", "s4", Country.FR); + VoltageLevel v41 = createVoltageLevel(s4, "v41", "v41", TopologyKind.NODE_BREAKER, 450.0); + createBusBarSection(v41, "7.1", "7.1", 0); + createLoad(v41, "load11", "load11", 1, 42.1, 1.0, "cn0", 3, ConnectablePosition.Direction.TOP); + createSwitch(v41, "v41d1", "v41d1", SwitchKind.DISCONNECTOR, true, false, false, 0, 1); + + Substation s5 = createSubstation(network, "s5", "s5", Country.FR); + VoltageLevel v51 = createVoltageLevel(s5, "v51", "v51", TopologyKind.NODE_BREAKER, 450.0); + createBusBarSection(v51, "8.1", "8.1", 0); + createLoad(v51, "load12", "load12", 1, 42.1, 1.0, "cn0", 3, ConnectablePosition.Direction.TOP); + createSwitch(v51, "v51d1", "v51d1", SwitchKind.DISCONNECTOR, true, false, false, 0, 1); + network.getVariantManager().setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID); network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_ID);