Skip to content

Commit 240b540

Browse files
committed
Refacto: Replace manual parsing with XSD parsing for XML VirtualHubs configuration importer
Signed-off-by: Vincent BOCHET <vincent.bochet@rte-france.com>
1 parent 0166cf1 commit 240b540

5 files changed

Lines changed: 1086 additions & 80 deletions

File tree

data/virtual-hubs/virtual-hubs-xml/pom.xml

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,53 @@
1515
<name>Virtual hubs XML converter</name>
1616
<description>Conversion between XML data and virtual hubs</description>
1717

18+
<build>
19+
<plugins>
20+
<plugin>
21+
<groupId>org.jvnet.jaxb</groupId>
22+
<artifactId>jaxb-maven-plugin</artifactId>
23+
<configuration>
24+
<extension>true</extension>
25+
<args>
26+
<arg>-Xinheritance</arg>
27+
</args>
28+
<plugins>
29+
<plugin>
30+
<groupId>org.jvnet.jaxb</groupId>
31+
<artifactId>jaxb-plugins</artifactId>
32+
<version>${maven.jvnet.jaxb.version}</version>
33+
</plugin>
34+
</plugins>
35+
</configuration>
36+
</plugin>
37+
</plugins>
38+
</build>
39+
1840
<dependencies>
1941
<dependency>
2042
<groupId>${project.groupId}</groupId>
2143
<artifactId>open-rao-virtual-hubs-api</artifactId>
2244
<version>${project.version}</version>
2345
</dependency>
46+
<dependency>
47+
<groupId>jakarta.xml.bind</groupId>
48+
<artifactId>jakarta.xml.bind-api</artifactId>
49+
</dependency>
2450

51+
<!-- Runtime dependencies -->
52+
<dependency>
53+
<groupId>org.glassfish.jaxb</groupId>
54+
<artifactId>jaxb-runtime</artifactId>
55+
<scope>runtime</scope>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.jvnet.jaxb</groupId>
59+
<artifactId>jaxb-plugins-runtime</artifactId>
60+
<version>${maven.jvnet.jaxb.version}</version>
61+
<scope>runtime</scope>
62+
</dependency>
63+
64+
<!-- Test dependencies -->
2565
<dependency>
2666
<groupId>org.junit.jupiter</groupId>
2767
<artifactId>junit-jupiter-api</artifactId>
@@ -37,5 +77,4 @@
3777
<artifactId>assertj-core</artifactId>
3878
</dependency>
3979
</dependencies>
40-
4180
</project>

data/virtual-hubs/virtual-hubs-xml/src/main/java/com/powsybl/openrao/virtualhubs/xml/VirtualHubsConfigurationImporter.java

Lines changed: 79 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,24 @@
1414
import com.powsybl.openrao.virtualhubs.MarketArea;
1515
import com.powsybl.openrao.virtualhubs.VirtualHub;
1616
import com.powsybl.openrao.virtualhubs.VirtualHubsConfiguration;
17-
import org.w3c.dom.Document;
18-
import org.w3c.dom.Element;
19-
import org.w3c.dom.NamedNodeMap;
20-
import org.w3c.dom.Node;
21-
import org.w3c.dom.NodeList;
22-
import org.xml.sax.SAXException;
23-
24-
import javax.xml.parsers.DocumentBuilder;
25-
import javax.xml.parsers.DocumentBuilderFactory;
26-
import javax.xml.parsers.ParserConfigurationException;
27-
import java.io.IOException;
17+
import com.powsybl.openrao.virtualhubs.xml.xsd.BorderDirections;
18+
import com.powsybl.openrao.virtualhubs.xml.xsd.Configuration;
19+
import com.powsybl.openrao.virtualhubs.xml.xsd.ConverterListType;
20+
import com.powsybl.openrao.virtualhubs.xml.xsd.HVDCType;
21+
import com.powsybl.openrao.virtualhubs.xml.xsd.InternalHVDCs;
22+
import com.powsybl.openrao.virtualhubs.xml.xsd.LineListType;
23+
import com.powsybl.openrao.virtualhubs.xml.xsd.MarketAreas;
24+
import com.powsybl.openrao.virtualhubs.xml.xsd.PoleType;
25+
import com.powsybl.openrao.virtualhubs.xml.xsd.VirtualHubs;
26+
import jakarta.xml.bind.JAXBContext;
27+
import jakarta.xml.bind.JAXBElement;
28+
import jakarta.xml.bind.JAXBException;
29+
import jakarta.xml.bind.Unmarshaller;
30+
2831
import java.io.InputStream;
32+
import java.io.Serializable;
2933
import java.util.ArrayList;
34+
import java.util.Collection;
3035
import java.util.List;
3136
import java.util.Map;
3237
import java.util.Objects;
@@ -35,85 +40,88 @@
3540

3641
/**
3742
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
43+
* @author Vincent Bochet {@literal <vincent.bochet at rte-france.com>}
3844
*/
3945
class VirtualHubsConfigurationImporter {
4046
public VirtualHubsConfiguration importConfiguration(InputStream inputStream) {
4147
Objects.requireNonNull(inputStream, "Cannot import configuration from null input stream");
48+
4249
try {
43-
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
44-
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
45-
final DocumentBuilder builder = factory.newDocumentBuilder();
46-
final Document document = builder.parse(inputStream);
47-
final Element configurationEl = document.getDocumentElement();
48-
final NodeList marketAreas = configurationEl.getElementsByTagName("MarketArea");
49-
final NodeList virtualHubs = configurationEl.getElementsByTagName("VirtualHub");
50-
final NodeList borderDirections = configurationEl.getElementsByTagName("BorderDirection");
51-
final NodeList internalHvdcs = configurationEl.getElementsByTagName("HVDC");
52-
final Map<String, MarketArea> marketAreasMap = new TreeMap<>();
50+
final JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class);
51+
final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
52+
final Configuration unmarshalled = (Configuration) jaxbUnmarshaller.unmarshal(inputStream);
5353

54+
final Map<String, MarketArea> marketAreasMap = new TreeMap<>();
5455
final VirtualHubsConfiguration configuration = new VirtualHubsConfiguration();
5556

56-
importMarketAreas(marketAreas, marketAreasMap, configuration);
57-
importVirtualHubs(virtualHubs, marketAreasMap, configuration);
58-
importBorderDirections(borderDirections, configuration);
59-
importInternalHvdcs(internalHvdcs, configuration);
57+
final MarketAreas marketAreas = unmarshalled.getMarketAreas();
58+
if (marketAreas != null) {
59+
importMarketAreas(marketAreas.getMarketArea(), marketAreasMap, configuration);
60+
}
61+
62+
final VirtualHubs virtualHubs = unmarshalled.getVirtualHubs();
63+
if (virtualHubs != null) {
64+
importVirtualHubs(virtualHubs.getVirtualHub(), marketAreasMap, configuration);
65+
}
66+
67+
final BorderDirections borderDirections = unmarshalled.getBorderDirections();
68+
if (borderDirections != null) {
69+
importBorderDirections(borderDirections.getBorderDirection(), configuration);
70+
}
71+
72+
final InternalHVDCs internalHvdcs = unmarshalled.getInternalHVDCs();
73+
if (internalHvdcs != null) {
74+
importInternalHvdcs(internalHvdcs.getHVDC(), configuration);
75+
}
6076

6177
return configuration;
62-
} catch (ParserConfigurationException | SAXException | IOException e) {
78+
} catch (JAXBException e) {
6379
throw new VirtualHubsConfigProcessingException(e);
6480
}
6581
}
6682

67-
private static void importMarketAreas(final NodeList marketAreas, final Map<String, MarketArea> marketAreasMap, final VirtualHubsConfiguration configuration) {
68-
for (int marketAreaIndex = 0; marketAreaIndex < marketAreas.getLength(); marketAreaIndex++) {
69-
final Node node = marketAreas.item(marketAreaIndex);
70-
final String code = node.getAttributes().getNamedItem("Code").getNodeValue();
71-
final String eic = node.getAttributes().getNamedItem("Eic").getNodeValue();
72-
final boolean isMcParticipant = Boolean.parseBoolean(node.getAttributes().getNamedItem("MCParticipant").getNodeValue());
73-
final boolean isAhc = getAhc(node);
83+
private static void importMarketAreas(final List<com.powsybl.openrao.virtualhubs.xml.xsd.MarketArea> rawMarketAreas, final Map<String, MarketArea> marketAreasMap, final VirtualHubsConfiguration configuration) {
84+
for (com.powsybl.openrao.virtualhubs.xml.xsd.MarketArea rawMarketArea : rawMarketAreas) {
85+
final String code = rawMarketArea.getCode();
86+
final String eic = rawMarketArea.getEic();
87+
final boolean isMcParticipant = rawMarketArea.isMCParticipant();
88+
final boolean isAhc = Optional.ofNullable(rawMarketArea.isAHC()).orElse(false);
7489
final MarketArea marketArea = new MarketArea(code, eic, isMcParticipant, isAhc);
7590
marketAreasMap.put(code, marketArea);
7691
configuration.addMarketArea(marketArea);
7792
}
7893
}
7994

80-
private static void importVirtualHubs(final NodeList virtualHubs, final Map<String, MarketArea> marketAreasMap, final VirtualHubsConfiguration configuration) {
81-
for (int virtualHubIndex = 0; virtualHubIndex < virtualHubs.getLength(); virtualHubIndex++) {
82-
final Node node = virtualHubs.item(virtualHubIndex);
83-
final String code = node.getAttributes().getNamedItem("Code").getNodeValue();
84-
final String eic = node.getAttributes().getNamedItem("Eic").getNodeValue();
85-
final boolean isMcParticipant = Boolean.parseBoolean(node.getAttributes().getNamedItem("MCParticipant").getNodeValue());
86-
final boolean isAhc = getAhc(node);
87-
final Node nodeNameItem = node.getAttributes().getNamedItem("NodeName");
88-
final String nodeName = nodeNameItem != null ? nodeNameItem.getNodeValue() : null;
89-
final MarketArea marketArea = marketAreasMap.get(node.getAttributes().getNamedItem("RelatedMA").getNodeValue());
90-
final String oppositeHub = Optional.ofNullable(node.getAttributes().getNamedItem("OppositeHub")).map(Node::getNodeValue).orElse(null);
95+
private static void importVirtualHubs(final List<com.powsybl.openrao.virtualhubs.xml.xsd.VirtualHub> rawVirtualHubs, final Map<String, MarketArea> marketAreasMap, final VirtualHubsConfiguration configuration) {
96+
for (com.powsybl.openrao.virtualhubs.xml.xsd.VirtualHub rawVirtualHub : rawVirtualHubs) {
97+
final String code = rawVirtualHub.getCode();
98+
final String eic = rawVirtualHub.getEic();
99+
final boolean isMcParticipant = rawVirtualHub.isMCParticipant();
100+
final boolean isAhc = Optional.ofNullable(rawVirtualHub.isAHC()).orElse(false);
101+
final String nodeName = rawVirtualHub.getNodeName();
102+
final MarketArea marketArea = marketAreasMap.get(rawVirtualHub.getRelatedMA());
103+
final String oppositeHub = rawVirtualHub.getOppositeHub();
91104
configuration.addVirtualHub(new VirtualHub(code, eic, isMcParticipant, isAhc, nodeName, marketArea, oppositeHub));
92105
}
93106
}
94107

95-
private static void importBorderDirections(final NodeList borderDirections, final VirtualHubsConfiguration configuration) {
96-
for (int borderDirectionIndex = 0; borderDirectionIndex < borderDirections.getLength(); borderDirectionIndex++) {
97-
final Node node = borderDirections.item(borderDirectionIndex);
98-
final String from = node.getAttributes().getNamedItem("From").getNodeValue();
99-
final String to = node.getAttributes().getNamedItem("To").getNodeValue();
100-
final boolean isAhc = getAhc(node);
108+
private static void importBorderDirections(final List<com.powsybl.openrao.virtualhubs.xml.xsd.BorderDirection> rawBorderDirections, final VirtualHubsConfiguration configuration) {
109+
for (com.powsybl.openrao.virtualhubs.xml.xsd.BorderDirection rawBorderDirection : rawBorderDirections) {
110+
final String from = rawBorderDirection.getFrom();
111+
final String to = rawBorderDirection.getTo();
112+
final boolean isAhc = Optional.ofNullable(rawBorderDirection.isAHC()).orElse(false);
101113
configuration.addBorderDirection(new BorderDirection(from, to, isAhc));
102114
}
103115
}
104116

105-
private static void importInternalHvdcs(final NodeList internalHvdcs, final VirtualHubsConfiguration configuration) {
106-
for (int internalHvdcIndex = 0; internalHvdcIndex < internalHvdcs.getLength(); internalHvdcIndex++) {
107-
final Element hvdcNode = (Element) internalHvdcs.item(internalHvdcIndex);
108-
final NodeList poles = hvdcNode.getElementsByTagName("pole");
109-
final Element pole1 = (Element) poles.item(0);
110-
final Element pole2 = (Element) poles.item(1); // null if there is no such element
111-
importHvdcPoleConfiguration(pole1, configuration);
112-
importHvdcPoleConfiguration(pole2, configuration);
113-
}
117+
private static void importInternalHvdcs(final List<HVDCType> internalHvdcs, final VirtualHubsConfiguration configuration) {
118+
internalHvdcs.stream()
119+
.map(HVDCType::getPole)
120+
.flatMap(Collection::stream)
121+
.forEach(pole -> importHvdcPoleConfiguration(pole, configuration));
114122
}
115123

116-
private static void importHvdcPoleConfiguration(final Element pole, final VirtualHubsConfiguration configuration) {
124+
private static void importHvdcPoleConfiguration(final PoleType pole, final VirtualHubsConfiguration configuration) {
117125
if (pole == null) {
118126
return;
119127
}
@@ -122,26 +130,20 @@ private static void importHvdcPoleConfiguration(final Element pole, final Virtua
122130
final List<HvdcLine> hvdcLines = new ArrayList<>();
123131

124132
// HVDC -> pole -> converterList -> converter (node, station)
125-
final NodeList converters = pole.getElementsByTagName("converter");
126-
for (int converterIndex = 0; converterIndex < converters.getLength(); converterIndex++) {
127-
final NamedNodeMap hvdcConverterAttributes = converters.item(converterIndex).getAttributes();
128-
hvdcConverters.add(new HvdcConverter(
129-
hvdcConverterAttributes.getNamedItem("node").getNodeValue(),
130-
hvdcConverterAttributes.getNamedItem("station").getNodeValue()));
133+
final List<Serializable> converters = pole.getConverterList().getContent();
134+
for (Serializable serializableConverter : converters) {
135+
if (serializableConverter instanceof JAXBElement<?> element && element.getValue() instanceof ConverterListType.Converter converter) {
136+
hvdcConverters.add(new HvdcConverter(converter.getNode(), converter.getStation()));
137+
}
131138
}
132139
// HVDC -> pole -> lineList -> line (from, to)
133-
final NamedNodeMap hvdcLineAttributes = pole.getElementsByTagName("line").item(0).getAttributes();
134-
hvdcLines.add(new HvdcLine(
135-
hvdcLineAttributes.getNamedItem("from").getNodeValue(),
136-
hvdcLineAttributes.getNamedItem("to").getNodeValue()));
140+
final List<Serializable> lineLists = pole.getLineList().getContent();
141+
for (Serializable serializableConverter : lineLists) {
142+
if (serializableConverter instanceof JAXBElement<?> element && element.getValue() instanceof LineListType.Line hvdcLine) {
143+
hvdcLines.add(new HvdcLine(hvdcLine.getFrom(), hvdcLine.getTo()));
144+
}
145+
}
137146

138147
configuration.addInternalHvdc(new InternalHvdc(hvdcConverters, hvdcLines));
139148
}
140-
141-
private static Boolean getAhc(Node node) {
142-
return Optional.ofNullable(node.getAttributes().getNamedItem("AHC"))
143-
.map(Node::getNodeValue)
144-
.map(Boolean::parseBoolean)
145-
.orElse(false);
146-
}
147149
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jxb:bindings version="3.0"
3+
xmlns:jxb="https://jakarta.ee/xml/ns/jaxb"
4+
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
5+
xmlns:xs="http://www.w3.org/2001/XMLSchema">
6+
<jxb:bindings schemaLocation="../xsd/configuration-25.xsd">
7+
<jxb:schemaBindings>
8+
<jxb:package name="com.powsybl.openrao.virtualhubs.xml.xsd" />
9+
</jxb:schemaBindings>
10+
</jxb:bindings>
11+
</jxb:bindings>

0 commit comments

Comments
 (0)