Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring XML IIDM serialization classes #2481

Merged
merged 6 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright (c) 2023, 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.iidm.xml;

import com.google.common.base.Supplier;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.xml.XmlUtil;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.IdentifiableAdder;
import com.powsybl.iidm.xml.util.IidmXmlUtil;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
* @author Miora Vedelago <miora.ralambotiana at rte-france.com>
*/
abstract class AbstractComplexIdentifiableXml<T extends Identifiable, A extends IdentifiableAdder<A>, P extends Identifiable> extends AbstractIdentifiableXml<T, A, P> {

protected void readUntilEndRootElement(XMLStreamReader reader, XmlUtil.XmlEventHandler eventHandler) throws XMLStreamException {
XmlUtil.readUntilEndElement(getRootElementName(), reader, eventHandler);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some code duplicates, like here, or in read (getting id, name and fictitious), or maybe also readSubElements. Shouldn't we factorize them? That would lead to some utils method in AbstractIdentifiableXml. You didn't do it because you didn't want to put any reading in AbstractIdentifiableXml?


protected abstract void readRootElementAttributes(A adder, List<Consumer<T>> toApply, NetworkXmlReaderContext context);

protected void readSubElements(String id, A adder, List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
if (context.getReader().getLocalName().equals(PropertiesXml.PROPERTY)) {
PropertiesXml.read(toApply, context);
} else if (context.getReader().getLocalName().equals(AliasesXml.ALIAS)) {
IidmXmlUtil.assertMinimumVersion(getRootElementName(), AliasesXml.ALIAS, IidmXmlUtil.ErrorMessage.NOT_SUPPORTED, IidmXmlVersion.V_1_3, context);
AliasesXml.read(toApply, context);
} else {
throw new PowsyblException("Unknown element name <" + context.getReader().getLocalName() + "> in <" + id + ">");
}
}

protected void readElement(String id, A adder, List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
readRootElementAttributes(adder, toApply, context);
readSubElements(id, adder, toApply, context);
}

protected void apply(T identifiable, List<Consumer<T>> toApply) {
toApply.forEach(consumer -> consumer.accept(identifiable));
}

public final void read(Supplier<A> createAdder, Function<A, T> create, NetworkXmlReaderContext context) throws XMLStreamException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could do as the simple one for creating the adder, that is adding a createAdder(voltageLevel), which could therefore remain in AbstractIdentifiableXml. And then we could also leave in AbstractIdentifiableXml an abstract read(P, NetworkXmlReaderContext).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot the Function<A, T> create which is needed. We could do the same, that is, an abstract method which returns the adder. Or, better! in fact we could write adder.add() as I'd really like to add add methods in the Adders

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this PR, if your change in IIDM network is not passed, I will create an abstract method to add but I'm keeping it in mind!

List<Consumer<T>> toApply = new ArrayList<>();
A adder = read(createAdder, toApply, context);
T identifiable = create.apply(adder);
apply(identifiable, toApply);
}

public final A read(Supplier<A> createAdder, List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
A adder = createAdder.get();
read(adder, toApply, context);
return adder;
}

private void read(A adder, List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
String id = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "id"));
String name = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "name"));
adder.setId(id)
.setName(name);
IidmXmlUtil.runFromMinimumVersion(IidmXmlVersion.V_1_2, context, () -> {
boolean fictitious = XmlUtil.readOptionalBoolAttribute(context.getReader(), "fictitious", false);
adder.setFictitious(fictitious);
});
readElement(id, adder, toApply, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
*/
package com.powsybl.iidm.xml;

import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.exceptions.UncheckedXmlStreamException;
import com.powsybl.commons.xml.XmlUtil;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.IdentifiableAdder;
import com.powsybl.iidm.xml.util.IidmXmlUtil;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

/**
*
Expand Down Expand Up @@ -79,43 +77,4 @@ public final void write(T identifiable, P parent, NetworkXmlWriterContext contex

context.addExportedEquipment(identifiable);
}

protected void readUntilEndRootElement(XMLStreamReader reader, XmlUtil.XmlEventHandler eventHandler) throws XMLStreamException {
XmlUtil.readUntilEndElement(getRootElementName(), reader, eventHandler);
}

protected abstract A createAdder(P parent);

protected abstract T readRootElementAttributes(A adder, NetworkXmlReaderContext context);

protected void readSubElements(T identifiable, NetworkXmlReaderContext context) throws XMLStreamException {
if (context.getReader().getLocalName().equals(PropertiesXml.PROPERTY)) {
PropertiesXml.read(identifiable, context);
} else if (context.getReader().getLocalName().equals(AliasesXml.ALIAS)) {
IidmXmlUtil.assertMinimumVersion(getRootElementName(), AliasesXml.ALIAS, IidmXmlUtil.ErrorMessage.NOT_SUPPORTED, IidmXmlVersion.V_1_3, context);
AliasesXml.read(identifiable, context);
} else {
throw new PowsyblException("Unknown element name <" + context.getReader().getLocalName() + "> in <" + identifiable.getId() + ">");
}
}

protected void readElement(String id, A adder, NetworkXmlReaderContext context) throws XMLStreamException {
T identifiable = readRootElementAttributes(adder, context);
if (identifiable != null) {
readSubElements(identifiable, context);
}
}

public final void read(P parent, NetworkXmlReaderContext context) throws XMLStreamException {
A adder = createAdder(parent);
String id = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "id"));
String name = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "name"));
adder.setId(id)
.setName(name);
IidmXmlUtil.runFromMinimumVersion(IidmXmlVersion.V_1_2, context, () -> {
boolean fictitious = XmlUtil.readOptionalBoolAttribute(context.getReader(), "fictitious", false);
adder.setFictitious(fictitious);
});
readElement(id, adder, context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* Copyright (c) 2023, 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.iidm.xml;

import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.xml.XmlUtil;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.IdentifiableAdder;
import com.powsybl.iidm.xml.util.IidmXmlUtil;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

/**
* @author Miora Vedelago <miora.ralambotiana at rte-france.com>
*/
abstract class AbstractSimpleIdentifiableXml<T extends Identifiable, A extends IdentifiableAdder<A>, P extends Identifiable> extends AbstractIdentifiableXml<T, A, P> {

protected void readUntilEndRootElement(XMLStreamReader reader, XmlUtil.XmlEventHandler eventHandler) throws XMLStreamException {
XmlUtil.readUntilEndElement(getRootElementName(), reader, eventHandler);
}

protected abstract A createAdder(P parent);

protected abstract T readRootElementAttributes(A adder, NetworkXmlReaderContext context);

protected void readSubElements(T identifiable, NetworkXmlReaderContext context) throws XMLStreamException {
if (context.getReader().getLocalName().equals(PropertiesXml.PROPERTY)) {
PropertiesXml.read(identifiable, context);
} else if (context.getReader().getLocalName().equals(AliasesXml.ALIAS)) {
IidmXmlUtil.assertMinimumVersion(getRootElementName(), AliasesXml.ALIAS, IidmXmlUtil.ErrorMessage.NOT_SUPPORTED, IidmXmlVersion.V_1_3, context);
AliasesXml.read(identifiable, context);
} else {
throw new PowsyblException("Unknown element name <" + context.getReader().getLocalName() + "> in <" + identifiable.getId() + ">");
}
}

protected void readElement(String id, A adder, NetworkXmlReaderContext context) throws XMLStreamException {
T identifiable = readRootElementAttributes(adder, context);
if (identifiable != null) {
readSubElements(identifiable, context);
}
}

public final void read(P parent, NetworkXmlReaderContext context) throws XMLStreamException {
A adder = createAdder(parent);
String id = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "id"));
String name = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "name"));
adder.setId(id)
.setName(name);
IidmXmlUtil.runFromMinimumVersion(IidmXmlVersion.V_1_2, context, () -> {
boolean fictitious = XmlUtil.readOptionalBoolAttribute(context.getReader(), "fictitious", false);
adder.setFictitious(fictitious);
});
readElement(id, adder, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
abstract class AbstractSwitchXml<A extends IdentifiableAdder<A>> extends AbstractIdentifiableXml<Switch, A, VoltageLevel> {
abstract class AbstractSwitchXml<A extends IdentifiableAdder<A>> extends AbstractSimpleIdentifiableXml<Switch, A, VoltageLevel> {

static final String ROOT_ELEMENT_NAME = "switch";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
abstract class AbstractTransformerXml<T extends Connectable, A extends IdentifiableAdder<A>> extends AbstractConnectableXml<T, A, Container<? extends Identifiable<?>>> {
abstract class AbstractTransformerXml<T extends Connectable, A extends IdentifiableAdder<A>> extends AbstractSimpleIdentifiableXml<T, A, Container<? extends Identifiable<?>>> {

private interface StepConsumer {
void accept(double r, double x, double g, double b, double rho);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.powsybl.iidm.xml.util.IidmXmlUtil;

import javax.xml.stream.XMLStreamException;
import java.util.List;
import java.util.function.Consumer;

/**
* @author Sebastien Murgey <sebastien.murgey at rte-france.com>
Expand All @@ -35,7 +37,7 @@ public static void write(Identifiable<?> identifiable, String rootElementName, N
}
}

public static void read(Identifiable<?> identifiable, NetworkXmlReaderContext context) throws XMLStreamException {
public static <T extends Identifiable> void read(T identifiable, NetworkXmlReaderContext context) throws XMLStreamException {
if (!context.getReader().getLocalName().equals(ALIAS)) {
throw new IllegalStateException();
}
Expand All @@ -45,6 +47,16 @@ public static void read(Identifiable<?> identifiable, NetworkXmlReaderContext co
identifiable.addAlias(alias, aliasType[0]);
}

public static <T extends Identifiable> void read(List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
if (!context.getReader().getLocalName().equals(ALIAS)) {
throw new IllegalStateException();
}
String[] aliasType = new String[1];
IidmXmlUtil.runFromMinimumVersion(IidmXmlVersion.V_1_4, context, () -> aliasType[0] = context.getReader().getAttributeValue(null, "type"));
String alias = context.getAnonymizer().deanonymizeString(context.getReader().getElementText());
toApply.add(identifiable -> identifiable.addAlias(alias, aliasType[0]));
}

private AliasesXml() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

import javax.xml.stream.XMLStreamException;

import static com.powsybl.iidm.xml.ConnectableXmlUtil.*;

/**
* @author Ghiles Abdellah <ghiles.abdellah at rte-france.com>
*/
class BatteryXml extends AbstractConnectableXml<Battery, BatteryAdder, VoltageLevel> {
class BatteryXml extends AbstractSimpleIdentifiableXml<Battery, BatteryAdder, VoltageLevel> {

static final BatteryXml INSTANCE = new BatteryXml();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
class BusXml extends AbstractIdentifiableXml<Bus, BusAdder, VoltageLevel> {
class BusXml extends AbstractSimpleIdentifiableXml<Bus, BusAdder, VoltageLevel> {

static final BusXml INSTANCE = new BusXml();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
class BusbarSectionXml extends AbstractIdentifiableXml<BusbarSection, BusbarSectionAdder, VoltageLevel> {
class BusbarSectionXml extends AbstractSimpleIdentifiableXml<BusbarSection, BusbarSectionAdder, VoltageLevel> {

static final BusbarSectionXml INSTANCE = new BusbarSectionXml();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
public abstract class AbstractConnectableXml<T extends Connectable, A extends IdentifiableAdder<A>, P extends Container> extends AbstractIdentifiableXml<T, A, P> {
public final class ConnectableXmlUtil {

private ConnectableXmlUtil() {
}

private static final String BUS = "bus";
private static final String CONNECTABLE_BUS = "connectableBus";
Expand All @@ -39,21 +42,21 @@ private static String indexToString(Integer index) {
return index != null ? index.toString() : "";
}

protected static boolean hasValidOperationalLimits(Branch<?> branch, NetworkXmlWriterContext context) {
public static boolean hasValidOperationalLimits(Branch<?> branch, NetworkXmlWriterContext context) {
if (context.getVersion().compareTo(IidmXmlVersion.V_1_5) >= 0) {
return !branch.getOperationalLimits1().isEmpty() || !branch.getOperationalLimits2().isEmpty();
}
return branch.getCurrentLimits1().isPresent() || branch.getCurrentLimits2().isPresent();
}

protected static boolean hasValidOperationalLimits(FlowsLimitsHolder limitsHolder, NetworkXmlWriterContext context) {
public static boolean hasValidOperationalLimits(FlowsLimitsHolder limitsHolder, NetworkXmlWriterContext context) {
if (context.getVersion().compareTo(IidmXmlVersion.V_1_5) >= 0) {
return !limitsHolder.getOperationalLimits().isEmpty();
}
return limitsHolder.getCurrentLimits().isPresent();
}

protected static void writeNodeOrBus(Integer index, Terminal t, NetworkXmlWriterContext context) throws XMLStreamException {
public static void writeNodeOrBus(Integer index, Terminal t, NetworkXmlWriterContext context) throws XMLStreamException {
TopologyLevel topologyLevel = TopologyLevel.min(t.getVoltageLevel().getTopologyKind(), context.getOptions().getTopologyLevel());
switch (topologyLevel) {
case NODE_BREAKER:
Expand Down Expand Up @@ -88,7 +91,7 @@ private static void writeBus(Integer index, Bus bus, Bus connectableBus, Network
}
}

protected static void readNodeOrBus(InjectionAdder adder, NetworkXmlReaderContext context) {
public static void readNodeOrBus(InjectionAdder adder, NetworkXmlReaderContext context) {
String bus = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, BUS));
String connectableBus = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, CONNECTABLE_BUS));
Integer node = XmlUtil.readOptionalIntegerAttribute(context.getReader(), NODE);
Expand All @@ -103,7 +106,7 @@ protected static void readNodeOrBus(InjectionAdder adder, NetworkXmlReaderContex
}
}

protected static void readNodeOrBus(BranchAdder adder, NetworkXmlReaderContext context) {
public static void readNodeOrBus(BranchAdder adder, NetworkXmlReaderContext context) {
String bus1 = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "bus1"));
String connectableBus1 = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, "connectableBus1"));
Integer node1 = XmlUtil.readOptionalIntegerAttribute(context.getReader(), "node1");
Expand Down Expand Up @@ -134,7 +137,7 @@ protected static void readNodeOrBus(BranchAdder adder, NetworkXmlReaderContext c
adder.setVoltageLevel2(voltageLevelId2);
}

protected static void readNodeOrBus(int index, LegAdder adder, NetworkXmlReaderContext context) {
public static void readNodeOrBus(int index, LegAdder adder, NetworkXmlReaderContext context) {
String bus = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, BUS + index));
String connectableBus = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(null, CONNECTABLE_BUS + index));
Integer node = XmlUtil.readOptionalIntegerAttribute(context.getReader(), NODE + index);
Expand All @@ -151,12 +154,12 @@ protected static void readNodeOrBus(int index, LegAdder adder, NetworkXmlReaderC
adder.setVoltageLevel(voltageLevelId);
}

protected static void writePQ(Integer index, Terminal t, XMLStreamWriter writer) throws XMLStreamException {
public static void writePQ(Integer index, Terminal t, XMLStreamWriter writer) throws XMLStreamException {
XmlUtil.writeOptionalDouble("p" + indexToString(index), t.getP(), Double.NaN, writer);
XmlUtil.writeOptionalDouble("q" + indexToString(index), t.getQ(), Double.NaN, writer);
}

protected static void readPQ(Integer index, Terminal t, XMLStreamReader reader) {
public static void readPQ(Integer index, Terminal t, XMLStreamReader reader) {
double p = XmlUtil.readOptionalDoubleAttribute(reader, "p" + indexToString(index));
double q = XmlUtil.readOptionalDoubleAttribute(reader, "q" + indexToString(index));
t.setP(p)
Expand Down Expand Up @@ -268,15 +271,15 @@ private static <L extends LoadingLimits> void writeLoadingLimits(Integer index,
* @deprecated Use {@link TerminalRefXml#writeTerminalRef(Terminal, NetworkXmlWriterContext, String)} instead.
*/
@Deprecated
protected static void writeTerminalRef(Terminal t, NetworkXmlWriterContext context, String elementName) throws XMLStreamException {
public static void writeTerminalRef(Terminal t, NetworkXmlWriterContext context, String elementName) throws XMLStreamException {
TerminalRefXml.writeTerminalRef(t, context, elementName);
}

/**
* @deprecated Use {@link TerminalRefXml#readTerminalRef(Network, String, String)} instead.
*/
@Deprecated
protected static Terminal readTerminalRef(Network network, String id, String side) {
public static Terminal readTerminalRef(Network network, String id, String side) {
return TerminalRefXml.readTerminalRef(network, id, side);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
import javax.xml.stream.XMLStreamException;
import java.util.Optional;

import static com.powsybl.iidm.xml.ConnectableXmlUtil.*;

/**
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
class DanglingLineXml extends AbstractConnectableXml<DanglingLine, DanglingLineAdder, VoltageLevel> {
class DanglingLineXml extends AbstractSimpleIdentifiableXml<DanglingLine, DanglingLineAdder, VoltageLevel> {
private static final String GENERATION = "generation";
private static final String GENERATION_MAX_P = "generationMaxP";
private static final String GENERATION_MIN_P = "generationMinP";
Expand Down
Loading