AbstractVoltageStyleProvider.java
/**
* 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 com.powsybl.sld.svg.styles;
import com.powsybl.commons.config.BaseVoltagesConfig;
import com.powsybl.sld.library.ComponentLibrary;
import com.powsybl.sld.library.ComponentTypeName;
import com.powsybl.sld.model.graphs.Graph;
import com.powsybl.sld.model.graphs.VoltageLevelGraph;
import com.powsybl.sld.model.graphs.VoltageLevelInfos;
import com.powsybl.sld.model.nodes.*;
import com.powsybl.sld.model.nodes.feeders.FeederTwLeg;
import com.powsybl.sld.model.nodes.feeders.FeederWithSides;
import com.powsybl.sld.svg.BusInfo;
import java.util.*;
import static com.powsybl.sld.svg.styles.StyleClassConstants.WIRE_STYLE_CLASS;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
* @author Franck Lecuyer {@literal <franck.lecuyer at rte-france.com>}
* @author Florian Dupuy {@literal <florian.dupuy at rte-france.com>}
*/
public abstract class AbstractVoltageStyleProvider extends AbstractStyleProvider {
protected static final String BASE_VOLTAGE_PROFILE = "Default";
private static final String WINDING1 = "WINDING1";
private static final String WINDING2 = "WINDING2";
private static final String WINDING3 = "WINDING3";
private static final String ARROW1 = "ARROW1";
private static final String ARROW2 = "ARROW2";
private static final String ARROW3 = "ARROW3";
protected final BaseVoltagesConfig baseVoltagesConfig;
protected AbstractVoltageStyleProvider(BaseVoltagesConfig baseVoltagesConfig) {
this.baseVoltagesConfig = Objects.requireNonNull(baseVoltagesConfig);
}
@Override
public List<String> getEdgeStyles(Graph graph, Edge edge) {
List<String> edgesStyles = new ArrayList<>();
edgesStyles.add(WIRE_STYLE_CLASS);
edgesStyles.addAll(getVoltageLevelEdgeStyles(graph, edge));
getDanglingLineStyle(edge).ifPresent(edgesStyles::add);
return edgesStyles;
}
private Optional<String> getDanglingLineStyle(Edge edge) {
if (edge.getNode1() instanceof FeederNode feederNode1) {
return getDanglingLineStyle(feederNode1);
}
if (edge.getNode2() instanceof FeederNode feederNode2) {
return getDanglingLineStyle(feederNode2);
}
return Optional.empty();
}
private Optional<String> getDanglingLineStyle(FeederNode n) {
if (n.getFeeder().getFeederType() == FeederType.BRANCH) {
return switch (n.getComponentType()) {
case ComponentTypeName.TIE_LINE -> Optional.of(StyleClassConstants.TIE_LINE);
case ComponentTypeName.DANGLING_LINE -> Optional.of(StyleClassConstants.DANGLING_LINE);
default -> Optional.empty();
};
}
return Optional.empty();
}
protected List<String> getVoltageLevelEdgeStyles(Graph graph, Edge edge) {
VoltageLevelInfos vLevelInfos;
Node nodeForStyle = isNodeSeparatingStyles(edge.getNode1()) ? edge.getNode2() : edge.getNode1();
if (nodeForStyle instanceof FeederNode && ((FeederNode) nodeForStyle).getFeeder() instanceof FeederTwLeg) {
vLevelInfos = ((FeederTwLeg) ((FeederNode) nodeForStyle).getFeeder()).getVoltageLevelInfos();
} else {
vLevelInfos = graph.getVoltageLevelInfos(nodeForStyle);
}
return getNodeStyles(vLevelInfos, nodeForStyle);
}
@Override
public List<String> getNodeStyles(VoltageLevelGraph graph, Node node, ComponentLibrary componentLibrary, boolean showInternalNodes) {
List<String> styles = super.getNodeStyles(graph, node, componentLibrary, showInternalNodes);
if (graph != null && !isNodeSeparatingStyles(node)) {
// Some nodes have two styles as they separate voltage levels for instance
// Then they have a style depending on their subcomponents (-> see getSvgNodeSubcomponentStyles)
// Note that nodes outside a voltageLevel graph (graph==null) are nodes with two styles
styles.addAll(getNodeStyles(graph.getVoltageLevelInfos(), node));
}
return styles;
}
protected abstract boolean isNodeSeparatingStyles(Node node);
@Override
public List<String> getNodeSubcomponentStyles(Graph graph, Node node, String subComponentName) {
List<String> styles = new ArrayList<>();
VoltageLevelGraph g = graph.getVoltageLevelGraph(node);
if (g != null) {
// node inside a voltageLevel graph
if (isNodeSeparatingStyles(node)) {
if (node instanceof FeederNode) {
Feeder feeder = ((FeederNode) node).getFeeder();
if (feeder instanceof FeederWithSides) {
VoltageLevelInfos vlInfo = getSubComponentVoltageLevelInfos((FeederWithSides) feeder, subComponentName);
styles.addAll(getNodeStyles(vlInfo, node));
}
} else if (node instanceof Middle3WTNode) {
VoltageLevelInfos vlInfo = getSubComponentVoltageLevelInfos((Middle3WTNode) node, subComponentName);
styles.addAll(getNodeStyles(vlInfo, node));
} else {
VoltageLevelInfos vlInfo = graph.getVoltageLevelInfos(node);
styles.addAll(getNodeStyles(vlInfo, node, getSide(subComponentName)));
}
}
} else {
// node outside any voltageLevel graph (multi-terminal node)
Node feederNode = null;
if (node instanceof Middle2WTNode) {
feederNode = getFeederNode((Middle2WTNode) node, subComponentName);
} else if (node instanceof Middle3WTNode) {
feederNode = getFeederNode((Middle3WTNode) node, subComponentName);
}
if (feederNode != null) {
styles.addAll(getNodeStyles(graph.getVoltageLevelInfos(feederNode), feederNode));
}
}
return styles;
}
/**
* Returns the list of styles to apply to the given node
*
* @param vlInfo the VoltageLevelInfos related to the given node
* @param node the node on which the styles if any are applied to
* @return the list of node styles
*/
public abstract List<String> getNodeStyles(VoltageLevelInfos vlInfo, Node node);
public abstract List<String> getNodeStyles(VoltageLevelInfos vlInfo, Node node, NodeSide side);
private Node getFeederNode(Middle3WTNode node, String subComponentName) {
switch (subComponentName) {
case WINDING1, ARROW1: return node.getAdjacentNode(Middle3WTNode.Winding.UPPER_LEFT);
case WINDING2, ARROW2: return node.getAdjacentNode(Middle3WTNode.Winding.UPPER_RIGHT);
case WINDING3, ARROW3: return node.getAdjacentNode(Middle3WTNode.Winding.DOWN);
default: throw new IllegalStateException("Unexpected subComponent name: " + subComponentName);
}
}
private Node getFeederNode(Middle2WTNode node, String subComponentName) {
return node.getAdjacentNodes().get(subComponentName.equals(WINDING1) ? 0 : 1);
}
protected VoltageLevelInfos getSubComponentVoltageLevelInfos(FeederWithSides feederWs, String subComponentName) {
if (subComponentName.equals(WINDING2)) {
return feederWs.getOtherSideVoltageLevelInfos();
} else {
return feederWs.getVoltageLevelInfos();
}
}
protected NodeSide getSide(String subComponentName) {
return subComponentName.equals(WINDING2) ? NodeSide.TWO : NodeSide.ONE;
}
protected VoltageLevelInfos getSubComponentVoltageLevelInfos(Middle3WTNode node, String subComponentName) {
switch (subComponentName) {
case WINDING1, ARROW1: return node.getVoltageLevelInfos(Middle3WTNode.Winding.UPPER_LEFT);
case WINDING2, ARROW2: return node.getVoltageLevelInfos(Middle3WTNode.Winding.UPPER_RIGHT);
case WINDING3, ARROW3: return node.getVoltageLevelInfos(Middle3WTNode.Winding.DOWN);
default: return null; // for decorators
}
}
@Override
public List<String> getBusInfoStyle(BusInfo info) {
return Collections.emptyList();
}
}