Skip to content

Commit b899700

Browse files
author
Dennis Labordus
authored
Merge pull request #119 from com-pas/group-bays
Combine all equipment of a bay in one container
2 parents c7072df + 909b1e9 commit b899700

File tree

6 files changed

+7648
-5181
lines changed

6 files changed

+7648
-5181
lines changed

service/src/main/java/org/lfenergy/compas/scl/auto/alignment/builder/VoltageLevelGraphBuilder.java

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,22 @@ private void createVoltageLevel() {
4141
var busbarIndex = new AtomicInteger(1);
4242
voltageLevel.getBays().stream()
4343
.filter(GenericBay::isBusbar)
44-
.forEach(busbar -> processBusbarNode(busbar, busbarIndex));
44+
.forEach(busbar -> processBusbarNode(busbar, busbarIndex.getAndIncrement()));
4545

4646
// Next process the other bays.
47+
var bayIndex = new AtomicInteger(1);
4748
voltageLevel.getBays().stream()
4849
.filter(bay -> !bay.isBusbar())
49-
.forEach(this::processBayNode);
50+
.forEach(bay -> processBayNode(bay, bayIndex.getAndIncrement()));
5051
}
5152

5253
private void processBusbarNode(GenericBay busbar,
53-
AtomicInteger busbarIndex) {
54+
int busbarIndex) {
5455
busbar.getConnectivityNodes()
5556
.stream().findFirst()
5657
.ifPresent(connectivityNode ->
5758
addNode(connectivityNode.getPathName(),
58-
createBusbarNode(busbar.getFullName(), busbarIndex.getAndIncrement(), 1)));
59+
createBusbarNode(busbar.getFullName(), busbarIndex, 1)));
5960
}
6061

6162
public BusNode createBusbarNode(String id, int busbarIndex, int sectionIndex) {
@@ -64,9 +65,10 @@ public BusNode createBusbarNode(String id, int busbarIndex, int sectionIndex) {
6465
return busNode;
6566
}
6667

67-
private void processBayNode(GenericBay bay) {
68+
private void processBayNode(GenericBay bay, int bayIndex) {
6869
bay.getConnectivityNodes().forEach(this::createConnectivityNode);
69-
bay.getConductingEquipments().forEach(this::processConductingEquipment);
70+
bay.getConductingEquipments().forEach(conductingEquipment ->
71+
processConductingEquipment(conductingEquipment, bayIndex));
7072
}
7173

7274
private void createConnectivityNode(GenericConnectivityNode connectivityNode) {
@@ -94,36 +96,39 @@ private Optional<GenericPowerTransformer> getPowerTransformer(String pathName) {
9496
return Optional.empty();
9597
}
9698

97-
private void processConductingEquipment(GenericConductingEquipment conductingEquipment) {
99+
private void processConductingEquipment(GenericConductingEquipment conductingEquipment, int order) {
98100
var terminals = conductingEquipment.getTerminals();
99101
var fullName = conductingEquipment.getFullName();
100-
var node = createSwitchNode(fullName);
102+
var node = createSwitchNode(fullName, order);
101103

102104
if (!terminals.isEmpty()) {
103-
Node node1 = terminalToNode(terminals.get(0));
104-
Node node2 = null;
105-
var termNb = terminals.size();
106-
if (termNb == 1) {
107-
node2 = createLoad(fullName + "/Grounded");
108-
} else if (termNb == 2) {
109-
node2 = terminalToNode(terminals.get(1));
110-
}
105+
var node1 = terminalToNode(terminals.get(0), order);
111106
connectNode(node, node1);
112-
connectNode(node, node2);
107+
108+
if (terminals.size() == 2) {
109+
var node2 = terminalToNode(terminals.get(1), order);
110+
connectNode(node, node2);
111+
} else {
112+
var node2 = createLoad(fullName + "/Grounded", order);
113+
connectNode(node, node2);
114+
}
113115
}
114116
}
115117

116-
private Node terminalToNode(GenericTerminal terminal) {
118+
private Node terminalToNode(GenericTerminal terminal, int order) {
117119
var pathName = terminal.getConnectivityNode();
118120
if (pathName != null) {
119121
return getNodeByPath(pathName);
120122
}
121-
return createLoad(terminal.getCNodeName());
123+
return createLoad(terminal.getCNodeName(), order);
122124
}
123125

124-
private SwitchNode createSwitchNode(String id) {
125-
return NodeFactory.createSwitchNode(getGraph(), id, id, SwitchNode.SwitchKind.BREAKER.name(),
126+
private SwitchNode createSwitchNode(String id, int order) {
127+
var switchNode = NodeFactory.createSwitchNode(getGraph(), id, id, SwitchNode.SwitchKind.BREAKER.name(),
126128
false, SwitchNode.SwitchKind.BREAKER, false);
129+
switchNode.setOrder(order);
130+
switchNode.setDirection(Direction.TOP);
131+
return switchNode;
127132
}
128133

129134
private void connectNode(Node node1, Node node2) {
@@ -134,9 +139,9 @@ private FictitiousNode createFictitiousNode(String id) {
134139
return NodeFactory.createFictitiousNode(getGraph(), id, id, id, ComponentTypeName.LINE);
135140
}
136141

137-
private FeederNode createLoad(String id) {
142+
private FeederNode createLoad(String id, int order) {
138143
FeederNode fn = NodeFactory.createLoad(getGraph(), id, id);
139-
commonFeederSetting(fn, id, 0, null);
144+
commonFeederSetting(fn, id, order, Direction.TOP);
140145
return fn;
141146
}
142147

service/src/test/java/org/lfenergy/compas/scl/auto/alignment/TestUtil.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,50 @@
33
// SPDX-License-Identifier: Apache-2.0
44
package org.lfenergy.compas.scl.auto.alignment;
55

6+
import javanet.staxutils.SimpleNamespaceContext;
67
import org.lfenergy.compas.core.commons.ElementConverter;
78
import org.w3c.dom.Element;
9+
import org.w3c.dom.NodeList;
810

11+
import javax.xml.xpath.XPathConstants;
12+
import javax.xml.xpath.XPathFactory;
913
import java.io.*;
1014
import java.nio.charset.StandardCharsets;
1115

12-
import static org.lfenergy.compas.scl.auto.alignment.SclAutoAlignmentConstants.SCL_ELEMENT_NAME;
13-
import static org.lfenergy.compas.scl.auto.alignment.SclAutoAlignmentConstants.SCL_NS_URI;
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
import static org.junit.jupiter.api.Assertions.assertNotNull;
18+
import static org.lfenergy.compas.scl.auto.alignment.SclAutoAlignmentConstants.*;
1419

1520
public final class TestUtil {
1621
private TestUtil() {
1722
// Only static methods.
1823
}
1924

20-
public static Element readSCLElement(String filename) throws IOException {
21-
var sclData = readSCL(filename);
25+
public static Element toElement(String sclData) throws IOException {
2226
var converter = new ElementConverter();
27+
try (var inputStream = new BufferedInputStream(
28+
new ByteArrayInputStream(sclData.getBytes(StandardCharsets.UTF_8)))) {
29+
return converter.convertToElement(inputStream, SCL_ELEMENT_NAME, SCL_NS_URI);
30+
}
31+
}
2332

24-
return converter.convertToElement(new BufferedInputStream(
25-
new ByteArrayInputStream(sclData.getBytes(StandardCharsets.UTF_8))), SCL_ELEMENT_NAME, SCL_NS_URI);
33+
public static Element readSCLElement(String filename) throws IOException {
34+
var sclData = readSCL(filename);
35+
return toElement(sclData);
2636
}
2737

2838
public static String readSCL(String filename) throws IOException {
2939
return readFile("/scl/" + filename);
3040
}
3141

3242
public static String readFile(String filename) throws IOException {
33-
var inputStream = TestUtil.class.getResourceAsStream(filename);
34-
assert inputStream != null;
43+
try (var inputStream = TestUtil.class.getResourceAsStream(filename)) {
44+
assert inputStream != null;
3545

36-
return new String(inputStream.readAllBytes());
46+
return new String(inputStream.readAllBytes());
47+
}
3748
}
3849

39-
@Deprecated
4050
public static void writeFile(String fileName, String data) {
4151
var file = new File("target", fileName);
4252
try (var fw = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
@@ -45,4 +55,20 @@ public static void writeFile(String fileName, String data) {
4555
throw new UncheckedIOException(e);
4656
}
4757
}
58+
59+
public static void assertXYCoordinates(Element rootElement, String xPathExpression, Integer x, Integer y) throws Exception {
60+
var xPath = XPathFactory.newInstance().newXPath();
61+
62+
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
63+
nsCtx.setPrefix("scl", SCL_NS_URI);
64+
xPath.setNamespaceContext(nsCtx);
65+
66+
var nodeList = (NodeList) xPath.compile(xPathExpression).evaluate(rootElement.getOwnerDocument(), XPathConstants.NODESET);
67+
assertEquals(1, nodeList.getLength());
68+
69+
var element = (Element) nodeList.item(0);
70+
assertNotNull(element);
71+
assertEquals(x.toString(), element.getAttributeNS(SCLXY_NS_URI, "x"));
72+
assertEquals(y.toString(), element.getAttributeNS(SCLXY_NS_URI, "y"));
73+
}
4874
}

service/src/test/java/org/lfenergy/compas/scl/auto/alignment/service/SclAutoAlignmentEnricherTest.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
import static org.junit.jupiter.api.Assertions.assertNotNull;
1818
import static org.lfenergy.compas.scl.auto.alignment.SclAutoAlignmentConstants.SCL_ELEMENT_NAME;
1919
import static org.lfenergy.compas.scl.auto.alignment.SclAutoAlignmentConstants.SCL_NS_URI;
20-
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.readFile;
21-
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.readSCL;
20+
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.*;
2221

2322
class SclAutoAlignmentEnricherTest {
2423
@Test
25-
void enrich_WhenPassingCase1_ThenXSDUpdated() throws IOException {
24+
void enrich_WhenPassingCase1_ThenSCDUpdated() throws Exception {
25+
// The JSON file used here is a copy created by the testcase
26+
// SclAutoAlignmentServiceTest#createJson_WhenPassingCase1_ThenJsonReturned
2627
var filename = "scl-1";
2728
var jsonString = readFile("/json/" + filename + ".json");
2829
var scl = new GenericSCL(readSCLElement(filename + ".scd"));
@@ -32,10 +33,17 @@ void enrich_WhenPassingCase1_ThenXSDUpdated() throws IOException {
3233

3334
assertNotNull(scl.getElement());
3435
writeFile(filename + "-updated.scd", scl);
36+
37+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='J1']", 2, 4);
38+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='BusBar A']", 1, 15);
39+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='Bay 1S']", 2, 13);
40+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='Bay 1S']/scl:ConductingEquipment[@name='CBR1']", 1, 1);
3541
}
3642

3743
@Test
38-
void enrich_WhenPassingCase2_ThenXSDUpdated() throws IOException {
44+
void enrich_WhenPassingCase2_ThenSCDUpdated() throws Exception {
45+
// The JSON file used here is a copy created by the testcase
46+
// SclAutoAlignmentServiceTest#createJson_WhenPassingCase2_ThenJsonReturned
3947
var filename = "scl-2";
4048
var jsonString = readFile("/json/" + filename + ".json");
4149
var scl = new GenericSCL(readSCLElement(filename + ".scd"));
@@ -45,6 +53,12 @@ void enrich_WhenPassingCase2_ThenXSDUpdated() throws IOException {
4553

4654
assertNotNull(scl.getElement());
4755
writeFile(filename + "-updated.scd", scl);
56+
57+
assertXYCoordinates(scl.getElement(), "//scl:PowerTransformer[@name='T4']", 27, 3);
58+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='S1 380kV']", 2, 7);
59+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BUSBAR10']", 1, 12);
60+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BAY_T4_2']", 1, 4);
61+
assertXYCoordinates(scl.getElement(), "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BAY_T4_2']/scl:ConductingEquipment[@name='BREAKER25']", 1, 4);
4862
}
4963

5064
private Element readSCLElement(String filename) throws IOException {

service/src/test/java/org/lfenergy/compas/scl/auto/alignment/service/SclAutoAlignmentServiceTest.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
import java.util.List;
1414

1515
import static org.junit.jupiter.api.Assertions.assertNotNull;
16-
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.readSCL;
17-
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.writeFile;
16+
import static org.lfenergy.compas.scl.auto.alignment.TestUtil.*;
1817

1918
@ExtendWith(MockitoExtension.class)
2019
class SclAutoAlignmentServiceTest {
@@ -29,27 +28,41 @@ void beforeEach() {
2928
}
3029

3130
@Test
32-
void updateSCL_WhenPassingCase1_ThenUpdatedSCLReturned() throws IOException {
31+
void updateSCL_WhenPassingCase1_ThenUpdatedSCLReturned() throws Exception {
3332
var filename = "scl-1";
3433
var sclString = readSCL(filename + ".scd");
3534

3635
var result = sclAutoAlignmentService.updateSCL(sclString, List.of("AA1"), "Mr. Editor");
3736
assertNotNull(result);
3837
writeFile(filename + "-updated-service.scd", result);
38+
39+
var rootElement = toElement(result);
40+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='J1']", 2, 4);
41+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='BusBar A']", 1, 15);
42+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='Bay 1S']", 2, 13);
43+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='J1']/scl:Bay[@name='Bay 1S']/scl:ConductingEquipment[@name='CBR1']", 1, 1);
3944
}
4045

4146
@Test
42-
void updateSCL_WhenPassingCase2_ThenUpdatedSCLReturned() throws IOException {
47+
void updateSCL_WhenPassingCase2_ThenUpdatedSCLReturned() throws Exception {
4348
var filename = "scl-2";
4449
var sclString = readSCL(filename + ".scd");
4550

4651
var result = sclAutoAlignmentService.updateSCL(sclString, List.of("_af9a4ae3-ba2e-4c34-8e47-5af894ee20f4"), "Mr. Editor");
4752
assertNotNull(result);
4853
writeFile(filename + "-updated-service.scd", result);
54+
55+
var rootElement = toElement(result);
56+
assertXYCoordinates(rootElement, "//scl:PowerTransformer[@name='T4']", 27, 3);
57+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='S1 380kV']", 2, 7);
58+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BUSBAR10']", 1, 12);
59+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BAY_T4_2']", 1, 4);
60+
assertXYCoordinates(rootElement, "//scl:VoltageLevel[@name='S1 380kV']/scl:Bay[@name='BAY_T4_2']/scl:ConductingEquipment[@name='BREAKER25']", 1, 4);
4961
}
5062

5163
@Test
5264
void getSVG_WhenPassingCase1_ThenSVGReturned() throws IOException {
65+
// Nice addition to the updateSCL Test to have a visual output from PowSyBl and check how their drawing looks.
5366
var filename = "scl-1";
5467
var sclString = readSCL(filename + ".scd");
5568

@@ -60,6 +73,7 @@ void getSVG_WhenPassingCase1_ThenSVGReturned() throws IOException {
6073

6174
@Test
6275
void getSVG_WhenPassingCase2_ThenSVGReturned() throws IOException {
76+
// Nice addition to the updateSCL Test to have a visual output from PowSyBl and check how their drawing looks.
6377
var filename = "scl-2";
6478
var sclString = readSCL(filename + ".scd");
6579

@@ -70,6 +84,8 @@ void getSVG_WhenPassingCase2_ThenSVGReturned() throws IOException {
7084

7185
@Test
7286
void createJson_WhenPassingCase1_ThenJsonReturned() throws IOException {
87+
// This just tests if the SCD File can be processed, because most of the work is done in PowSyBl.
88+
// But this way we know the GraphBuilders are still working and not missing electric components.
7389
var filename = "scl-1";
7490
var substationName = "AA1";
7591
var sclData = readSCL(filename + ".scd");
@@ -83,6 +99,8 @@ void createJson_WhenPassingCase1_ThenJsonReturned() throws IOException {
8399

84100
@Test
85101
void createJson_WhenPassingCase2_ThenJsonReturned() throws IOException {
102+
// This just tests if the SCD File can be processed, because most of the work is done in PowSyBl.
103+
// But this way we know the GraphBuilders are still working and not missing electric components.
86104
var filename = "scl-2";
87105
var substationName = "_af9a4ae3-ba2e-4c34-8e47-5af894ee20f4";
88106
var sclData = readSCL(filename + ".scd");

0 commit comments

Comments
 (0)