Skip to content

Commit

Permalink
Refactoring XML IIDM serialization classes (to prevent hacks)
Browse files Browse the repository at this point in the history
Signed-off-by: VEDELAGO MIORA <miora.ralambotiana@rte-france.com>
  • Loading branch information
miovd committed Mar 1, 2023
1 parent 1873643 commit f7f4a24
Show file tree
Hide file tree
Showing 25 changed files with 230 additions and 109 deletions.
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);
}

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 {
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,14 +37,22 @@ 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 {
assert context.getReader().getLocalName().equals(ALIAS);
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());
identifiable.addAlias(alias, aliasType[0]);
}

public static <T extends Identifiable> void read(List<Consumer<T>> toApply, NetworkXmlReaderContext context) throws XMLStreamException {
assert context.getReader().getLocalName().equals(ALIAS);
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

0 comments on commit f7f4a24

Please sign in to comment.