diff --git a/network-area-diagram/src/main/java/com/powsybl/nad/svg/iidm/TopologicalStyleProvider.java b/network-area-diagram/src/main/java/com/powsybl/nad/svg/iidm/TopologicalStyleProvider.java index 28382a78b..a66b11f1e 100644 --- a/network-area-diagram/src/main/java/com/powsybl/nad/svg/iidm/TopologicalStyleProvider.java +++ b/network-area-diagram/src/main/java/com/powsybl/nad/svg/iidm/TopologicalStyleProvider.java @@ -11,10 +11,10 @@ import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.Terminal; import com.powsybl.nad.model.*; - import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; /** @@ -22,6 +22,8 @@ */ public class TopologicalStyleProvider extends AbstractVoltageStyleProvider { + private Map limitViolationStyles = Map.of(); + public TopologicalStyleProvider(Network network) { super(network); } @@ -30,11 +32,34 @@ public TopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltageS super(network, baseVoltageStyle); } + public TopologicalStyleProvider(Network network, Map limitViolationStyles) { + super(network); + this.limitViolationStyles = limitViolationStyles; + } + + public TopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltageStyle, Map limitViolationStyles) { + super(network, baseVoltageStyle); + this.limitViolationStyles = limitViolationStyles; + } + @Override public List getCssFilenames() { return Collections.singletonList("topologicalStyle.css"); } + @Override + public List getBranchEdgeStyleClasses(BranchEdge branchEdge) { + // Check custom violations first + if (!limitViolationStyles.isEmpty()) { + String customStyle = limitViolationStyles.get(branchEdge.getEquipmentId()); + if (customStyle != null && !customStyle.isBlank()) { + return List.of(customStyle); + } + } + // Fallback to default overload detection + return super.getBranchEdgeStyleClasses(branchEdge); + } + @Override public List getBusNodeStyleClasses(BusNode busNode) { List styles = new ArrayList<>(super.getBusNodeStyleClasses(busNode)); diff --git a/network-area-diagram/src/test/java/com/powsybl/nad/svg/iidm/TopologicalStyleProviderTest.java b/network-area-diagram/src/test/java/com/powsybl/nad/svg/iidm/TopologicalStyleProviderTest.java new file mode 100644 index 000000000..e31fab51d --- /dev/null +++ b/network-area-diagram/src/test/java/com/powsybl/nad/svg/iidm/TopologicalStyleProviderTest.java @@ -0,0 +1,81 @@ +/** + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.nad.svg.iidm; + +import com.powsybl.commons.config.BaseVoltagesConfig; +import com.powsybl.diagram.test.Networks; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Terminal; +import com.powsybl.nad.model.BranchEdge; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class TopologicalStyleProviderTest { + + @Test + void customLimitViolationStyleOverridesDefaultBranchStyle() { + Network network = Networks.createNetworkWithLine(); + TopologicalStyleProvider provider = new TopologicalStyleProvider(network, Map.of("Line", "custom-style")); + BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); + + List styles = provider.getBranchEdgeStyleClasses(branchEdge); + + assertEquals(List.of("custom-style"), styles); + } + + @Test + void missingCustomStyleFallsBackToDefaultBranchStyle() { + Network network = Networks.createNetworkWithLine(); + BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); + + TopologicalStyleProvider defaultProvider = new TopologicalStyleProvider(network); + List defaultStyles = defaultProvider.getBranchEdgeStyleClasses(branchEdge); + + TopologicalStyleProvider providerWithCustomMap = new TopologicalStyleProvider(network, Map.of("OtherLine", "custom-style")); + List styles = providerWithCustomMap.getBranchEdgeStyleClasses(branchEdge); + + assertEquals(defaultStyles, styles); + } + + @Test + void constructorWithBaseVoltageConfigKeepsCustomStyles() { + Network network = Networks.createNetworkWithLine(); + BaseVoltagesConfig baseVoltagesConfig = BaseVoltagesConfig.fromPlatformConfig(); + BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); + + TopologicalStyleProvider provider = new TopologicalStyleProvider(network, baseVoltagesConfig, Map.of("Line", "custom-style")); + + assertEquals(List.of("custom-style"), provider.getBranchEdgeStyleClasses(branchEdge)); + } + + @Test + void baseVoltageStyleReturnsEmptyForNullTerminal() { + Network network = Networks.createNetworkWithLine(); + BaseVoltagesConfig baseVoltagesConfig = BaseVoltagesConfig.fromPlatformConfig(); + TestTopologicalStyleProvider provider = new TestTopologicalStyleProvider(network, baseVoltagesConfig); + + assertTrue(provider.getBaseVoltageStyleForTerminal(null).isEmpty()); + } + + private static final class TestTopologicalStyleProvider extends TopologicalStyleProvider { + + private TestTopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltagesConfig) { + super(network, baseVoltagesConfig); + } + + private Optional getBaseVoltageStyleForTerminal(Terminal terminal) { + return super.getBaseVoltageStyle(terminal); + } + } +} diff --git a/single-line-diagram/single-line-diagram-core/src/main/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProvider.java b/single-line-diagram/single-line-diagram-core/src/main/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProvider.java index 9294f720b..cd002cf7c 100644 --- a/single-line-diagram/single-line-diagram-core/src/main/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProvider.java +++ b/single-line-diagram/single-line-diagram-core/src/main/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProvider.java @@ -22,17 +22,43 @@ */ public class LimitHighlightStyleProvider extends EmptyStyleProvider { private final Network network; + private Map limitViolationStyles = Map.of(); public LimitHighlightStyleProvider(Network network) { + this(network, Collections.emptyMap()); + } + + public LimitHighlightStyleProvider(Network network, Map limitViolationStyles) { this.network = network; + this.limitViolationStyles = limitViolationStyles; } @Override public List getEdgeStyles(Graph graph, Edge edge) { + // Check custom violations first + if (!limitViolationStyles.isEmpty()) { + Optional customStyle = getCustomViolationStyle(edge); + if (customStyle.isPresent()) { + return List.of(customStyle.get()); + } + } + // Fallback to default overload detection Optional overloadStyle = getOverloadStyle(edge); return overloadStyle.map(Collections::singletonList).orElse(Collections.emptyList()); } + private Optional getCustomViolationStyle(Edge edge) { + for (Node node : edge.getNodes()) { + if (node instanceof FeederNode feederNode) { + String style = limitViolationStyles.get(feederNode.getEquipmentId()); + if (style != null && !style.isBlank()) { + return Optional.of(style); + } + } + } + return Optional.empty(); + } + private Optional getOverloadStyle(Edge edge) { List nodes = edge.getNodes(); for (Node node : nodes) { diff --git a/single-line-diagram/single-line-diagram-core/src/test/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProviderTest.java b/single-line-diagram/single-line-diagram-core/src/test/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProviderTest.java new file mode 100644 index 000000000..ed0c721a5 --- /dev/null +++ b/single-line-diagram/single-line-diagram-core/src/test/java/com/powsybl/sld/svg/styles/iidm/LimitHighlightStyleProviderTest.java @@ -0,0 +1,64 @@ +/** + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.sld.svg.styles.iidm; + +import com.powsybl.diagram.test.Networks; +import com.powsybl.iidm.network.Network; +import com.powsybl.sld.model.graphs.VoltageLevelInfos; +import com.powsybl.sld.model.nodes.BusNode; +import com.powsybl.sld.model.nodes.Edge; +import com.powsybl.sld.model.nodes.FeederNode; +import com.powsybl.sld.model.nodes.FeederType; +import com.powsybl.sld.model.nodes.NodeSide; +import com.powsybl.sld.model.nodes.feeders.FeederWithSides; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LimitHighlightStyleProviderTest { + + private static Edge buildEdge(String equipmentId) { + FeederWithSides feeder = new FeederWithSides( + FeederType.BRANCH, + NodeSide.ONE, + new VoltageLevelInfos("VL1", "VoltageLevel1", 225.0), + new VoltageLevelInfos("VL2", "VoltageLevel2", 225.0) + ); + FeederNode feederNode = new FeederNode("feederNode", "Feeder", equipmentId, "component", false, feeder, null); + BusNode busNode = new BusNode("busNode", "Bus", false); + return new Edge(feederNode, busNode); + } + + @Test + void customLimitViolationStyleOverridesDefaultEdgeStyles() { + Network network = Networks.createNetworkWithLine(); + LimitHighlightStyleProvider provider = new LimitHighlightStyleProvider(network, Map.of("Line", "custom-style")); + Edge edge = buildEdge("Line"); + + List styles = provider.getEdgeStyles(null, edge); + + assertEquals(List.of("custom-style"), styles); + } + + @Test + void missingCustomStyleFallsBackToDefaultEdgeStyles() { + Network network = Networks.createNetworkWithLine(); + Edge edge = buildEdge("Line"); + + LimitHighlightStyleProvider defaultProvider = new LimitHighlightStyleProvider(network); + List defaultStyles = defaultProvider.getEdgeStyles(null, edge); + + LimitHighlightStyleProvider providerWithCustomMap = new LimitHighlightStyleProvider(network, Map.of("OtherLine", "custom-style")); + List styles = providerWithCustomMap.getEdgeStyles(null, edge); + + assertEquals(defaultStyles, styles); + } +}