From cc4470ba44db86b9043aa3059ba664d462838db9 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 11:25:15 +0100 Subject: [PATCH 01/42] Remove ifs prior to calling writeStringAttribute Signed-off-by: Florian Dupuy --- .../java/com/powsybl/iidm/serde/AliasesSerDe.java | 2 +- .../powsybl/iidm/serde/ConnectableSerDeUtil.java | 12 ++++++------ .../com/powsybl/iidm/serde/DanglingLineSerDe.java | 14 ++++++-------- .../iidm/serde/StaticVarCompensatorSerDe.java | 4 +--- .../com/powsybl/iidm/serde/SubstationSerDe.java | 3 +-- .../iidm/serde/extensions/MeasurementsSerDe.java | 4 +--- 6 files changed, 16 insertions(+), 23 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AliasesSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AliasesSerDe.java index ee61fe19b5f..ce14e6dce5f 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AliasesSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AliasesSerDe.java @@ -26,7 +26,7 @@ public static void write(Identifiable identifiable, String rootElementName, N for (String alias : identifiable.getAliases()) { context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), ROOT_ELEMENT_NAME); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_4, context, - () -> identifiable.getAliasType(alias).ifPresent(type -> context.getWriter().writeStringAttribute("type", type))); + () -> context.getWriter().writeStringAttribute("type", identifiable.getAliasType(alias).orElse(null))); context.getWriter().writeNodeContent(context.getAnonymizer().anonymizeString(alias)); context.getWriter().writeEndNode(); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index c13548153a6..d370b064e38 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -13,6 +13,8 @@ import com.powsybl.iidm.network.ThreeWindingsTransformerAdder.LegAdder; import com.powsybl.iidm.serde.util.IidmSerDeUtil; +import java.util.Optional; + /** * @author Geoffroy Jamgotchian {@literal } */ @@ -82,12 +84,10 @@ private static void writeNode(Integer index, Terminal t, NetworkSerializerContex } private static void writeBus(Integer index, Bus bus, Bus connectableBus, NetworkSerializerContext context) { - if (bus != null) { - context.getWriter().writeStringAttribute(BUS + indexToString(index), context.getAnonymizer().anonymizeString(bus.getId())); - } - if (connectableBus != null) { - context.getWriter().writeStringAttribute(CONNECTABLE_BUS + indexToString(index), context.getAnonymizer().anonymizeString(connectableBus.getId())); - } + context.getWriter().writeStringAttribute(BUS + indexToString(index), + Optional.ofNullable(bus).map(b -> context.getAnonymizer().anonymizeString(b.getId())).orElse(null)); + context.getWriter().writeStringAttribute(CONNECTABLE_BUS + indexToString(index), + Optional.ofNullable(connectableBus).map(b -> context.getAnonymizer().anonymizeString(b.getId())).orElse(null)); } public static void readNodeOrBus(InjectionAdder adder, NetworkDeserializerContext context) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index eb4a40d5b9a..5fd085772c0 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -75,14 +75,12 @@ static void writeRootElementAttributesInternal(DanglingLine dl, Supplier context.getWriter().writeStringAttribute("ucteXnodeCode", dl.getPairingKey()) - ); - IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, - () -> context.getWriter().writeStringAttribute("pairingKey", dl.getPairingKey()) - ); - } + IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_10, context, + () -> context.getWriter().writeStringAttribute("ucteXnodeCode", dl.getPairingKey()) + ); + IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, + () -> context.getWriter().writeStringAttribute("pairingKey", dl.getPairingKey()) + ); writePQ(null, t, context.getWriter()); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java index 1448035c761..16c04548513 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java @@ -43,9 +43,7 @@ protected void writeRootElementAttributes(StaticVarCompensator svc, VoltageLevel context.getWriter().writeDoubleAttribute(voltageSetpointName[0], svc.getVoltageSetpoint()); context.getWriter().writeDoubleAttribute(reactivePowerSetpointName[0], svc.getReactivePowerSetpoint()); - if (svc.getRegulationMode() != null) { - context.getWriter().writeStringAttribute("regulationMode", svc.getRegulationMode().name()); - } + context.getWriter().writeEnumAttribute("regulationMode", svc.getRegulationMode()); writeNodeOrBus(null, svc.getTerminal(), context); writePQ(null, svc.getTerminal(), context.getWriter()); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java index c23a9565b0c..de0e245e536 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java @@ -31,8 +31,7 @@ protected String getRootElementName() { @Override protected void writeRootElementAttributes(Substation s, Network n, NetworkSerializerContext context) { - Optional country = s.getCountry(); - country.ifPresent(value -> context.getWriter().writeStringAttribute(COUNTRY, context.getAnonymizer().anonymizeCountry(value).toString())); + context.getWriter().writeStringAttribute(COUNTRY, s.getCountry().map(c -> context.getAnonymizer().anonymizeCountry(c).toString()).orElse(null)); if (s.getTso() != null) { context.getWriter().writeStringAttribute("tso", context.getAnonymizer().anonymizeString(s.getTso())); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/MeasurementsSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/MeasurementsSerDe.java index 4fcac7e101d..458ccdff223 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/MeasurementsSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/MeasurementsSerDe.java @@ -48,9 +48,7 @@ public void write(Measurements extension, SerializerContext context) { writer.writeStartNodes(); for (Measurement measurement : extension.getMeasurements()) { writer.writeStartNode(getNamespaceUri(), MEASUREMENT_ROOT_ELEMENT); - if (measurement.getId() != null) { - writer.writeStringAttribute("id", measurement.getId()); - } + writer.writeStringAttribute("id", measurement.getId()); writer.writeEnumAttribute("type", measurement.getType()); writer.writeEnumAttribute("side", measurement.getSide()); writer.writeDoubleAttribute(VALUE, measurement.getValue()); From a373903f5568bb75ff024f7c791b718738a4b50b Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 11:25:15 +0100 Subject: [PATCH 02/42] Remove ifs prior to calling writeDoubleAttribute Signed-off-by: Florian Dupuy --- .../commons/io/AbstractTreeDataWriter.java | 31 +++++++++++++++++++ .../powsybl/commons/io/TreeDataWriter.java | 6 ++++ .../com/powsybl/commons/json/JsonWriter.java | 4 +-- .../com/powsybl/commons/xml/XmlWriter.java | 4 +-- .../iidm/serde/AbstractTransformerSerDe.java | 6 ++-- .../iidm/serde/ConnectableSerDeUtil.java | 6 ++++ .../com/powsybl/iidm/serde/LineSerDe.java | 6 ++-- .../serde/ThreeWindingsTransformerSerDe.java | 8 ++--- .../com/powsybl/iidm/serde/TieLineSerDe.java | 6 ++-- .../serde/TwoWindingsTransformerSerDe.java | 6 ++-- .../iidm/serde/VoltageAngleLimitSerDe.java | 4 +-- .../extensions/BranchObservabilitySerDe.java | 13 ++++---- .../InjectionObservabilitySerDe.java | 4 +-- 13 files changed, 68 insertions(+), 36 deletions(-) create mode 100644 commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java new file mode 100644 index 00000000000..901541f3286 --- /dev/null +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2024, 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.commons.io; + +import java.util.function.BooleanSupplier; +import java.util.function.DoubleSupplier; + +/** + * @author Florian Dupuy {@literal } + */ +public abstract class AbstractTreeDataWriter implements TreeDataWriter { + + @Override + public void writeOptionalBooleanAttribute(String name, Boolean value, BooleanSupplier write) { + if (write.getAsBoolean() && value != null) { + writeBooleanAttribute(name, value); + } + } + + @Override + public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write) { + if (write.getAsBoolean()) { + writeDoubleAttribute(name, valueSupplier.getAsDouble()); + } + } +} diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index 1f4fcf00182..37b1b7209ce 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -8,6 +8,8 @@ import java.util.Collection; import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.function.DoubleSupplier; /** * @author Geoffroy Jamgotchian {@literal } @@ -34,6 +36,8 @@ public interface TreeDataWriter extends AutoCloseable { void writeDoubleAttribute(String name, double value, double absentValue); + void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write); + void writeIntAttribute(String name, int value); void writeIntAttribute(String name, int value, int absentValue); @@ -48,6 +52,8 @@ public interface TreeDataWriter extends AutoCloseable { void writeBooleanAttribute(String name, boolean value, boolean absentValue); + void writeOptionalBooleanAttribute(String name, Boolean value, BooleanSupplier write); + @Override void close(); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java index d449310b969..864802328c7 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.powsybl.commons.PowsyblException; -import com.powsybl.commons.io.TreeDataWriter; +import com.powsybl.commons.io.AbstractTreeDataWriter; import com.powsybl.commons.json.JsonUtil.Context; import com.powsybl.commons.json.JsonUtil.ContextType; @@ -20,7 +20,7 @@ /** * @author Geoffroy Jamgotchian {@literal } */ -public class JsonWriter implements TreeDataWriter { +public class JsonWriter extends AbstractTreeDataWriter { public static final String VERSION = "version"; private static final String EXTENSION_VERSIONS = "extensionVersions"; diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java index 5c3b8b5cbd0..4d35c30676a 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java @@ -8,7 +8,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.exceptions.UncheckedXmlStreamException; -import com.powsybl.commons.io.TreeDataWriter; +import com.powsybl.commons.io.AbstractTreeDataWriter; import org.apache.commons.lang3.StringUtils; import javax.xml.stream.XMLStreamException; @@ -21,7 +21,7 @@ /** * @author Geoffroy Jamgotchian {@literal } */ -public class XmlWriter implements TreeDataWriter { +public class XmlWriter extends AbstractTreeDataWriter { private final XMLStreamWriter writer; diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 205034cae04..5b92b54625e 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -157,10 +157,8 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net } writeTapChanger(ptc, context); context.getWriter().writeEnumAttribute("regulationMode", ptc.getRegulationMode()); - if (ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP - || !Double.isNaN(ptc.getRegulationValue())) { - context.getWriter().writeDoubleAttribute("regulationValue", ptc.getRegulationValue()); - } + context.getWriter().writeOptionalDoubleAttribute("regulationValue", ptc::getRegulationValue, + () -> ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP); if (ptc.getRegulationTerminal() != null) { TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index d370b064e38..ad13a58e164 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -14,6 +14,7 @@ import com.powsybl.iidm.serde.util.IidmSerDeUtil; import java.util.Optional; +import java.util.function.BooleanSupplier; /** * @author Geoffroy Jamgotchian {@literal } @@ -162,6 +163,11 @@ public static void writePQ(Integer index, Terminal t, TreeDataWriter writer) { writer.writeDoubleAttribute("q" + indexToString(index), t.getQ()); } + public static void writeOptionalPQ(Integer index, Terminal t, TreeDataWriter writer, BooleanSupplier write) { + writer.writeOptionalDoubleAttribute("p" + indexToString(index), t::getP, write); + writer.writeOptionalDoubleAttribute("q" + indexToString(index), t::getQ, write); + } + public static void readPQ(Integer index, Terminal t, TreeDataReader reader) { double p = reader.readDoubleAttribute("p" + indexToString(index)); double q = reader.readDoubleAttribute("q" + indexToString(index)); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java index 8f8322cd3a7..99b1dc8f840 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java @@ -39,10 +39,8 @@ protected void writeRootElementAttributes(Line l, Network n, NetworkSerializerCo context.getWriter().writeDoubleAttribute("b2", l.getB2()); writeNodeOrBus(1, l.getTerminal1(), context); writeNodeOrBus(2, l.getTerminal2(), context); - if (context.getOptions().isWithBranchSV()) { - writePQ(1, l.getTerminal1(), context.getWriter()); - writePQ(2, l.getTerminal2(), context.getWriter()); - } + writeOptionalPQ(1, l.getTerminal1(), context.getWriter(), context.getOptions()::isWithBranchSV); + writeOptionalPQ(2, l.getTerminal2(), context.getWriter(), context.getOptions()::isWithBranchSV); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java index ade8f30d566..38e9d87bb89 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java @@ -65,11 +65,9 @@ protected void writeRootElementAttributes(ThreeWindingsTransformer twt, Substati writeNodeOrBus(1, twt.getLeg1().getTerminal(), context); writeNodeOrBus(2, twt.getLeg2().getTerminal(), context); writeNodeOrBus(3, twt.getLeg3().getTerminal(), context); - if (context.getOptions().isWithBranchSV()) { - writePQ(1, twt.getLeg1().getTerminal(), context.getWriter()); - writePQ(2, twt.getLeg2().getTerminal(), context.getWriter()); - writePQ(3, twt.getLeg3().getTerminal(), context.getWriter()); - } + writeOptionalPQ(1, twt.getLeg1().getTerminal(), context.getWriter(), context.getOptions()::isWithBranchSV); + writeOptionalPQ(2, twt.getLeg2().getTerminal(), context.getWriter(), context.getOptions()::isWithBranchSV); + writeOptionalPQ(3, twt.getLeg3().getTerminal(), context.getWriter(), context.getOptions()::isWithBranchSV); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java index 97e341b000b..4f8864232df 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java @@ -63,10 +63,8 @@ protected void writeRootElementAttributes(TieLine tl, Network n, NetworkSerializ } writeNodeOrBus(1, tl.getDanglingLine1().getTerminal(), context); writeNodeOrBus(2, tl.getDanglingLine2().getTerminal(), context); - if (context.getOptions().isWithBranchSV()) { - writePQ(1, tl.getDanglingLine1().getTerminal(), context.getWriter()); - writePQ(2, tl.getDanglingLine2().getTerminal(), context.getWriter()); - } + writeOptionalPQ(1, tl.getDanglingLine1().getTerminal(), context.getWriter(), context.getOptions()::isWithBranchSV); + writeOptionalPQ(2, tl.getDanglingLine2().getTerminal(), context.getWriter(), context.getOptions()::isWithBranchSV); writeDanglingLine(tl.getDanglingLine1(), context, 1); writeDanglingLine(tl.getDanglingLine2(), context, 2); }); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java index 2059613044d..015273fe620 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java @@ -40,10 +40,8 @@ protected void writeRootElementAttributes(TwoWindingsTransformer twt, Substation writeRatedS("ratedS", twt.getRatedS(), context); writeNodeOrBus(1, twt.getTerminal1(), context); writeNodeOrBus(2, twt.getTerminal2(), context); - if (context.getOptions().isWithBranchSV()) { - writePQ(1, twt.getTerminal1(), context.getWriter()); - writePQ(2, twt.getTerminal2(), context.getWriter()); - } + writeOptionalPQ(1, twt.getTerminal1(), context.getWriter(), context.getOptions()::isWithBranchSV); + writeOptionalPQ(2, twt.getTerminal2(), context.getWriter(), context.getOptions()::isWithBranchSV); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java index 3f3e5f7105e..441ffa3aaa0 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java @@ -34,8 +34,8 @@ public static void write(VoltageAngleLimit voltageAngleLimit, NetworkSerializerC IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, () -> { context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), ROOT_ELEMENT_NAME); context.getWriter().writeStringAttribute(ID, context.getAnonymizer().anonymizeString(voltageAngleLimit.getId())); - voltageAngleLimit.getLowLimit().ifPresent(low -> context.getWriter().writeDoubleAttribute(LOW_LIMIT, low)); - voltageAngleLimit.getHighLimit().ifPresent(high -> context.getWriter().writeDoubleAttribute(HIGH_LIMIT, high)); + context.getWriter().writeOptionalDoubleAttribute(LOW_LIMIT, () -> voltageAngleLimit.getLowLimit().orElse(Double.NaN), voltageAngleLimit.getLowLimit()::isPresent); + context.getWriter().writeOptionalDoubleAttribute(HIGH_LIMIT, () -> voltageAngleLimit.getHighLimit().orElse(Double.NaN), voltageAngleLimit.getHighLimit()::isPresent); TerminalRefSerDe.writeTerminalRef(voltageAngleLimit.getTerminalFrom(), context, FROM); TerminalRefSerDe.writeTerminalRef(voltageAngleLimit.getTerminalTo(), context, TO); context.getWriter().writeEndNode(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java index db667605176..1de4bccb9e7 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java @@ -54,14 +54,13 @@ public void write(BranchObservability branchObservability, SerializerContext } private void writeOptionalQuality(SerializerContext context, ObservabilityQuality quality, String type, TwoSides side) { - if (quality == null) { - return; + if (quality != null) { + context.getWriter().writeStartNode(getNamespaceUri(), type); + context.getWriter().writeEnumAttribute(SIDE, side); + context.getWriter().writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); + context.getWriter().writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null), quality.isRedundant()::isPresent); + context.getWriter().writeEndNode(); } - context.getWriter().writeStartNode(getNamespaceUri(), type); - context.getWriter().writeEnumAttribute(SIDE, side); - context.getWriter().writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - quality.isRedundant().ifPresent(redundant -> context.getWriter().writeBooleanAttribute(REDUNDANT, redundant)); - context.getWriter().writeEndNode(); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java index 3c62950adf8..de66655ce3b 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java @@ -10,9 +10,9 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.extensions.AbstractExtensionSerDe; import com.powsybl.commons.extensions.ExtensionSerDe; -import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.commons.io.DeserializerContext; import com.powsybl.commons.io.SerializerContext; +import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.iidm.network.Injection; import com.powsybl.iidm.network.extensions.InjectionObservability; import com.powsybl.iidm.network.extensions.InjectionObservabilityAdder; @@ -48,7 +48,7 @@ private void writeOptionalQuality(String elementName, ObservabilityQuality qu if (quality != null) { writer.writeStartNode(getNamespaceUri(), elementName); writer.writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - quality.isRedundant().ifPresent(redundant -> writer.writeBooleanAttribute(REDUNDANT, redundant)); + writer.writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null), quality.isRedundant()::isPresent); writer.writeEndNode(); } } From f1a14aca6b8814b1b2c48a05164cd6f075de2034 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:00:33 +0100 Subject: [PATCH 03/42] Remove ifs prior to calling writeIntAttribute Signed-off-by: Florian Dupuy --- .../powsybl/cgmes/extensions/CgmesTapChangersSerDe.java | 9 ++++----- .../main/java/com/powsybl/commons/io/TreeDataWriter.java | 3 +++ .../com/powsybl/iidm/serde/AbstractTransformerSerDe.java | 5 ++--- .../iidm/serde/extensions/ConnectablePositionSerDe.java | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java index 2970f5c7080..16512eb032b 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java @@ -50,11 +50,10 @@ public void write(CgmesTapChangers extension, SerializerContext context) { writer.writeStringAttribute("id", tapChanger.getId()); writer.writeStringAttribute("combinedTapChangerId", tapChanger.getCombinedTapChangerId()); writer.writeStringAttribute("type", tapChanger.getType()); - if (tapChanger.isHidden()) { - writer.writeBooleanAttribute("hidden", true); - writer.writeIntAttribute("step", tapChanger.getStep() - .orElseThrow(() -> new PowsyblException("Step should be defined"))); - } + writer.writeBooleanAttribute("hidden", tapChanger.isHidden(), false); + writer.writeOptionalIntAttribute("step", + () -> tapChanger.getStep().orElseThrow(() -> new PowsyblException("Step should be defined")), + tapChanger::isHidden); writer.writeStringAttribute("controlId", tapChanger.getControlId()); writer.writeEndNode(); } diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index 37b1b7209ce..b00cb2131a8 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; /** * @author Geoffroy Jamgotchian {@literal } @@ -42,6 +43,8 @@ public interface TreeDataWriter extends AutoCloseable { void writeIntAttribute(String name, int value, int absentValue); + void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write); + void writeIntArrayAttribute(String name, Collection values); void writeStringArrayAttribute(String name, Collection values); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 5b92b54625e..ba19af04eeb 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -66,9 +66,8 @@ private static double readTargetDeadband(NetworkDeserializerContext context, boo private static void writeTapChanger(TapChanger tc, NetworkSerializerContext context) { context.getWriter().writeIntAttribute(ATTR_LOW_TAP_POSITION, tc.getLowTapPosition()); - if (tc.findTapPosition().isPresent()) { - context.getWriter().writeIntAttribute(ATTR_TAP_POSITION, tc.getTapPosition()); - } + var tp = tc.findTapPosition(); + context.getWriter().writeOptionalIntAttribute(ATTR_TAP_POSITION, tp::orElseThrow, tp::isPresent); writeTargetDeadband(tc.getTargetDeadband(), context); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java index 58001c7e697..c080d705fab 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java @@ -71,8 +71,7 @@ private void writePosition(String connectableId, ConnectablePosition.Feeder feed default: throw new PowsyblException("Unsupported version (" + extVersionStr + ") for " + ConnectablePosition.NAME); } - Optional oOrder = feeder.getOrder(); - oOrder.ifPresent(integer -> context.getWriter().writeIntAttribute("order", integer)); + context.getWriter().writeOptionalIntAttribute("order", feeder.getOrder()::orElseThrow, feeder.getOrder()::isPresent); context.getWriter().writeStringAttribute("direction", feeder.getDirection().name()); context.getWriter().writeEndNode(); } From a6ca8556d97e099fdf03134a71918b48a0bb05ef Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:00:53 +0100 Subject: [PATCH 04/42] Remove ifs prior to calling writeStringArrayAttribute Signed-off-by: Florian Dupuy --- .../java/com/powsybl/commons/json/JsonWriter.java | 12 +++++++----- .../main/java/com/powsybl/commons/xml/XmlWriter.java | 4 +++- .../java/com/powsybl/iidm/serde/SubstationSerDe.java | 4 +--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java index 864802328c7..ccf5a60e2ac 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java @@ -206,12 +206,14 @@ public void writeIntArrayAttribute(String name, Collection values) { @Override public void writeStringArrayAttribute(String name, Collection values) { try { - jsonGenerator.writeFieldName(name); - jsonGenerator.writeStartArray(); - for (String value : values) { - jsonGenerator.writeString(value); + if (!values.isEmpty()) { + jsonGenerator.writeFieldName(name); + jsonGenerator.writeStartArray(); + for (String value : values) { + jsonGenerator.writeString(value); + } + jsonGenerator.writeEndArray(); } - jsonGenerator.writeEndArray(); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java index 4d35c30676a..1723f791446 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java @@ -178,7 +178,9 @@ public void writeIntArrayAttribute(String name, Collection values) { @Override public void writeStringArrayAttribute(String name, Collection values) { - writeStringAttribute(name, String.join(",", values)); + if (!values.isEmpty()) { + writeStringAttribute(name, String.join(",", values)); + } } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java index de0e245e536..94b886f7a33 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java @@ -35,9 +35,7 @@ protected void writeRootElementAttributes(Substation s, Network n, NetworkSerial if (s.getTso() != null) { context.getWriter().writeStringAttribute("tso", context.getAnonymizer().anonymizeString(s.getTso())); } - if (!s.getGeographicalTags().isEmpty()) { - context.getWriter().writeStringArrayAttribute("geographicalTags", s.getGeographicalTags().stream().map(tag -> context.getAnonymizer().anonymizeString(tag)).toList()); - } + context.getWriter().writeStringArrayAttribute("geographicalTags", s.getGeographicalTags().stream().map(tag -> context.getAnonymizer().anonymizeString(tag)).toList()); } @Override From b755d4a599641a7286fdd7283e30fef8b684b79e Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:03:22 +0100 Subject: [PATCH 05/42] Fix int Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/io/AbstractTreeDataWriter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java index 901541f3286..ee22a5d623d 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -9,6 +9,7 @@ import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; /** * @author Florian Dupuy {@literal } @@ -28,4 +29,11 @@ public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSuppli writeDoubleAttribute(name, valueSupplier.getAsDouble()); } } + + @Override + public void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write) { + if (write.getAsBoolean()) { + writeIntAttribute(name, valueSupplier.getAsInt()); + } + } } From 7602111b339ad855e172bc692f1991e2df5fe386 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:03:59 +0100 Subject: [PATCH 06/42] Fix writeIntArrayAttribute for empty collections Signed-off-by: Florian Dupuy --- .../java/com/powsybl/commons/json/JsonWriter.java | 12 +++++++----- .../main/java/com/powsybl/commons/xml/XmlWriter.java | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java index ccf5a60e2ac..9d3386fa6b6 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonWriter.java @@ -192,12 +192,14 @@ public void writeIntAttribute(String name, int value, int absentValue) { @Override public void writeIntArrayAttribute(String name, Collection values) { try { - jsonGenerator.writeFieldName(name); - jsonGenerator.writeStartArray(); - for (int value : values) { - jsonGenerator.writeNumber(value); + if (!values.isEmpty()) { + jsonGenerator.writeFieldName(name); + jsonGenerator.writeStartArray(); + for (int value : values) { + jsonGenerator.writeNumber(value); + } + jsonGenerator.writeEndArray(); } - jsonGenerator.writeEndArray(); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java index 1723f791446..b7690b3e4bf 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlWriter.java @@ -171,9 +171,11 @@ public void writeIntAttribute(String name, int value, int absentValue) { @Override public void writeIntArrayAttribute(String name, Collection values) { - writeStringAttribute(name, values.stream() - .map(i -> Integer.toString(i)) - .collect(Collectors.joining(","))); + if (!values.isEmpty()) { + writeStringAttribute(name, values.stream() + .map(i -> Integer.toString(i)) + .collect(Collectors.joining(","))); + } } @Override From 18dcea2d4e9dcb4ca676cc20e342ba8ce1eb5758 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:06:22 +0100 Subject: [PATCH 07/42] Fix writeString Signed-off-by: Florian Dupuy --- .../src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java index 94b886f7a33..577d8ddfc3a 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java @@ -32,9 +32,7 @@ protected String getRootElementName() { @Override protected void writeRootElementAttributes(Substation s, Network n, NetworkSerializerContext context) { context.getWriter().writeStringAttribute(COUNTRY, s.getCountry().map(c -> context.getAnonymizer().anonymizeCountry(c).toString()).orElse(null)); - if (s.getTso() != null) { - context.getWriter().writeStringAttribute("tso", context.getAnonymizer().anonymizeString(s.getTso())); - } + context.getWriter().writeStringAttribute("tso", Optional.ofNullable(s.getTso()).map(tso -> context.getAnonymizer().anonymizeString(tso)).orElse(null)); context.getWriter().writeStringArrayAttribute("geographicalTags", s.getGeographicalTags().stream().map(tag -> context.getAnonymizer().anonymizeString(tag)).toList()); } From dd6aacff3e6aaab9b270de04439c962e85ba6c26 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:07:55 +0100 Subject: [PATCH 08/42] Remove if prior to calling writeEnumAttribute Signed-off-by: Florian Dupuy --- .../com/powsybl/cgmes/extensions/CgmesControlAreasSerDe.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesControlAreasSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesControlAreasSerDe.java index 229c2c88756..8c1cd814a0f 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesControlAreasSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesControlAreasSerDe.java @@ -77,10 +77,7 @@ public void write(CgmesControlAreas extension, SerializerContext context) { writer.writeStringAttribute("id", networkContext.getAnonymizer().anonymizeString(boundary.getDanglingLine().getId())); // TODO use TieLine Id and DanglingLine Id for reference instead of TieLine Id and Side - TwoSides side = getSide(boundary); - if (side != null) { - writer.writeEnumAttribute("side", side); - } + writer.writeEnumAttribute("side", getSide(boundary)); writer.writeEndNode(); } } From 443496d79de35c69a0b8a6cfcf52fe9becc681a6 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 8 Jan 2024 17:25:58 +0100 Subject: [PATCH 09/42] Remove if prior to calling writeBooleanAttribute Signed-off-by: Florian Dupuy --- .../commons/io/AbstractTreeDataWriter.java | 6 +++--- .../powsybl/commons/io/TreeDataWriter.java | 2 +- .../iidm/serde/AbstractTransformerSerDe.java | 10 ++++------ .../powsybl/iidm/serde/DanglingLineSerDe.java | 20 +++++++++---------- .../extensions/BranchObservabilitySerDe.java | 2 +- .../InjectionObservabilitySerDe.java | 2 +- 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java index ee22a5d623d..2502b37f653 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -17,9 +17,9 @@ public abstract class AbstractTreeDataWriter implements TreeDataWriter { @Override - public void writeOptionalBooleanAttribute(String name, Boolean value, BooleanSupplier write) { - if (write.getAsBoolean() && value != null) { - writeBooleanAttribute(name, value); + public void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write) { + if (write.getAsBoolean()) { + writeBooleanAttribute(name, valueSupplier.getAsBoolean()); } } diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index b00cb2131a8..0e58eea3c72 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -55,7 +55,7 @@ public interface TreeDataWriter extends AutoCloseable { void writeBooleanAttribute(String name, boolean value, boolean absentValue); - void writeOptionalBooleanAttribute(String name, Boolean value, BooleanSupplier write); + void writeOptionalBooleanAttribute(String name, BooleanSupplier value, BooleanSupplier write); @Override void close(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index ba19af04eeb..caf2093cdca 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -149,15 +149,13 @@ protected static void readRatioTapChanger(int leg, ThreeWindingsTransformer.Leg } protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, NetworkSerializerContext context) { + boolean nonFixedRegulationMode = ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP; + context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), name); - if (ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP - || ptc.isRegulating()) { - context.getWriter().writeBooleanAttribute(ATTR_REGULATING, ptc.isRegulating()); - } + context.getWriter().writeOptionalBooleanAttribute(ATTR_REGULATING, ptc::isRegulating, () -> nonFixedRegulationMode || ptc.isRegulating()); writeTapChanger(ptc, context); context.getWriter().writeEnumAttribute("regulationMode", ptc.getRegulationMode()); - context.getWriter().writeOptionalDoubleAttribute("regulationValue", ptc::getRegulationValue, - () -> ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP); + context.getWriter().writeOptionalDoubleAttribute("regulationValue", ptc::getRegulationValue, () -> nonFixedRegulationMode); if (ptc.getRegulationTerminal() != null) { TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index 5fd085772c0..74a99b8fa0f 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -10,6 +10,7 @@ import com.powsybl.iidm.serde.util.IidmSerDeUtil; import java.util.Optional; +import java.util.function.BooleanSupplier; import java.util.function.Supplier; import static com.powsybl.iidm.serde.ConnectableSerDeUtil.*; @@ -63,16 +64,15 @@ static void writeRootElementAttributesInternal(DanglingLine dl, Supplier { - context.getWriter().writeBooleanAttribute("generationVoltageRegulationOn", generation.isVoltageRegulationOn()); - context.getWriter().writeDoubleAttribute(GENERATION_MIN_P, generation.getMinP()); - context.getWriter().writeDoubleAttribute(GENERATION_MAX_P, generation.getMaxP()); - context.getWriter().writeDoubleAttribute(GENERATION_TARGET_P, generation.getTargetP()); - context.getWriter().writeDoubleAttribute(GENERATION_TARGET_V, generation.getTargetV()); - context.getWriter().writeDoubleAttribute(GENERATION_TARGET_Q, generation.getTargetQ()); - }); - } + IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { + BooleanSupplier write = () -> generation != null; + context.getWriter().writeOptionalBooleanAttribute("generationVoltageRegulationOn", generation::isVoltageRegulationOn, write); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_MIN_P, generation::getMinP, write); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_MAX_P, generation::getMaxP, write); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_P, generation::getTargetP, write); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_V, generation::getTargetV, write); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_Q, generation::getTargetQ, write); + }); Terminal t = terminalGetter.get(); writeNodeOrBus(null, t, context); IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_10, context, diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java index 1de4bccb9e7..6b61cc1fbd1 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java @@ -58,7 +58,7 @@ private void writeOptionalQuality(SerializerContext context, ObservabilityQualit context.getWriter().writeStartNode(getNamespaceUri(), type); context.getWriter().writeEnumAttribute(SIDE, side); context.getWriter().writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - context.getWriter().writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null), quality.isRedundant()::isPresent); + context.getWriter().writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant()::orElseThrow, quality.isRedundant()::isPresent); context.getWriter().writeEndNode(); } } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java index de66655ce3b..ea8250cd80b 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java @@ -48,7 +48,7 @@ private void writeOptionalQuality(String elementName, ObservabilityQuality qu if (quality != null) { writer.writeStartNode(getNamespaceUri(), elementName); writer.writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - writer.writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null), quality.isRedundant()::isPresent); + writer.writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant()::orElseThrow, quality.isRedundant()::isPresent); writer.writeEndNode(); } } From ef2c7e3b22eb21f21046b8c01df94c6bb80a9b73 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 9 Jan 2024 09:40:09 +0100 Subject: [PATCH 10/42] Add write methods with boxed Double & Boolean Signed-off-by: Florian Dupuy --- .../commons/io/AbstractTreeDataWriter.java | 14 ++++++++++++ .../powsybl/commons/io/TreeDataWriter.java | 4 ++++ .../iidm/serde/AbstractTransformerSerDe.java | 2 +- .../powsybl/iidm/serde/DanglingLineSerDe.java | 22 +++++++++++-------- .../powsybl/iidm/serde/SubstationSerDe.java | 2 +- .../extensions/BranchObservabilitySerDe.java | 2 +- .../InjectionObservabilitySerDe.java | 2 +- 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java index 2502b37f653..d87073844d1 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -23,6 +23,13 @@ public void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupp } } + @Override + public void writeOptionalBooleanAttribute(String name, Boolean value) { + if (value != null) { + writeBooleanAttribute(name, value); + } + } + @Override public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write) { if (write.getAsBoolean()) { @@ -30,6 +37,13 @@ public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSuppli } } + @Override + public void writeOptionalDoubleAttribute(String name, Double value) { + if (value != null) { + writeDoubleAttribute(name, value); + } + } + @Override public void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write) { if (write.getAsBoolean()) { diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index 0e58eea3c72..f98b23963ec 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -39,6 +39,8 @@ public interface TreeDataWriter extends AutoCloseable { void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write); + void writeOptionalDoubleAttribute(String name, Double value); + void writeIntAttribute(String name, int value); void writeIntAttribute(String name, int value, int absentValue); @@ -57,6 +59,8 @@ public interface TreeDataWriter extends AutoCloseable { void writeOptionalBooleanAttribute(String name, BooleanSupplier value, BooleanSupplier write); + void writeOptionalBooleanAttribute(String name, Boolean value); + @Override void close(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index caf2093cdca..aa5a181a4e0 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -155,7 +155,7 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net context.getWriter().writeOptionalBooleanAttribute(ATTR_REGULATING, ptc::isRegulating, () -> nonFixedRegulationMode || ptc.isRegulating()); writeTapChanger(ptc, context); context.getWriter().writeEnumAttribute("regulationMode", ptc.getRegulationMode()); - context.getWriter().writeOptionalDoubleAttribute("regulationValue", ptc::getRegulationValue, () -> nonFixedRegulationMode); + context.getWriter().writeDoubleAttribute("regulationValue", ptc.getRegulationValue()); if (ptc.getRegulationTerminal() != null) { TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index 74a99b8fa0f..0a527d78502 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -7,10 +7,11 @@ package com.powsybl.iidm.serde; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.DanglingLine.Generation; import com.powsybl.iidm.serde.util.IidmSerDeUtil; import java.util.Optional; -import java.util.function.BooleanSupplier; +import java.util.function.Function; import java.util.function.Supplier; import static com.powsybl.iidm.serde.ConnectableSerDeUtil.*; @@ -42,7 +43,7 @@ protected void writeRootElementAttributes(DanglingLine dl, VoltageLevel vl, Netw } static void writeRootElementAttributesInternal(DanglingLine dl, Supplier terminalGetter, NetworkSerializerContext context) { - DanglingLine.Generation generation = dl.getGeneration(); + Generation generation = dl.getGeneration(); double[] p0 = new double[1]; double[] q0 = new double[1]; p0[0] = dl.getP0(); @@ -65,13 +66,12 @@ static void writeRootElementAttributesInternal(DanglingLine dl, Supplier { - BooleanSupplier write = () -> generation != null; - context.getWriter().writeOptionalBooleanAttribute("generationVoltageRegulationOn", generation::isVoltageRegulationOn, write); - context.getWriter().writeOptionalDoubleAttribute(GENERATION_MIN_P, generation::getMinP, write); - context.getWriter().writeOptionalDoubleAttribute(GENERATION_MAX_P, generation::getMaxP, write); - context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_P, generation::getTargetP, write); - context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_V, generation::getTargetV, write); - context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_Q, generation::getTargetQ, write); + context.getWriter().writeOptionalBooleanAttribute("generationVoltageRegulationOn", getOptionalValue(generation, Generation::isVoltageRegulationOn)); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_MIN_P, getOptionalValue(generation, Generation::getMinP)); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_MAX_P, getOptionalValue(generation, Generation::getMaxP)); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_P, getOptionalValue(generation, Generation::getTargetP)); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_V, getOptionalValue(generation, Generation::getTargetV)); + context.getWriter().writeOptionalDoubleAttribute(GENERATION_TARGET_Q, getOptionalValue(generation, Generation::getTargetQ)); }); Terminal t = terminalGetter.get(); writeNodeOrBus(null, t, context); @@ -85,6 +85,10 @@ static void writeRootElementAttributesInternal(DanglingLine dl, Supplier T getOptionalValue(Generation generation, Function valueGetter) { + return Optional.ofNullable(generation).map(valueGetter).orElse(null); + } + @Override protected DanglingLineAdder createAdder(VoltageLevel parent) { return parent.newDanglingLine(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java index 577d8ddfc3a..08678f6568d 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/SubstationSerDe.java @@ -32,7 +32,7 @@ protected String getRootElementName() { @Override protected void writeRootElementAttributes(Substation s, Network n, NetworkSerializerContext context) { context.getWriter().writeStringAttribute(COUNTRY, s.getCountry().map(c -> context.getAnonymizer().anonymizeCountry(c).toString()).orElse(null)); - context.getWriter().writeStringAttribute("tso", Optional.ofNullable(s.getTso()).map(tso -> context.getAnonymizer().anonymizeString(tso)).orElse(null)); + context.getWriter().writeStringAttribute("tso", Optional.ofNullable(s.getTso()).map(tso -> context.getAnonymizer().anonymizeString(tso)).orElse(null)); context.getWriter().writeStringArrayAttribute("geographicalTags", s.getGeographicalTags().stream().map(tag -> context.getAnonymizer().anonymizeString(tag)).toList()); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java index 6b61cc1fbd1..d8919dc7179 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java @@ -58,7 +58,7 @@ private void writeOptionalQuality(SerializerContext context, ObservabilityQualit context.getWriter().writeStartNode(getNamespaceUri(), type); context.getWriter().writeEnumAttribute(SIDE, side); context.getWriter().writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - context.getWriter().writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant()::orElseThrow, quality.isRedundant()::isPresent); + context.getWriter().writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null)); context.getWriter().writeEndNode(); } } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java index ea8250cd80b..3270fe8d536 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java @@ -48,7 +48,7 @@ private void writeOptionalQuality(String elementName, ObservabilityQuality qu if (quality != null) { writer.writeStartNode(getNamespaceUri(), elementName); writer.writeDoubleAttribute(STANDARD_DEVIATION, quality.getStandardDeviation()); - writer.writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant()::orElseThrow, quality.isRedundant()::isPresent); + writer.writeOptionalBooleanAttribute(REDUNDANT, quality.isRedundant().orElse(null)); writer.writeEndNode(); } } From 4775389894f8e44ab1e0de4567e97e05d4ae04f3 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 9 Jan 2024 12:54:19 +0100 Subject: [PATCH 11/42] First version of BinReader Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 commons/src/main/java/com/powsybl/commons/binary/BinReader.java diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java new file mode 100644 index 00000000000..e13c526c8b0 --- /dev/null +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -0,0 +1,228 @@ +/** + * Copyright (c) 2024, 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.commons.binary; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.io.TreeDataReader; + +import javax.xml.stream.XMLStreamConstants; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.*; +import java.util.function.Supplier; + +/** + * @author Florian Dupuy {@literal } + */ +public class BinReader implements TreeDataReader { + + private static final int END_NODE = 0; + private final DataInputStream dis; + private final Map dictionary = new HashMap<>(); + + public BinReader(InputStream is) throws IOException { + this.dis = new DataInputStream(Objects.requireNonNull(is)); + readDictionary(); + } + + private void readDictionary() throws IOException { + int nbEntries = dis.readShort(); + for (int i = 0; i < nbEntries; i++) { + dictionary.put(i + 1, readString()); + } + } + + private String readString() { + try { + int stringNbBytes = dis.readShort(); + byte[] stringBytes = new byte[stringNbBytes]; + int nbBytesRead = dis.read(stringBytes, 0, stringNbBytes); + if (nbBytesRead != stringNbBytes) { + throw new PowsyblException("Cannot read the full string, bytes missing: " + (stringNbBytes - nbBytesRead)); + } + return new String(stringBytes); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private double readDouble() { + try { + return dis.readDouble(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private float readFloat() { + try { + return dis.readFloat(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private int readInt() { + try { + return dis.readInt(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private boolean readBoolean() { + try { + return dis.readBoolean(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private > T readEnum(Class clazz) { + return clazz.getEnumConstants()[readInt()]; + } + + private List readArray(Supplier valueReader) { + try { + int nbValues = dis.readShort(); + List values = new ArrayList<>(nbValues); + for (int i = 0; i < nbValues; i++) { + values.add(valueReader.get()); + } + return values; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public String readRootVersion() { + return readString(); + } + + @Override + public Map readVersions() { + try { + int nbVersions = dis.readShort(); + Map versions = new HashMap<>(); + for (int i = 0; i < nbVersions; i++) { + versions.put(readString(), readString()); + } + return versions; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public double readDoubleAttribute(String name) { + return readDouble(); + } + + @Override + public double readDoubleAttribute(String name, double defaultValue) { + return readDouble(); + } + + @Override + public float readFloatAttribute(String name) { + return readFloat(); + } + + @Override + public float readFloatAttribute(String name, float defaultValue) { + return readFloat(); + } + + @Override + public String readStringAttribute(String name) { + return readString(); + } + + @Override + public Integer readIntAttribute(String name) { + return readInt(); + } + + @Override + public int readIntAttribute(String name, int defaultValue) { + return readInt(); + } + + @Override + public Boolean readBooleanAttribute(String name) { + return readBoolean(); + } + + @Override + public boolean readBooleanAttribute(String name, boolean defaultValue) { + return readBoolean(); + } + + @Override + public > T readEnumAttribute(String name, Class clazz) { + return readEnum(clazz); + } + + @Override + public > T readEnumAttribute(String name, Class clazz, T defaultValue) { + return clazz.getEnumConstants()[readInt()]; + } + + @Override + public String readContent() { + return readString(); + } + + @Override + public List readIntArrayAttribute(String name) { + return readArray(this::readInt); + } + + @Override + public List readStringArrayAttribute(String name) { + return readArray(this::readString); + } + + @Override + public void skipChildNodes() { + throw new PowsyblException("Binary format does not support skipping child nodes"); + } + + @Override + public void readChildNodes(ChildNodeReader childNodeReader) { + try { + int nodeNameIndex; + while ((nodeNameIndex = dis.readShort()) != END_NODE) { + String nodeName = dictionary.get(nodeNameIndex); + if (nodeName == null) { + throw new PowsyblException("Cannot read child node: unknown element name index " + nodeNameIndex); + } + childNodeReader.onStartNode(nodeName); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void readEndNode() { + // Nothing to do + } + + @Override + public void close() { + try { + dis.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} From 16e89544ecc7766e01a7c0d30150074dd98ef995 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 9 Jan 2024 23:05:44 +0100 Subject: [PATCH 12/42] First version of BinWriter Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinWriter.java | 267 ++++++++++++++++++ .../powsybl/commons/io/TreeDataWriter.java | 2 +- 2 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 commons/src/main/java/com/powsybl/commons/binary/BinWriter.java diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java new file mode 100644 index 00000000000..960f1e215fe --- /dev/null +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2024, 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.commons.binary; + +import com.powsybl.commons.io.TreeDataWriter; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; + +/** + * @author Florian Dupuy {@literal } + */ +public class BinWriter implements TreeDataWriter { + + private final String rootVersion; + private final DataOutputStream dos; + private final DataOutputStream tmpDos; + private final ByteArrayOutputStream buffer; + private final Map nodeNamesIndex = new LinkedHashMap<>(); + private Map extensionVersions; + + public BinWriter(OutputStream outputStream, String rootVersion) { + this.rootVersion = Objects.requireNonNull(rootVersion); + this.dos = new DataOutputStream(Objects.requireNonNull(outputStream)); + this.buffer = new ByteArrayOutputStream(); + this.tmpDos = new DataOutputStream(buffer); + } + + private static void writeIndex(int index, DataOutputStream dataOutputStream) { + try { + dataOutputStream.writeShort(index); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void writeString(String value, DataOutputStream dataOutputStream) { + try { + byte[] bytes = value.getBytes(StandardCharsets.UTF_8); + writeIndex(bytes.length, dataOutputStream); + dataOutputStream.write(bytes); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void writeDouble(double value) { + try { + tmpDos.writeDouble(value); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void writeInt(int value) { + try { + tmpDos.writeInt(value); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void writeArray(Collection values, Consumer valueWriter) { + try { + tmpDos.writeShort(values.size()); + for (T value : values) { + valueWriter.accept(value); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void writeBoolean(boolean value) { + try { + tmpDos.writeBoolean(value); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeStartNodes() { + // nothing to do + } + + @Override + public void writeEndNodes() { + // nothing to do + } + + @Override + public void writeStartNode(String namespace, String name) { + int index = nodeNamesIndex.computeIfAbsent(name, n -> 1 + nodeNamesIndex.size()); + writeIndex(index, tmpDos); + } + + @Override + public void writeEndNode() { + writeIndex(0, tmpDos); + } + + @Override + public void writeNamespace(String prefix, String namespace) { + // nothing to do + } + + @Override + public void writeNodeContent(String value) { + writeString(value, tmpDos); + } + + @Override + public void writeStringAttribute(String name, String value) { + writeString(value, tmpDos); + } + + @Override + public void writeFloatAttribute(String name, float value) { + try { + tmpDos.writeFloat(value); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeDoubleAttribute(String name, double value) { + writeDouble(value); + } + + @Override + public void writeDoubleAttribute(String name, double value, double absentValue) { + writeDouble(value); + } + + @Override + public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write) { + try { + boolean writeValue = write.getAsBoolean(); + tmpDos.writeBoolean(writeValue); + if (writeValue) { + writeDouble(valueSupplier.getAsDouble()); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeOptionalDoubleAttribute(String name, Double value) { + try { + tmpDos.writeBoolean(value != null); + if (value != null) { + writeDouble(value); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeIntAttribute(String name, int value) { + writeInt(value); + } + + @Override + public void writeIntAttribute(String name, int value, int absentValue) { + writeInt(value); + } + + @Override + public void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write) { + try { + boolean writeValue = write.getAsBoolean(); + tmpDos.writeBoolean(writeValue); + if (writeValue) { + writeDouble(valueSupplier.getAsInt()); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeIntArrayAttribute(String name, Collection values) { + writeArray(values, this::writeInt); + } + + @Override + public void writeStringArrayAttribute(String name, Collection values) { + writeArray(values, s -> writeString(s, tmpDos)); + } + + @Override + public > void writeEnumAttribute(String name, E value) { + writeIndex(value.ordinal(), tmpDos); + } + + @Override + public void writeBooleanAttribute(String name, boolean value) { + writeBoolean(value); + } + + @Override + public void writeBooleanAttribute(String name, boolean value, boolean absentValue) { + writeBoolean(value); + } + + @Override + public void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write) { + try { + boolean writeValue = write.getAsBoolean(); + tmpDos.writeBoolean(writeValue); + if (writeValue) { + writeBoolean(valueSupplier.getAsBoolean()); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void writeOptionalBooleanAttribute(String name, Boolean value) { + try { + tmpDos.writeBoolean(value != null); + if (value != null) { + writeBoolean(value); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void close() { + try { + tmpDos.flush(); + writeIndex(nodeNamesIndex.size(), dos); + nodeNamesIndex.forEach((name, index) -> writeString(name, dos)); + writeString(rootVersion, dos); + writeIndex(extensionVersions.size(), dos); + extensionVersions.forEach((extensionName, extensionVersion) -> { + writeString(extensionName, dos); + writeString(extensionVersion, dos); + }); + dos.write(buffer.toByteArray()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void setVersions(Map extensionVersions) { + this.extensionVersions = Objects.requireNonNull(extensionVersions); + } +} diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index f98b23963ec..6d07a72ce41 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -57,7 +57,7 @@ public interface TreeDataWriter extends AutoCloseable { void writeBooleanAttribute(String name, boolean value, boolean absentValue); - void writeOptionalBooleanAttribute(String name, BooleanSupplier value, BooleanSupplier write); + void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write); void writeOptionalBooleanAttribute(String name, Boolean value); From 7b70512300966f4989f93dd46c372bdabc573494 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 9 Jan 2024 23:06:50 +0100 Subject: [PATCH 13/42] fix Signed-off-by: Florian Dupuy --- commons/src/main/java/com/powsybl/commons/binary/BinReader.java | 1 - 1 file changed, 1 deletion(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index e13c526c8b0..55105d22b8b 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -10,7 +10,6 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.io.TreeDataReader; -import javax.xml.stream.XMLStreamConstants; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; From 2ad5ab11d9e0c8f829c165d23ee75aceb92bcfbf Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 11:13:08 +0100 Subject: [PATCH 14/42] Fix reader & writer Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 9 ++++++++- .../com/powsybl/commons/binary/BinWriter.java | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 55105d22b8b..2755de628e5 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -41,6 +41,9 @@ private void readDictionary() throws IOException { private String readString() { try { int stringNbBytes = dis.readShort(); + if (stringNbBytes == 0) { + return null; + } byte[] stringBytes = new byte[stringNbBytes]; int nbBytesRead = dis.read(stringBytes, 0, stringNbBytes); if (nbBytesRead != stringNbBytes) { @@ -85,7 +88,11 @@ private boolean readBoolean() { } private > T readEnum(Class clazz) { - return clazz.getEnumConstants()[readInt()]; + try { + return clazz.getEnumConstants()[dis.readShort()]; + } catch (IOException e) { + throw new UncheckedIOException(e); + } } private List readArray(Supplier valueReader) { diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 960f1e215fe..6d278c45e9d 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -46,9 +46,13 @@ private static void writeIndex(int index, DataOutputStream dataOutputStream) { private static void writeString(String value, DataOutputStream dataOutputStream) { try { - byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - writeIndex(bytes.length, dataOutputStream); - dataOutputStream.write(bytes); + if (value == null) { + writeIndex(0, dataOutputStream); + } else { + byte[] bytes = value.getBytes(StandardCharsets.UTF_8); + writeIndex(bytes.length, dataOutputStream); + dataOutputStream.write(bytes); + } } catch (IOException e) { throw new UncheckedIOException(e); } @@ -101,8 +105,12 @@ public void writeEndNodes() { @Override public void writeStartNode(String namespace, String name) { - int index = nodeNamesIndex.computeIfAbsent(name, n -> 1 + nodeNamesIndex.size()); - writeIndex(index, tmpDos); + if (nodeNamesIndex.isEmpty()) { + nodeNamesIndex.put(name, 1); // root element is not a child of another node, hence index is not expected + } else { + int index = nodeNamesIndex.computeIfAbsent(name, n -> 1 + nodeNamesIndex.size()); + writeIndex(index, tmpDos); + } } @Override From cc41ee76b6c7e7bfb77b627a80a608216ada91fa Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 11:13:47 +0100 Subject: [PATCH 15/42] Add TreeDataFormat.BIN Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/io/TreeDataFormat.java | 3 ++- .../com/powsybl/iidm/serde/NetworkSerDe.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataFormat.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataFormat.java index c37cab6dc78..9fe6218a3f8 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataFormat.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataFormat.java @@ -12,5 +12,6 @@ */ public enum TreeDataFormat { XML, - JSON + JSON, + BIN } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java index 5debecd41b4..4724706fb4c 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java @@ -10,6 +10,8 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.binary.BinReader; +import com.powsybl.commons.binary.BinWriter; import com.powsybl.commons.datasource.DataSource; import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.commons.exceptions.UncheckedSaxException; @@ -263,6 +265,10 @@ private static JsonWriter createJsonWriter(OutputStream os, ExportOptions option } } + private static TreeDataWriter createBinWriter(OutputStream os, ExportOptions options) { + return new BinWriter(os, options.getVersion().toString(".")); + } + private static void writeRootElement(Network n, NetworkSerializerContext context) { IidmSerDeUtil.assertMinimumVersionIfNotDefault(n.getValidationLevel() != ValidationLevel.STEADY_STATE_HYPOTHESIS, NETWORK_ROOT_ELEMENT_NAME, MINIMUM_VALIDATION_LEVEL, IidmSerDeUtil.ErrorMessage.NOT_SUPPORTED, IidmVersion.V_1_7, context.getVersion()); @@ -409,6 +415,7 @@ private static TreeDataWriter createTreeDataWriter(Network n, ExportOptions opti return switch (options.getFormat()) { case XML -> createXmlWriter(n, os, options); case JSON -> createJsonWriter(os, options); + case BIN -> createBinWriter(os, options); }; } @@ -508,9 +515,18 @@ private static TreeDataReader createTreeDataReader(InputStream is, ImportOptions return switch (config.getFormat()) { case XML -> createXmlReader(is, config); case JSON -> createJsonReader(is, config); + case BIN -> createBinReader(is); }; } + private static TreeDataReader createBinReader(InputStream is) { + try { + return new BinReader(is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private static TreeDataReader createJsonReader(InputStream is, ImportOptions config) { try { return new JsonReader(is, NETWORK_ROOT_ELEMENT_NAME, createArrayNameToSingleNameMap(config)); From 7d2249debf35150c1acb33829036754ea953f6f2 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 11:14:19 +0100 Subject: [PATCH 16/42] Writing fixes Signed-off-by: Florian Dupuy --- .../java/com/powsybl/iidm/serde/AbstractIdentifiableSerDe.java | 2 +- .../src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractIdentifiableSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractIdentifiableSerDe.java index 40fe44da585..eca9f255ecf 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractIdentifiableSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractIdentifiableSerDe.java @@ -32,7 +32,7 @@ public final void write(T identifiable, P parent, NetworkSerializerContext conte } context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), getRootElementName()); context.getWriter().writeStringAttribute("id", context.getAnonymizer().anonymizeString(identifiable.getId())); - identifiable.getOptionalName().ifPresent(name -> context.getWriter().writeStringAttribute("name", context.getAnonymizer().anonymizeString(name))); + context.getWriter().writeStringAttribute("name", identifiable.getOptionalName().map(context.getAnonymizer()::anonymizeString).orElse(null)); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_2, context, () -> context.getWriter().writeBooleanAttribute("fictitious", identifiable.isFictitious(), false)); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java index 78339cdcf54..e61474b8351 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java @@ -51,7 +51,7 @@ protected void writeRootElementAttributes(VoltageLevel vl, Container Date: Wed, 10 Jan 2024 13:11:19 +0100 Subject: [PATCH 17/42] Reading fixes Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 9 +- .../AbstractComplexIdentifiableSerDe.java | 4 +- .../com/powsybl/iidm/serde/BatterySerDe.java | 2 +- .../iidm/serde/ConnectableSerDeUtil.java | 107 ++++++++++-------- .../powsybl/iidm/serde/DanglingLineSerDe.java | 6 +- .../powsybl/iidm/serde/GeneratorSerDe.java | 7 +- .../iidm/serde/LccConverterStationSerDe.java | 2 +- .../com/powsybl/iidm/serde/LineSerDe.java | 2 +- .../com/powsybl/iidm/serde/LoadSerDe.java | 4 +- .../com/powsybl/iidm/serde/ShuntSerDe.java | 4 +- .../iidm/serde/StaticVarCompensatorSerDe.java | 2 +- .../serde/ThreeWindingsTransformerSerDe.java | 6 +- .../com/powsybl/iidm/serde/TieLineSerDe.java | 5 +- .../serde/TwoWindingsTransformerSerDe.java | 2 +- .../iidm/serde/VscConverterStationSerDe.java | 2 +- 15 files changed, 89 insertions(+), 75 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 2755de628e5..2da47475214 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -220,7 +220,14 @@ public void readChildNodes(ChildNodeReader childNodeReader) { @Override public void readEndNode() { - // Nothing to do + try { + int nextIndex = dis.readShort(); + if (nextIndex != END_NODE) { + throw new PowsyblException("Binary parsing: expected end node but got " + nextIndex); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractComplexIdentifiableSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractComplexIdentifiableSerDe.java index e723ae538b5..a01f6fc1741 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractComplexIdentifiableSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractComplexIdentifiableSerDe.java @@ -23,7 +23,7 @@ */ abstract class AbstractComplexIdentifiableSerDe, A extends IdentifiableAdder, P extends Identifiable> extends AbstractIdentifiableSerDe { - protected abstract void readRootElementAttributes(A adder, List> toApply, NetworkDeserializerContext context); + protected abstract void readRootElementAttributes(A adder, P parent, List> toApply, NetworkDeserializerContext context); protected void readSubElement(String elementName, String id, List> toApply, NetworkDeserializerContext context) { switch (elementName) { @@ -43,7 +43,7 @@ public final void read(P parent, NetworkDeserializerContext context) { List> toApply = new ArrayList<>(); A adder = createAdder(parent); String id = readIdentifierAttributes(adder, context); - readRootElementAttributes(adder, toApply, context); + readRootElementAttributes(adder, parent, toApply, context); readSubElements(id, adder, toApply, context); T identifiable = adder.add(); toApply.forEach(consumer -> consumer.accept(identifiable)); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BatterySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BatterySerDe.java index 57932ec3c5b..29cec927bdf 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BatterySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BatterySerDe.java @@ -60,7 +60,7 @@ protected Battery readRootElementAttributes(BatteryAdder adder, VoltageLevel vol IidmSerDeUtil.getAttributeName("q0", "targetQ", context.getVersion(), IidmVersion.V_1_8)); double minP = context.getReader().readDoubleAttribute("minP"); double maxP = context.getReader().readDoubleAttribute("maxP"); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); Battery b = adder.setTargetP(targetP) .setTargetQ(targetQ) .setMinP(minP) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index ad13a58e164..626954081ca 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -15,6 +15,8 @@ import java.util.Optional; import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.IntConsumer; /** * @author Geoffroy Jamgotchian {@literal } @@ -91,71 +93,78 @@ private static void writeBus(Integer index, Bus bus, Bus connectableBus, Network Optional.ofNullable(connectableBus).map(b -> context.getAnonymizer().anonymizeString(b.getId())).orElse(null)); } - public static void readNodeOrBus(InjectionAdder adder, NetworkDeserializerContext context) { - readNodeOrBus(adder, "", context); + public static void readNodeOrBus(InjectionAdder adder, NetworkDeserializerContext context, TopologyKind topologyKind) { + readNodeOrBus(adder, "", context, topologyKind); } - public static void readNodeOrBus(InjectionAdder adder, String suffix, NetworkDeserializerContext context) { - String bus = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(BUS + suffix)); - String connectableBus = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(CONNECTABLE_BUS + suffix)); - Integer node = context.getReader().readIntAttribute(NODE + suffix); - if (bus != null) { - adder.setBus(bus); - } - if (connectableBus != null) { - adder.setConnectableBus(connectableBus); + public static void readNodeOrBus(InjectionAdder adder, String suffix, NetworkDeserializerContext context, TopologyKind topologyKind) { + switch (topologyKind) { + case NODE_BREAKER -> readNode(adder::setNode, suffix, context); + case BUS_BREAKER -> { + readBus(adder::setBus, suffix, context); + readConnectableBus(adder::setConnectableBus, suffix, context); + } } + } + + private static void readNode(IntConsumer nodeAdder, String suffix, NetworkDeserializerContext context) { + Integer node = context.getReader().readIntAttribute(NODE + suffix); if (node != null) { - adder.setNode(node); + nodeAdder.accept(node); } } - public static void readNodeOrBus(BranchAdder adder, NetworkDeserializerContext context) { + private static void readBus(Consumer busAdder, String suffix, NetworkDeserializerContext context) { + busAdder.accept(context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(BUS + suffix))); + } + + private static void readConnectableBus(Consumer busAdder, String suffix, NetworkDeserializerContext context) { + busAdder.accept(context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(CONNECTABLE_BUS + suffix))); + } + + public static void readNodeOrBus(BranchAdder adder, Network network, NetworkDeserializerContext context) { String voltageLevelId1 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId1")); - String bus1 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("bus1")); - String connectableBus1 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("connectableBus1")); - Integer node1 = context.getReader().readIntAttribute("node1"); - String voltageLevelId2 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId2")); - String bus2 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("bus2")); - String connectableBus2 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("connectableBus2")); - Integer node2 = context.getReader().readIntAttribute("node2"); - if (bus1 != null) { - adder.setBus1(bus1); - } - if (connectableBus1 != null) { - adder.setConnectableBus1(connectableBus1); - } - if (node1 != null) { - adder.setNode1(node1); - } adder.setVoltageLevel1(voltageLevelId1); - if (bus2 != null) { - adder.setBus2(bus2); + String suffix1 = String.valueOf(1); + switch (getTopologKind(voltageLevelId1, network)) { + case NODE_BREAKER -> readNode(adder::setNode1, suffix1, context); + case BUS_BREAKER -> { + readBus(adder::setBus1, suffix1, context); + readConnectableBus(adder::setConnectableBus1, suffix1, context); + } } - if (connectableBus2 != null) { - adder.setConnectableBus2(connectableBus2); + + String voltageLevelId2 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId2")); + adder.setVoltageLevel2(voltageLevelId2); + String suffix2 = String.valueOf(2); + switch (getTopologKind(voltageLevelId2, network)) { + case NODE_BREAKER -> readNode(adder::setNode2, suffix2, context); + case BUS_BREAKER -> { + readBus(adder::setBus2, suffix2, context); + readConnectableBus(adder::setConnectableBus2, suffix2, context); + } } - if (node2 != null) { - adder.setNode2(node2); + } + + private static TopologyKind getTopologKind(String vlId, Network network) { + VoltageLevel vl = network.getVoltageLevel(vlId); + if (vl == null) { + throw new PowsyblException("Voltage level '" + vlId + "' not found"); } - adder.setVoltageLevel2(voltageLevelId2); + return vl.getTopologyKind(); } - public static void readNodeOrBus(int index, LegAdder adder, NetworkDeserializerContext context) { + public static void readNodeOrBus(int index, LegAdder adder, Network network, NetworkDeserializerContext context) { String voltageLevelId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId" + index)); - String bus = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(BUS + index)); - String connectableBus = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(CONNECTABLE_BUS + index)); - Integer node = context.getReader().readIntAttribute(NODE + index); - if (bus != null) { - adder.setBus(bus); - } - if (connectableBus != null) { - adder.setConnectableBus(connectableBus); - } - if (node != null) { - adder.setNode(node); - } adder.setVoltageLevel(voltageLevelId); + String suffix = String.valueOf(index); + switch (getTopologKind(voltageLevelId, network)) { + case NODE_BREAKER -> readNode(adder::setNode, suffix, context); + case BUS_BREAKER -> { + readBus(adder::setBus, suffix, context); + readConnectableBus(adder::setConnectableBus, suffix, context); + } + } } public static void writePQ(Integer index, Terminal t, TreeDataWriter writer) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index 0a527d78502..edc417ee974 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -125,7 +125,7 @@ protected void writeSubElements(DanglingLine dl, VoltageLevel vl, NetworkSeriali @Override protected DanglingLine readRootElementAttributes(DanglingLineAdder adder, VoltageLevel voltageLevel, NetworkDeserializerContext context) { - readRootElementAttributesInternal(adder, context); + readRootElementAttributesInternal(adder, voltageLevel, context); IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_10, context, () -> { String pairingKey = context.getReader().readStringAttribute("ucteXnodeCode"); adder.setPairingKey(pairingKey); @@ -139,7 +139,7 @@ protected DanglingLine readRootElementAttributes(DanglingLineAdder adder, Voltag return dl; } - public static void readRootElementAttributesInternal(DanglingLineAdder adder, NetworkDeserializerContext context) { + public static void readRootElementAttributesInternal(DanglingLineAdder adder, VoltageLevel voltageLevel, NetworkDeserializerContext context) { double p0 = context.getReader().readDoubleAttribute("p0"); double q0 = context.getReader().readDoubleAttribute("q0"); double r = context.getReader().readDoubleAttribute("r"); @@ -164,7 +164,7 @@ public static void readRootElementAttributesInternal(DanglingLineAdder adder, Ne .add(); } }); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); adder.setP0(p0) .setQ0(q0) .setR(r) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java index a82af956c44..8530828df7d 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java @@ -6,10 +6,7 @@ */ package com.powsybl.iidm.serde; -import com.powsybl.iidm.network.EnergySource; -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.GeneratorAdder; -import com.powsybl.iidm.network.VoltageLevel; +import com.powsybl.iidm.network.*; import static com.powsybl.iidm.serde.ConnectableSerDeUtil.*; @@ -65,7 +62,7 @@ protected Generator readRootElementAttributes(GeneratorAdder adder, VoltageLevel double targetP = context.getReader().readDoubleAttribute("targetP"); double targetV = context.getReader().readDoubleAttribute("targetV"); double targetQ = context.getReader().readDoubleAttribute("targetQ"); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); adder.setEnergySource(energySource) .setMinP(minP) .setMaxP(maxP) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LccConverterStationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LccConverterStationSerDe.java index 34cb62e80ec..e49d8565912 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LccConverterStationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LccConverterStationSerDe.java @@ -45,7 +45,7 @@ protected LccConverterStationAdder createAdder(VoltageLevel vl) { protected LccConverterStation readRootElementAttributes(LccConverterStationAdder adder, VoltageLevel voltageLevel, NetworkDeserializerContext context) { float lossFactor = context.getReader().readFloatAttribute("lossFactor"); float powerFactor = context.getReader().readFloatAttribute("powerFactor"); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); LccConverterStation cs = adder .setLossFactor(lossFactor) .setPowerFactor(powerFactor) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java index 99b1dc8f840..074454fe0ce 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java @@ -92,7 +92,7 @@ protected Line readRootElementAttributes(LineAdder adder, Network network, Netwo .setB1(b1) .setG2(g2) .setB2(b2); - readNodeOrBus(adder, context); + readNodeOrBus(adder, network, context); Line l = adder.add(); readPQ(1, l.getTerminal1(), context.getReader()); readPQ(2, l.getTerminal2(), context.getReader()); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LoadSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LoadSerDe.java index 77e94e8b34f..490663bd109 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LoadSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LoadSerDe.java @@ -82,11 +82,11 @@ protected LoadAdder createAdder(VoltageLevel vl) { } @Override - protected void readRootElementAttributes(LoadAdder adder, List> toApply, NetworkDeserializerContext context) { + protected void readRootElementAttributes(LoadAdder adder, VoltageLevel parent, List> toApply, NetworkDeserializerContext context) { LoadType loadType = context.getReader().readEnumAttribute("loadType", LoadType.class, LoadType.UNDEFINED); double p0 = context.getReader().readDoubleAttribute("p0"); double q0 = context.getReader().readDoubleAttribute("q0"); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, parent.getTopologyKind()); adder.setLoadType(loadType) .setP0(p0) .setQ0(q0); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java index 474171173a1..ece3e0d2ac5 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java @@ -130,7 +130,7 @@ private static void writeModel(ShuntCompensator sc, NetworkSerializerContext con } @Override - protected void readRootElementAttributes(ShuntCompensatorAdder adder, List> toApply, NetworkDeserializerContext context) { + protected void readRootElementAttributes(ShuntCompensatorAdder adder, VoltageLevel parent, List> toApply, NetworkDeserializerContext context) { IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_1, context, () -> adder.setVoltageRegulatorOn(false)); IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_2, context, () -> { double bPerSection = context.getReader().readDoubleAttribute(B_PER_SECTION); @@ -156,7 +156,7 @@ protected void readRootElementAttributes(ShuntCompensatorAdder adder, List sc.getTerminal().setP(p).setQ(q)); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java index 16c04548513..d17d3c9379a 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/StaticVarCompensatorSerDe.java @@ -80,7 +80,7 @@ protected StaticVarCompensator readRootElementAttributes(StaticVarCompensatorAdd .setVoltageSetpoint(voltageSetpoint) .setReactivePowerSetpoint(reactivePowerSetpoint) .setRegulationMode(regulationMode); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); StaticVarCompensator svc = adder.add(); readPQ(null, svc.getTerminal(), context.getReader()); return svc; diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java index 38e9d87bb89..c182e72a816 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java @@ -160,9 +160,9 @@ protected ThreeWindingsTransformer readRootElementAttributes(ThreeWindingsTransf adder.setRatedU0(ratedU0); }); - readNodeOrBus(1, legAdder1, context); - readNodeOrBus(2, legAdder2, context); - readNodeOrBus(3, legAdder3, context); + readNodeOrBus(1, legAdder1, s.getNetwork(), context); + readNodeOrBus(2, legAdder2, s.getNetwork(), context); + readNodeOrBus(3, legAdder3, s.getNetwork(), context); legAdder1.add(); legAdder2.add(); legAdder3.add(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java index 4f8864232df..b2f14d2edf2 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java @@ -178,8 +178,9 @@ protected TieLine readRootElementAttributes(TieLineAdder adder, Network network, private static DanglingLineAdder readVlAndNodeOrBus(NetworkDeserializerContext context, Network network, int side) { String voltageLevelId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId" + side)); - DanglingLineAdder adderDl1 = network.getVoltageLevel(voltageLevelId).newDanglingLine(); - readNodeOrBus(adderDl1, String.valueOf(side), context); + VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); + DanglingLineAdder adderDl1 = voltageLevel.newDanglingLine(); + readNodeOrBus(adderDl1, String.valueOf(side), context, voltageLevel.getTopologyKind()); return adderDl1; } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java index 015273fe620..f681cfce339 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java @@ -106,7 +106,7 @@ protected TwoWindingsTransformer readRootElementAttributes(TwoWindingsTransforme .setRatedU1(ratedU1) .setRatedU2(ratedU2); readRatedS("ratedS", context, adder::setRatedS); - readNodeOrBus(adder, context); + readNodeOrBus(adder, s.getNetwork(), context); TwoWindingsTransformer twt = adder.add(); readPQ(1, twt.getTerminal1(), context.getReader()); readPQ(2, twt.getTerminal2(), context.getReader()); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VscConverterStationSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VscConverterStationSerDe.java index beabbc8b29c..6ed6a10a658 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VscConverterStationSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VscConverterStationSerDe.java @@ -62,7 +62,7 @@ protected VscConverterStation readRootElementAttributes(VscConverterStationAdder float lossFactor = context.getReader().readFloatAttribute("lossFactor"); double voltageSetpoint = context.getReader().readDoubleAttribute("voltageSetpoint"); double reactivePowerSetpoint = context.getReader().readDoubleAttribute("reactivePowerSetpoint"); - readNodeOrBus(adder, context); + readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); adder .setLossFactor(lossFactor) .setVoltageSetpoint(voltageSetpoint) From 8b55683e94e147811396951250e308b4bf8627ec Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 13:16:38 +0100 Subject: [PATCH 18/42] First passing unit test V_V Signed-off-by: Florian Dupuy --- .../powsybl/commons/test/ComparisonUtils.java | 11 +++- .../iidm/serde/EurostagBinaryTest.java | 58 ++++++++++++++++++ .../eurostag-tutorial1-lf-extensions.bin | Bin 0 -> 1724 bytes .../resources/V1_11/eurostag-tutorial1-lf.bin | Bin 0 -> 1578 bytes 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java create mode 100644 iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin create mode 100644 iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf.bin diff --git a/commons-test/src/main/java/com/powsybl/commons/test/ComparisonUtils.java b/commons-test/src/main/java/com/powsybl/commons/test/ComparisonUtils.java index 6256f310c86..3dee28bf206 100644 --- a/commons-test/src/main/java/com/powsybl/commons/test/ComparisonUtils.java +++ b/commons-test/src/main/java/com/powsybl/commons/test/ComparisonUtils.java @@ -16,8 +16,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.*; /** * @author Stanislao Fidanza {@literal } @@ -46,6 +45,14 @@ public static void compareTxt(InputStream expected, InputStream actual) { } } + public static void compareBytes(InputStream expected, InputStream actual) { + try { + assertArrayEquals(expected.readAllBytes(), actual.readAllBytes()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public static void compareTxt(InputStream expected, InputStream actual, List excludedLines) { BufferedReader expectedReader = new BufferedReader(new InputStreamReader(expected)); List expectedLines = expectedReader.lines().toList(); diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java new file mode 100644 index 00000000000..143fa613e56 --- /dev/null +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2019, 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.iidm.serde; + +import com.powsybl.commons.io.TreeDataFormat; +import com.powsybl.commons.test.ComparisonUtils; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; +import com.powsybl.iidm.network.extensions.ConnectablePosition; +import com.powsybl.iidm.network.extensions.ConnectablePositionAdder; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; + +/** + * @author Geoffroy Jamgotchian {@literal } + */ +class EurostagBinaryTest extends AbstractIidmSerDeTest { + + @Test + void roundTripTest() throws IOException { + ExportOptions exportOptions = new ExportOptions().setFormat(TreeDataFormat.BIN); + ImportOptions importOptions = new ImportOptions().setFormat(TreeDataFormat.BIN); + roundTripTest(EurostagTutorialExample1Factory.createWithLFResults(), + (n, jsonFile) -> NetworkSerDe.write(n, exportOptions, jsonFile), + jsonFile -> NetworkSerDe.read(jsonFile, importOptions), + ComparisonUtils::compareBytes, + getVersionedNetworkPath("eurostag-tutorial1-lf.bin", CURRENT_IIDM_VERSION)); + + //backward compatibility + roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf.bin", IidmVersion.V_1_11); + } + + @Test + void roundTripTestWithExtension() throws IOException { + ExportOptions exportOptions = new ExportOptions().setFormat(TreeDataFormat.BIN); + ImportOptions importOptions = new ImportOptions().setFormat(TreeDataFormat.BIN); + Network network = EurostagTutorialExample1Factory.createWithLFResults(); + network.getGeneratorStream().findFirst().ifPresent(g -> g.newExtension(ActivePowerControlAdder.class).withDroop(2).withParticipate(true).add()); + network.getLoadStream().forEach(l -> l.newExtension(ConnectablePositionAdder.class).newFeeder().withDirection(ConnectablePosition.Direction.BOTTOM).add().add()); + roundTripTest(network, + (n, jsonFile) -> NetworkSerDe.write(n, exportOptions, jsonFile), + jsonFile -> NetworkSerDe.read(jsonFile, importOptions), + ComparisonUtils::compareBytes, + getVersionedNetworkPath("eurostag-tutorial1-lf-extensions.bin", CURRENT_IIDM_VERSION)); + + //backward compatibility + roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf-extensions.bin", IidmVersion.V_1_11); + } +} diff --git a/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin b/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin new file mode 100644 index 0000000000000000000000000000000000000000..9548068665454930a5c38ebe6964d106db4db4bc GIT binary patch literal 1724 zcmc&!O-vI(6n@)op)JJ%QDaO@h$bXN!ETjENVEfpVp3XcHsGyY=ukGayLES=BH16b&&Ryy20=%O)nCB{6#N;*BUCKrdW0&d+Y4Pz^Wd@Mh+{?|tuQ-Y&F5vxcpb zZp=Z@oS!l+#Zq+*LJNA{QgS$s7jParrsmBd11odbkoBUT*K>>DB{~S?u!arA(hWFT zP_;3ooWjbqr7qyOT2L($juYxhRm-Yc&Xf&BGiP+8fDI7yx{`%3aaDC$DGtvnT8^k& zENl=SC7;4GAet5~5~QkO2;j1XHIt_1FY2bsl5Cp6I7_@bc*t?RgpFZcvkW~CqSPx% z;Ms%r5=}!WGl-^Ikl<7_B3>G$gdLxm@*@#3=K$mD?(*l7|d&VWI z@LWrQHzkh{oiGSq@J+<8k0giz^;0vz-JSZK07dYDm~deg2wpC}M4qQh6^=Y8o50J_ z;IrR8{JnN_^8s>pmtH_s9tibw8f3iZL_89ccJ+ISTJ3yyFhi})`{}5XELO+p1g#L2 zY^wQt9S&^q^o`&CyS2?yE{ifc)bF03Ks0@M&}CQ671R44Cf@0zGjr(_P*wj+XZSlL>CyWoW9b%wDiOd zwfYbxY`nbCG!c&{2d@${nz9+lEzRAXIq@ZGIO9GA+GhryGlxbZ0HOmY#8sO?km?{E zD!v`CQji~lqiSy#@C&s?ziq#Mw&4)fHuqW3w9Rz2+}T@1*;}~Mt+*}= z@OJ=jj#g6-xV6o?*#*cRP(m*7T)mb$dP@??^rLc7Sur`YDDPcJ^N zKRy(8%kw6*b7%Qb*dOYn(R&?QEov*Y(3zw&A5F7Q%Fk^GRcau5h;_$>OlthRtE}A* zjy9imx3_fKqXIHEPJSW20=l)DS)m8paJp+Nyt_nMmkpcQ|C!AZXJEt72GBH=l;z|Y TNs_K3{HND0Aa>pT1M%x0+s{Gc literal 0 HcmV?d00001 diff --git a/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf.bin b/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf.bin new file mode 100644 index 0000000000000000000000000000000000000000..9b7cad27809ea7d6747f7f540cc911798010783b GIT binary patch literal 1578 zcmc&zPe>F|82@H>R@ZgKkctQbDG;QznJGzx+NWh1Y^yDccH15Gxeo5mY%}A(L$qu~ z(7B6cAa%_mtI0fI#<0PKJ1!x(a_WE3GPGL9Wl$?T-pNBBDK|>zf*fo8}g~LV5 zzG2R#u{q{jGdO7#E#HHqlzPOn$1OYWWn9ztCLFhjT~G^-IS$P<)N(Rr>GGs$=c&2T z$1deD3u!z7s^{YpMOronRqxbw0BW;}I-D>x{alBpcj#Riy}RdpSC6K3YMORh)9H=E zDA32A4+?}JG{gcSbTtj(bf%x$lwJr!WH@=PKSdp=o4En*Zq;fER3QRtO2WzzyI6XO zLQfaU0=ZY#L0F(6Lf$_7y>fH?0SdIFS5QSfgt`R{a^DLg@e-G$@_m+hNufQKW8V7R zbj(N(uVY}CRfuK@v;4h|05*T}`Y{gtr-(uWD?FPLQHj;&mGv{@KT%s(`N(4P$KA2A ziD+JUWVN!*J8EMlMyhgZE@@9hy$T8nR!C*7b%}B*WO6wtIH_dQG}zb9Y4*u3FwX(H zz+rRQOYI8_Pe{Bef*9fcCk%DN$>d<~73xN#go9*hQU`kyNmX&~eFh|_dY}o%`?$9WuUczJ9hA5LJ~N3mPNbR?VHy z!r-%zQdV4(1)b2lO+;fAbh|Cu$}S{GTOl&%x9%(+2>Zi&G;puQuD;p?jcg~`&Kp_&OGSkbp>h?(E{XP} zl1mSrmB#A#-qjY{E_=(i-B6IbcKi#CRnV>F+!DJGH|Q=gMR%#OCL6x9|1%r-10L5N AjsO4v literal 0 HcmV?d00001 From cc81b7c0d11b2b4e41e8444476723b40d470b8db Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 13:40:23 +0100 Subject: [PATCH 19/42] Fix referenceTerminal ser/de for the corner case null slack Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 7 ++-- .../com/powsybl/commons/binary/BinUtil.java | 21 +++++++++++ .../com/powsybl/commons/binary/BinWriter.java | 7 ++-- .../com/powsybl/iidm/serde/ShuntSerDe.java | 2 +- .../powsybl/iidm/serde/TerminalRefSerDe.java | 35 ++++++++++++------- .../serde/extensions/SlackTerminalSerDe.java | 5 +-- 6 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 commons/src/main/java/com/powsybl/commons/binary/BinUtil.java diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 2da47475214..7c604fb7fd1 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -17,12 +17,14 @@ import java.util.*; import java.util.function.Supplier; +import static com.powsybl.commons.binary.BinUtil.END_NODE; +import static com.powsybl.commons.binary.BinUtil.NULL_ENUM; + /** * @author Florian Dupuy {@literal } */ public class BinReader implements TreeDataReader { - private static final int END_NODE = 0; private final DataInputStream dis; private final Map dictionary = new HashMap<>(); @@ -89,7 +91,8 @@ private boolean readBoolean() { private > T readEnum(Class clazz) { try { - return clazz.getEnumConstants()[dis.readShort()]; + short ordinal = dis.readShort(); + return ordinal != NULL_ENUM ? clazz.getEnumConstants()[ordinal] : null; } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinUtil.java b/commons/src/main/java/com/powsybl/commons/binary/BinUtil.java new file mode 100644 index 00000000000..a3acbc4bece --- /dev/null +++ b/commons/src/main/java/com/powsybl/commons/binary/BinUtil.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2024, 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.commons.binary; + +/** + * @author Florian Dupuy {@literal } + */ +public final class BinUtil { + + private BinUtil() { + } + + static final int END_NODE = 0; + static final int NULL_ENUM = -1; + +} diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 6d278c45e9d..97db2018895 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -17,6 +17,9 @@ import java.util.function.DoubleSupplier; import java.util.function.IntSupplier; +import static com.powsybl.commons.binary.BinUtil.END_NODE; +import static com.powsybl.commons.binary.BinUtil.NULL_ENUM; + /** * @author Florian Dupuy {@literal } */ @@ -115,7 +118,7 @@ public void writeStartNode(String namespace, String name) { @Override public void writeEndNode() { - writeIndex(0, tmpDos); + writeIndex(END_NODE, tmpDos); } @Override @@ -212,7 +215,7 @@ public void writeStringArrayAttribute(String name, Collection values) { @Override public > void writeEnumAttribute(String name, E value) { - writeIndex(value.ordinal(), tmpDos); + writeIndex(value != null ? value.ordinal() : NULL_ENUM, tmpDos); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java index ece3e0d2ac5..43a96942a18 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java @@ -168,7 +168,7 @@ protected void readSubElements(String id, ShuntCompensatorAdder adder, List { String regId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("id")); - String regSide = context.getReader().readStringAttribute("side"); + ThreeSides regSide = context.getReader().readEnumAttribute("side", ThreeSides.class); context.getReader().readEndNode(); toApply.add(sc -> context.getEndTasks().add(() -> sc.setRegulatingTerminal(TerminalRefSerDe.resolve(regId, regSide, sc.getNetwork())))); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java index ade98f6a3e2..435f032daa5 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java @@ -11,6 +11,7 @@ import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.iidm.network.*; +import java.util.Optional; import java.util.function.Consumer; /** @@ -39,8 +40,24 @@ public static void writeTerminalRefAttribute(Terminal t, NetworkSerializerContex writeTerminalRefAttribute(t, context, context.getWriter()); } - public static void writeTerminalRefAttribute(Terminal t, NetworkSerializerContext context, TreeDataWriter writer) { - Connectable c = t.getConnectable(); + public static void writeTerminalRefAttribute(Terminal terminal, NetworkSerializerContext context, TreeDataWriter writer) { + + String connectableId = Optional.ofNullable(terminal) + .map(t -> { + checkTerminal(t, context); + return context.getAnonymizer().anonymizeString(t.getConnectable().getId()); + }) + .orElse(null); + ThreeSides tSide = Optional.ofNullable(terminal) + .flatMap(Terminal::getConnectableSide) + .orElse(null); + + writer.writeStringAttribute("id", connectableId); + writer.writeEnumAttribute("side", tSide); + } + + private static void checkTerminal(Terminal t, NetworkSerializerContext context) { + Connectable c = t.getConnectable(); if (!context.getFilter().test(c)) { throw new PowsyblException("Oups, terminal ref point to a filtered equipment " + c.getId()); } @@ -50,21 +67,18 @@ public static void writeTerminalRefAttribute(Terminal t, NetworkSerializerContex throw new PowsyblException(String.format("Terminal ref should not point to a busbar section (here %s). Try to export in node-breaker or delete this terminal ref.", t.getConnectable().getId())); } - writer.writeStringAttribute("id", context.getAnonymizer().anonymizeString(c.getId())); - - Terminal.getConnectableSide(t).ifPresent(side -> writer.writeStringAttribute("side", side.name())); } public static Terminal readTerminal(NetworkDeserializerContext context, Network n) { String id = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(ID)); - String side = context.getReader().readStringAttribute(SIDE); + ThreeSides side = context.getReader().readEnumAttribute(SIDE, ThreeSides.class); context.getReader().readEndNode(); return TerminalRefSerDe.resolve(id, side, n); } public static void readTerminalRef(NetworkDeserializerContext context, Network network, Consumer endTaskTerminalConsumer) { String id = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(ID)); - String side = context.getReader().readStringAttribute(SIDE); + ThreeSides side = context.getReader().readEnumAttribute(SIDE, ThreeSides.class); context.getReader().readEndNode(); context.getEndTasks().add(() -> { Terminal t = resolve(id, side, network); @@ -72,17 +86,12 @@ public static void readTerminalRef(NetworkDeserializerContext context, Network n }); } - public static Terminal resolve(String id, String sideText, Network network) { - ThreeSides side = sideText == null ? ThreeSides.ONE : ThreeSides.valueOf(sideText); - return TerminalRefSerDe.resolve(id, side, network); - } - public static Terminal resolve(String id, ThreeSides side, Network network) { Identifiable identifiable = network.getIdentifiable(id); if (identifiable == null) { throw new PowsyblException("Terminal reference identifiable not found: '" + id + "'"); } - return Terminal.getTerminal(identifiable, side); + return Terminal.getTerminal(identifiable, side != null ? side : ThreeSides.ONE); } private TerminalRefSerDe() { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/SlackTerminalSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/SlackTerminalSerDe.java index 7818f3a880b..6159385fa17 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/SlackTerminalSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/SlackTerminalSerDe.java @@ -72,10 +72,7 @@ public List getXsdAsStreamList() { @Override public void write(SlackTerminal slackTerminal, SerializerContext context) { - Terminal terminal = slackTerminal.getTerminal(); - if (terminal != null) { - TerminalRefSerDe.writeTerminalRefAttribute(slackTerminal.getTerminal(), (NetworkSerializerContext) context); - } + TerminalRefSerDe.writeTerminalRefAttribute(slackTerminal.getTerminal(), (NetworkSerializerContext) context); } @Override From 643dd2dcf02dd76dffae9928c3f187402ae205fb Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 14:07:03 +0100 Subject: [PATCH 20/42] Fix referenceTerminal ser/de for the corner case null slack Signed-off-by: Florian Dupuy --- .../com/powsybl/iidm/serde/AbstractTransformerSerDe.java | 8 ++------ .../java/com/powsybl/iidm/serde/TerminalRefSerDe.java | 8 +++++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index aa5a181a4e0..4dc077ca99c 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -79,9 +79,7 @@ protected static void writeRatioTapChanger(String name, RatioTapChanger rtc, Net writeTapChanger(rtc, context); context.getWriter().writeBooleanAttribute("loadTapChangingCapabilities", rtc.hasLoadTapChangingCapabilities()); context.getWriter().writeDoubleAttribute("targetV", rtc.getTargetV()); - if (rtc.getRegulationTerminal() != null) { - TerminalRefSerDe.writeTerminalRef(rtc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); - } + TerminalRefSerDe.writeTerminalRef(rtc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); context.getWriter().writeStartNodes(); for (int p = rtc.getLowTapPosition(); p <= rtc.getHighTapPosition(); p++) { @@ -156,9 +154,7 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net writeTapChanger(ptc, context); context.getWriter().writeEnumAttribute("regulationMode", ptc.getRegulationMode()); context.getWriter().writeDoubleAttribute("regulationValue", ptc.getRegulationValue()); - if (ptc.getRegulationTerminal() != null) { - TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); - } + TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); context.getWriter().writeStartNodes(); for (int p = ptc.getLowTapPosition(); p <= ptc.getHighTapPosition(); p++) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java index 435f032daa5..4e376671782 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TerminalRefSerDe.java @@ -31,9 +31,11 @@ public static void writeTerminalRef(Terminal t, NetworkSerializerContext context } public static void writeTerminalRef(Terminal t, NetworkSerializerContext context, String namespace, String elementName, TreeDataWriter writer) { - writer.writeStartNode(namespace, elementName); - writeTerminalRefAttribute(t, context, writer); - writer.writeEndNode(); + if (t != null) { + writer.writeStartNode(namespace, elementName); + writeTerminalRefAttribute(t, context, writer); + writer.writeEndNode(); + } } public static void writeTerminalRefAttribute(Terminal t, NetworkSerializerContext context) { From 14d362ab10dff2792719e5b257a9fe607e0f662d Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 14:12:31 +0100 Subject: [PATCH 21/42] Simplify optional writing Signed-off-by: Florian Dupuy --- .../extensions/CgmesTapChangersSerDe.java | 3 +- .../com/powsybl/commons/binary/BinWriter.java | 43 ++++--------------- .../commons/io/AbstractTreeDataWriter.java | 20 ++------- .../powsybl/commons/io/TreeDataWriter.java | 6 +-- .../iidm/serde/AbstractTransformerSerDe.java | 15 ++++--- .../iidm/serde/ConnectableSerDeUtil.java | 6 ++- .../iidm/serde/VoltageAngleLimitSerDe.java | 10 ++++- .../extensions/ConnectablePositionSerDe.java | 2 +- 8 files changed, 35 insertions(+), 70 deletions(-) diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java index 16512eb032b..d927be024e5 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java @@ -52,8 +52,7 @@ public void write(CgmesTapChangers extension, SerializerContext context) { writer.writeStringAttribute("type", tapChanger.getType()); writer.writeBooleanAttribute("hidden", tapChanger.isHidden(), false); writer.writeOptionalIntAttribute("step", - () -> tapChanger.getStep().orElseThrow(() -> new PowsyblException("Step should be defined")), - tapChanger::isHidden); + !tapChanger.isHidden() ? null : tapChanger.getStep().orElseThrow(() -> new PowsyblException("Step should be defined"))); writer.writeStringAttribute("controlId", tapChanger.getControlId()); writer.writeEndNode(); } diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 97db2018895..49284e2e336 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -11,11 +11,11 @@ import java.io.*; import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.function.BooleanSupplier; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; import java.util.function.Consumer; -import java.util.function.DoubleSupplier; -import java.util.function.IntSupplier; import static com.powsybl.commons.binary.BinUtil.END_NODE; import static com.powsybl.commons.binary.BinUtil.NULL_ENUM; @@ -155,19 +155,6 @@ public void writeDoubleAttribute(String name, double value, double absentValue) writeDouble(value); } - @Override - public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write) { - try { - boolean writeValue = write.getAsBoolean(); - tmpDos.writeBoolean(writeValue); - if (writeValue) { - writeDouble(valueSupplier.getAsDouble()); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - @Override public void writeOptionalDoubleAttribute(String name, Double value) { try { @@ -191,12 +178,11 @@ public void writeIntAttribute(String name, int value, int absentValue) { } @Override - public void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write) { + public void writeOptionalIntAttribute(String name, Integer value) { try { - boolean writeValue = write.getAsBoolean(); - tmpDos.writeBoolean(writeValue); - if (writeValue) { - writeDouble(valueSupplier.getAsInt()); + tmpDos.writeBoolean(value != null); + if (value != null) { + writeInt(value); } } catch (IOException e) { throw new UncheckedIOException(e); @@ -228,19 +214,6 @@ public void writeBooleanAttribute(String name, boolean value, boolean absentValu writeBoolean(value); } - @Override - public void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write) { - try { - boolean writeValue = write.getAsBoolean(); - tmpDos.writeBoolean(writeValue); - if (writeValue) { - writeBoolean(valueSupplier.getAsBoolean()); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - @Override public void writeOptionalBooleanAttribute(String name, Boolean value) { try { diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java index d87073844d1..6a9ea5e08c9 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -16,13 +16,6 @@ */ public abstract class AbstractTreeDataWriter implements TreeDataWriter { - @Override - public void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write) { - if (write.getAsBoolean()) { - writeBooleanAttribute(name, valueSupplier.getAsBoolean()); - } - } - @Override public void writeOptionalBooleanAttribute(String name, Boolean value) { if (value != null) { @@ -30,13 +23,6 @@ public void writeOptionalBooleanAttribute(String name, Boolean value) { } } - @Override - public void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write) { - if (write.getAsBoolean()) { - writeDoubleAttribute(name, valueSupplier.getAsDouble()); - } - } - @Override public void writeOptionalDoubleAttribute(String name, Double value) { if (value != null) { @@ -45,9 +31,9 @@ public void writeOptionalDoubleAttribute(String name, Double value) { } @Override - public void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write) { - if (write.getAsBoolean()) { - writeIntAttribute(name, valueSupplier.getAsInt()); + public void writeOptionalIntAttribute(String name, Integer value) { + if (value != null) { + writeIntAttribute(name, value); } } } diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index 6d07a72ce41..5c9cea42f96 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -37,15 +37,13 @@ public interface TreeDataWriter extends AutoCloseable { void writeDoubleAttribute(String name, double value, double absentValue); - void writeOptionalDoubleAttribute(String name, DoubleSupplier valueSupplier, BooleanSupplier write); - void writeOptionalDoubleAttribute(String name, Double value); void writeIntAttribute(String name, int value); void writeIntAttribute(String name, int value, int absentValue); - void writeOptionalIntAttribute(String name, IntSupplier valueSupplier, BooleanSupplier write); + void writeOptionalIntAttribute(String name, Integer value); void writeIntArrayAttribute(String name, Collection values); @@ -57,8 +55,6 @@ public interface TreeDataWriter extends AutoCloseable { void writeBooleanAttribute(String name, boolean value, boolean absentValue); - void writeOptionalBooleanAttribute(String name, BooleanSupplier valueSupplier, BooleanSupplier write); - void writeOptionalBooleanAttribute(String name, Boolean value); @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 4dc077ca99c..87ca6b5ab1a 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -9,6 +9,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.PhaseTapChanger.RegulationMode; import com.powsybl.iidm.serde.util.IidmSerDeUtil; import java.util.function.DoubleConsumer; @@ -67,7 +68,7 @@ private static double readTargetDeadband(NetworkDeserializerContext context, boo private static void writeTapChanger(TapChanger tc, NetworkSerializerContext context) { context.getWriter().writeIntAttribute(ATTR_LOW_TAP_POSITION, tc.getLowTapPosition()); var tp = tc.findTapPosition(); - context.getWriter().writeOptionalIntAttribute(ATTR_TAP_POSITION, tp::orElseThrow, tp::isPresent); + context.getWriter().writeOptionalIntAttribute(ATTR_TAP_POSITION, tp.isPresent() ? tp.getAsInt() : null); writeTargetDeadband(tc.getTargetDeadband(), context); } @@ -147,12 +148,14 @@ protected static void readRatioTapChanger(int leg, ThreeWindingsTransformer.Leg } protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, NetworkSerializerContext context) { - boolean nonFixedRegulationMode = ptc.getRegulationMode() != null && ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP; - context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), name); - context.getWriter().writeOptionalBooleanAttribute(ATTR_REGULATING, ptc::isRegulating, () -> nonFixedRegulationMode || ptc.isRegulating()); + + RegulationMode regMode = ptc.getRegulationMode(); + Boolean optionalRegulatingValue = (regMode == null || regMode == RegulationMode.FIXED_TAP) && !ptc.isRegulating() ? null : ptc.isRegulating(); + context.getWriter().writeOptionalBooleanAttribute(ATTR_REGULATING, optionalRegulatingValue); + writeTapChanger(ptc, context); - context.getWriter().writeEnumAttribute("regulationMode", ptc.getRegulationMode()); + context.getWriter().writeEnumAttribute("regulationMode", regMode); context.getWriter().writeDoubleAttribute("regulationValue", ptc.getRegulationValue()); TerminalRefSerDe.writeTerminalRef(ptc.getRegulationTerminal(), context, ELEM_TERMINAL_REF); @@ -174,7 +177,7 @@ protected static void readPhaseTapChanger(String name, PhaseTapChangerAdder adde int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); Integer tapPosition = context.getReader().readIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); - PhaseTapChanger.RegulationMode regulationMode = context.getReader().readEnumAttribute("regulationMode", PhaseTapChanger.RegulationMode.class); + RegulationMode regulationMode = context.getReader().readEnumAttribute("regulationMode", RegulationMode.class); double regulationValue = context.getReader().readDoubleAttribute("regulationValue"); adder.setLowTapPosition(lowTapPosition) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index 626954081ca..3a4c78d15fd 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -173,8 +173,10 @@ public static void writePQ(Integer index, Terminal t, TreeDataWriter writer) { } public static void writeOptionalPQ(Integer index, Terminal t, TreeDataWriter writer, BooleanSupplier write) { - writer.writeOptionalDoubleAttribute("p" + indexToString(index), t::getP, write); - writer.writeOptionalDoubleAttribute("q" + indexToString(index), t::getQ, write); + Double nullableP = write.getAsBoolean() ? t.getP() : null; + Double nullableQ = write.getAsBoolean() ? t.getQ() : null; + writer.writeOptionalDoubleAttribute("p" + indexToString(index), nullableP); + writer.writeOptionalDoubleAttribute("q" + indexToString(index), nullableQ); } public static void readPQ(Integer index, Terminal t, TreeDataReader reader) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java index 441ffa3aaa0..d8283671c71 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java @@ -15,6 +15,8 @@ import com.powsybl.iidm.network.VoltageAngleLimitAdder; import com.powsybl.iidm.serde.util.IidmSerDeUtil; +import java.util.OptionalDouble; + /** * * @author Luma Zamarreño {@literal } @@ -34,8 +36,12 @@ public static void write(VoltageAngleLimit voltageAngleLimit, NetworkSerializerC IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, () -> { context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), ROOT_ELEMENT_NAME); context.getWriter().writeStringAttribute(ID, context.getAnonymizer().anonymizeString(voltageAngleLimit.getId())); - context.getWriter().writeOptionalDoubleAttribute(LOW_LIMIT, () -> voltageAngleLimit.getLowLimit().orElse(Double.NaN), voltageAngleLimit.getLowLimit()::isPresent); - context.getWriter().writeOptionalDoubleAttribute(HIGH_LIMIT, () -> voltageAngleLimit.getHighLimit().orElse(Double.NaN), voltageAngleLimit.getHighLimit()::isPresent); + + OptionalDouble lowLimit = voltageAngleLimit.getLowLimit(); + OptionalDouble highLimit = voltageAngleLimit.getLowLimit(); + context.getWriter().writeOptionalDoubleAttribute(LOW_LIMIT, lowLimit.isPresent() ? lowLimit.getAsDouble() : null); + context.getWriter().writeOptionalDoubleAttribute(HIGH_LIMIT, highLimit.isPresent() ? highLimit.getAsDouble() : null); + TerminalRefSerDe.writeTerminalRef(voltageAngleLimit.getTerminalFrom(), context, FROM); TerminalRefSerDe.writeTerminalRef(voltageAngleLimit.getTerminalTo(), context, TO); context.getWriter().writeEndNode(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java index c080d705fab..7060cc49859 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java @@ -71,7 +71,7 @@ private void writePosition(String connectableId, ConnectablePosition.Feeder feed default: throw new PowsyblException("Unsupported version (" + extVersionStr + ") for " + ConnectablePosition.NAME); } - context.getWriter().writeOptionalIntAttribute("order", feeder.getOrder()::orElseThrow, feeder.getOrder()::isPresent); + context.getWriter().writeOptionalIntAttribute("order", feeder.getOrder().orElse(null)); context.getWriter().writeStringAttribute("direction", feeder.getDirection().name()); context.getWriter().writeEndNode(); } From 841227c15b825e3f85cbe62ce125c9cdee168942 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 14:35:56 +0100 Subject: [PATCH 22/42] Add readOptionalIntAttribute Signed-off-by: Florian Dupuy --- .../extensions/CgmesTapChangersSerDe.java | 7 +++---- .../com/powsybl/commons/binary/BinReader.java | 7 ++++++- .../powsybl/commons/io/TreeDataReader.java | 4 +++- .../com/powsybl/commons/json/JsonReader.java | 11 +++++++++- .../com/powsybl/commons/xml/XmlReader.java | 12 ++++++++++- .../iidm/serde/AbstractTransformerSerDe.java | 4 ++-- .../iidm/serde/ConnectableSerDeUtil.java | 5 +---- .../extensions/ConnectablePositionSerDe.java | 2 +- .../extensions/DiscreteMeasurementsSerDe.java | 21 ++++++------------- 9 files changed, 43 insertions(+), 30 deletions(-) diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java index d927be024e5..8f1b5f97060 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java @@ -19,6 +19,7 @@ import com.powsybl.iidm.serde.NetworkSerializerContext; import java.util.Map; +import java.util.Optional; /** * @author Miora Vedelago {@literal } @@ -73,10 +74,8 @@ public CgmesTapChangers read(C extendable, DeserializerContext context) { .setType(reader.readStringAttribute("type")) .setHiddenStatus(reader.readBooleanAttribute("hidden", false)) .setControlId(reader.readStringAttribute("controlId")); - Integer step = reader.readIntAttribute("step"); - if (step != null) { - adder.setStep(step); - } + Optional.ofNullable(reader.readOptionalIntAttribute("step")) + .ifPresent(adder::setStep); context.getReader().readEndNode(); adder.add(); } else { diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 7c604fb7fd1..694e5e91021 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -156,10 +156,15 @@ public String readStringAttribute(String name) { } @Override - public Integer readIntAttribute(String name) { + public int readIntAttribute(String name) { return readInt(); } + @Override + public Integer readOptionalIntAttribute(String name) { + return readBoolean() ? readInt() : null; + } + @Override public int readIntAttribute(String name, int defaultValue) { return readInt(); diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java index 16a9cfd9aec..bf5f425de2d 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java @@ -38,7 +38,9 @@ interface ChildNodeReader { String readStringAttribute(String name); - Integer readIntAttribute(String name); + int readIntAttribute(String name); + + Integer readOptionalIntAttribute(String name); int readIntAttribute(String name, int defaultValue); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java index 8635822fb42..30f8adc497d 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java @@ -112,7 +112,16 @@ private String readStringAttribute(String name, boolean throwException) { } @Override - public Integer readIntAttribute(String name) { + public int readIntAttribute(String name) { + String fieldName = getFieldName(); + if (!Objects.requireNonNull(name).equals(fieldName)) { + throw new PowsyblException("JSON parsing: expected '" + name + "' but got '" + fieldName + "'"); + } + return getIntValue(); + } + + @Override + public Integer readOptionalIntAttribute(String name) { return Objects.requireNonNull(name).equals(getFieldName()) ? getIntValue() : null; } diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java index 7e2ee3e489f..f2d7ee96872 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java @@ -8,6 +8,7 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.powsybl.commons.PowsyblException; import com.powsybl.commons.exceptions.UncheckedXmlStreamException; import com.powsybl.commons.extensions.ExtensionSerDe; import com.powsybl.commons.io.AbstractTreeDataReader; @@ -73,7 +74,16 @@ public String readStringAttribute(String name) { } @Override - public Integer readIntAttribute(String name) { + public int readIntAttribute(String name) { + Integer value = XmlUtil.readIntegerAttribute(reader, name); + if (value == null) { + throw new PowsyblException("XML parsing: unknown required attribute '" + name + "'"); + } + return value; + } + + @Override + public Integer readOptionalIntAttribute(String name) { return XmlUtil.readIntegerAttribute(reader, name); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 87ca6b5ab1a..1ab9df8bdc5 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -97,7 +97,7 @@ protected static void writeRatioTapChanger(String name, RatioTapChanger rtc, Net protected static void readRatioTapChanger(String elementName, RatioTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { boolean regulating = context.getReader().readBooleanAttribute(ATTR_REGULATING, false); int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); - Integer tapPosition = context.getReader().readIntAttribute(ATTR_TAP_POSITION); + Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); boolean loadTapChangingCapabilities = context.getReader().readBooleanAttribute("loadTapChangingCapabilities"); double targetV = context.getReader().readDoubleAttribute("targetV"); @@ -175,7 +175,7 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net protected static void readPhaseTapChanger(String name, PhaseTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { boolean regulating = context.getReader().readBooleanAttribute(ATTR_REGULATING, false); int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); - Integer tapPosition = context.getReader().readIntAttribute(ATTR_TAP_POSITION); + Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); RegulationMode regulationMode = context.getReader().readEnumAttribute("regulationMode", RegulationMode.class); double regulationValue = context.getReader().readDoubleAttribute("regulationValue"); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index 3a4c78d15fd..25aa65aaf86 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -108,10 +108,7 @@ public static void readNodeOrBus(InjectionAdder adder, String suffix, Netw } private static void readNode(IntConsumer nodeAdder, String suffix, NetworkDeserializerContext context) { - Integer node = context.getReader().readIntAttribute(NODE + suffix); - if (node != null) { - nodeAdder.accept(node); - } + nodeAdder.accept(context.getReader().readIntAttribute(NODE + suffix)); } private static void readBus(Consumer busAdder, String suffix, NetworkDeserializerContext context) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java index 7060cc49859..d31223ed24a 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java @@ -96,7 +96,7 @@ public void write(ConnectablePosition connectablePosition, SerializerContext private void readPosition(DeserializerContext context, ConnectablePositionAdder.FeederAdder adder) { String name = context.getReader().readStringAttribute("name"); - Optional.ofNullable(context.getReader().readIntAttribute("order")). + Optional.ofNullable(context.getReader().readOptionalIntAttribute("order")). ifPresent(adder::withOrder); ConnectablePosition.Direction direction = context.getReader().readEnumAttribute("direction", ConnectablePosition.Direction.class); context.getReader().readEndNode(); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java index 39c56afe8c7..3ef9ccf1221 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java @@ -57,17 +57,9 @@ public void write(DiscreteMeasurements extension, SerializerContext context) writer.writeEnumAttribute("tapChanger", discreteMeasurement.getTapChanger()); writer.writeEnumAttribute("valueType", discreteMeasurement.getValueType()); switch (discreteMeasurement.getValueType()) { - case BOOLEAN: - writer.writeBooleanAttribute(VALUE, discreteMeasurement.getValueAsBoolean()); - break; - case INT: - writer.writeIntAttribute(VALUE, discreteMeasurement.getValueAsInt()); - break; - case STRING: - writer.writeStringAttribute(VALUE, discreteMeasurement.getValueAsString()); - break; - default: - throw new PowsyblException("Unsupported serialization for value type: " + discreteMeasurement.getValueType()); + case BOOLEAN -> writer.writeBooleanAttribute(VALUE, discreteMeasurement.getValueAsBoolean()); + case INT -> writer.writeIntAttribute(VALUE, discreteMeasurement.getValueAsInt()); + case STRING -> writer.writeStringAttribute(VALUE, discreteMeasurement.getValueAsString()); } writer.writeBooleanAttribute("valid", discreteMeasurement.isValid()); @@ -110,10 +102,9 @@ private static > void readDiscreteMeasurement(Discrete .setType(type) .setTapChanger(tapChanger); switch (valueType) { - case BOOLEAN -> Optional.ofNullable(reader.readBooleanAttribute(VALUE)).ifPresent(adder::setValue); - case INT -> Optional.ofNullable(reader.readIntAttribute(VALUE)).ifPresent(adder::setValue); - case STRING -> Optional.ofNullable(reader.readStringAttribute(VALUE)).ifPresent(adder::setValue); - default -> throw new PowsyblException("Unsupported value type: " + valueType); + case BOOLEAN -> adder.setValue(reader.readBooleanAttribute(VALUE)); + case INT -> adder.setValue(reader.readIntAttribute(VALUE)); + case STRING -> adder.setValue(reader.readStringAttribute(VALUE)); } adder.setValid(reader.readBooleanAttribute("valid", true)); From 59249de1183a72ac3d9e75db4f7b978405355131 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 15:16:03 +0100 Subject: [PATCH 23/42] Add readOptionalDoubleAttribute Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 5 ++++ .../powsybl/commons/io/TreeDataReader.java | 2 ++ .../com/powsybl/commons/json/JsonReader.java | 5 ++++ .../com/powsybl/commons/xml/XmlReader.java | 5 ++++ .../java/com/powsybl/commons/xml/XmlUtil.java | 5 ++++ .../iidm/serde/ConnectableSerDeUtil.java | 7 +++++ .../powsybl/iidm/serde/DanglingLineSerDe.java | 26 +++++++++---------- .../com/powsybl/iidm/serde/LineSerDe.java | 4 +-- .../serde/ThreeWindingsTransformerSerDe.java | 6 ++--- .../com/powsybl/iidm/serde/TieLineSerDe.java | 14 +++++----- .../serde/TwoWindingsTransformerSerDe.java | 4 +-- .../iidm/serde/VoltageAngleLimitSerDe.java | 13 ++++------ 12 files changed, 62 insertions(+), 34 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 694e5e91021..d7e8f404855 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -140,6 +140,11 @@ public double readDoubleAttribute(String name, double defaultValue) { return readDouble(); } + @Override + public Double readOptionalDoubleAttribute(String name) { + return readBoolean() ? readDouble() : null; + } + @Override public float readFloatAttribute(String name) { return readFloat(); diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java index bf5f425de2d..183c7edef5d 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java @@ -32,6 +32,8 @@ interface ChildNodeReader { double readDoubleAttribute(String name, double defaultValue); + Double readOptionalDoubleAttribute(String name); + float readFloatAttribute(String name); float readFloatAttribute(String name, float defaultValue); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java index 30f8adc497d..818efeefc9c 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java @@ -83,6 +83,11 @@ public double readDoubleAttribute(String name, double defaultValue) { return Objects.requireNonNull(name).equals(getFieldName()) ? getDoubleValue() : defaultValue; } + @Override + public Double readOptionalDoubleAttribute(String name) { + return Objects.requireNonNull(name).equals(getFieldName()) ? getDoubleValue() : null; + } + @Override public float readFloatAttribute(String name, float defaultValue) { return Objects.requireNonNull(name).equals(getFieldName()) ? getFloatValue() : defaultValue; diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java index f2d7ee96872..02abfdfafa5 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java @@ -63,6 +63,11 @@ public double readDoubleAttribute(String name, double defaultValue) { return XmlUtil.readDoubleAttribute(reader, name, defaultValue); } + @Override + public Double readOptionalDoubleAttribute(String name) { + return XmlUtil.readOptionalDoubleAttribute(reader, name); + } + @Override public float readFloatAttribute(String name, float defaultValue) { return XmlUtil.readFloatAttribute(reader, name, defaultValue); diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java b/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java index f4c046b9d4b..e41064cfbc2 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java @@ -132,6 +132,11 @@ public static double readDoubleAttribute(XMLStreamReader reader, String name, do return attributeValue != null ? Double.parseDouble(attributeValue) : defaultValue; } + public static Double readOptionalDoubleAttribute(XMLStreamReader reader, String name) { + String attributeValue = reader.getAttributeValue(null, name); + return attributeValue != null ? Double.parseDouble(attributeValue) : null; + } + public static float readFloatAttribute(XMLStreamReader reader, String name, float defaultValue) { String attributeValue = reader.getAttributeValue(null, name); return attributeValue != null ? Float.parseFloat(attributeValue) : defaultValue; diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index 25aa65aaf86..3177d074584 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -183,6 +183,13 @@ public static void readPQ(Integer index, Terminal t, TreeDataReader reader) { .setQ(q); } + public static void readOptionalPQ(Integer index, Terminal t, TreeDataReader reader) { + Double p = reader.readOptionalDoubleAttribute("p" + indexToString(index)); + Double q = reader.readOptionalDoubleAttribute("q" + indexToString(index)); + Optional.ofNullable(p).ifPresent(t::setP); + Optional.ofNullable(q).ifPresent(t::setQ); + } + public static void readActivePowerLimits(ActivePowerLimitsAdder activePowerLimitsAdder, TreeDataReader reader) { readLoadingLimits(ACTIVE_POWER_LIMITS, activePowerLimitsAdder, reader); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index edc417ee974..894b202ff0f 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -148,20 +148,20 @@ public static void readRootElementAttributesInternal(DanglingLineAdder adder, Vo double b = context.getReader().readDoubleAttribute("b"); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { Boolean voltageRegulationOn = context.getReader().readBooleanAttribute("generationVoltageRegulationOn"); + Double minP = context.getReader().readOptionalDoubleAttribute(GENERATION_MIN_P); + Double maxP = context.getReader().readOptionalDoubleAttribute(GENERATION_MAX_P); + Double targetP = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_P); + Double targetV = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_V); + Double targetQ = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_Q); if (voltageRegulationOn != null) { - double minP = context.getReader().readDoubleAttribute(GENERATION_MIN_P); - double maxP = context.getReader().readDoubleAttribute(GENERATION_MAX_P); - double targetP = context.getReader().readDoubleAttribute(GENERATION_TARGET_P); - double targetV = context.getReader().readDoubleAttribute(GENERATION_TARGET_V); - double targetQ = context.getReader().readDoubleAttribute(GENERATION_TARGET_Q); - adder.newGeneration() - .setMinP(minP) - .setMaxP(maxP) - .setVoltageRegulationOn(voltageRegulationOn) - .setTargetP(targetP) - .setTargetV(targetV) - .setTargetQ(targetQ) - .add(); + DanglingLineAdder.GenerationAdder generationAdder = adder.newGeneration() + .setVoltageRegulationOn(voltageRegulationOn); + Optional.ofNullable(minP).ifPresent(generationAdder::setMinP); + Optional.ofNullable(maxP).ifPresent(generationAdder::setMaxP); + Optional.ofNullable(targetP).ifPresent(generationAdder::setTargetP); + Optional.ofNullable(targetV).ifPresent(generationAdder::setTargetV); + Optional.ofNullable(targetQ).ifPresent(generationAdder::setTargetQ); + generationAdder.add(); } }); readNodeOrBus(adder, context, voltageLevel.getTopologyKind()); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java index 074454fe0ce..4380df06bcd 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java @@ -94,8 +94,8 @@ protected Line readRootElementAttributes(LineAdder adder, Network network, Netwo .setB2(b2); readNodeOrBus(adder, network, context); Line l = adder.add(); - readPQ(1, l.getTerminal1(), context.getReader()); - readPQ(2, l.getTerminal2(), context.getReader()); + readOptionalPQ(1, l.getTerminal1(), context.getReader()); + readOptionalPQ(2, l.getTerminal2(), context.getReader()); return l; } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java index c182e72a816..fe8009d91f1 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ThreeWindingsTransformerSerDe.java @@ -167,9 +167,9 @@ protected ThreeWindingsTransformer readRootElementAttributes(ThreeWindingsTransf legAdder2.add(); legAdder3.add(); ThreeWindingsTransformer twt = adder.add(); - readPQ(1, twt.getLeg1().getTerminal(), context.getReader()); - readPQ(2, twt.getLeg2().getTerminal(), context.getReader()); - readPQ(3, twt.getLeg3().getTerminal(), context.getReader()); + readOptionalPQ(1, twt.getLeg1().getTerminal(), context.getReader()); + readOptionalPQ(2, twt.getLeg2().getTerminal(), context.getReader()); + readOptionalPQ(3, twt.getLeg3().getTerminal(), context.getReader()); return twt; } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java index b2f14d2edf2..a9a738d980c 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java @@ -158,14 +158,16 @@ protected TieLine readRootElementAttributes(TieLineAdder adder, Network network, String pairingKey = context.getReader().readStringAttribute("ucteXnodeCode"); DanglingLineAdder adderDl1 = readVlAndNodeOrBus(context, network, 1); DanglingLineAdder adderDl2 = readVlAndNodeOrBus(context, network, 2); - double p1 = context.getReader().readDoubleAttribute("p1"); - double q1 = context.getReader().readDoubleAttribute("q1"); - double p2 = context.getReader().readDoubleAttribute("p2"); - double q2 = context.getReader().readDoubleAttribute("q2"); + Double p1 = context.getReader().readOptionalDoubleAttribute("p1"); + Double q1 = context.getReader().readOptionalDoubleAttribute("q1"); + Double p2 = context.getReader().readOptionalDoubleAttribute("p2"); + Double q2 = context.getReader().readOptionalDoubleAttribute("q2"); DanglingLine dl1 = readDanglingLine(adderDl1, pairingKey, context, 1); DanglingLine dl2 = readDanglingLine(adderDl2, pairingKey, context, 2); - dl1.getTerminal().setP(p1).setQ(q1); - dl2.getTerminal().setP(p2).setQ(q2); + Optional.ofNullable(p1).ifPresent(dl1.getTerminal()::setP); + Optional.ofNullable(q1).ifPresent(dl1.getTerminal()::setQ); + Optional.ofNullable(p2).ifPresent(dl2.getTerminal()::setP); + Optional.ofNullable(q2).ifPresent(dl2.getTerminal()::setQ); adder.setDanglingLine1(dl1.getId()).setDanglingLine2(dl2.getId()); }); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_10, context, () -> { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java index f681cfce339..bf2779769f4 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java @@ -108,8 +108,8 @@ protected TwoWindingsTransformer readRootElementAttributes(TwoWindingsTransforme readRatedS("ratedS", context, adder::setRatedS); readNodeOrBus(adder, s.getNetwork(), context); TwoWindingsTransformer twt = adder.add(); - readPQ(1, twt.getTerminal1(), context.getReader()); - readPQ(2, twt.getTerminal2(), context.getReader()); + readOptionalPQ(1, twt.getTerminal1(), context.getReader()); + readOptionalPQ(2, twt.getTerminal2(), context.getReader()); return twt; } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java index d8283671c71..18ff23492dc 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java @@ -15,6 +15,7 @@ import com.powsybl.iidm.network.VoltageAngleLimitAdder; import com.powsybl.iidm.serde.util.IidmSerDeUtil; +import java.util.Optional; import java.util.OptionalDouble; /** @@ -52,17 +53,13 @@ public static void read(Network network, NetworkDeserializerContext context) { IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, () -> { String id = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(ID)); - double lowLimit = context.getReader().readDoubleAttribute(LOW_LIMIT); - double highLimit = context.getReader().readDoubleAttribute(HIGH_LIMIT); + Double lowLimit = context.getReader().readOptionalDoubleAttribute(LOW_LIMIT); + Double highLimit = context.getReader().readOptionalDoubleAttribute(HIGH_LIMIT); VoltageAngleLimitAdder adder = network.newVoltageAngleLimit(); adder.setId(id); - if (!Double.isNaN(lowLimit)) { - adder.setLowLimit(lowLimit); - } - if (!Double.isNaN(highLimit)) { - adder.setHighLimit(highLimit); - } + Optional.ofNullable(lowLimit).ifPresent(adder::setLowLimit); + Optional.ofNullable(highLimit).ifPresent(adder::setHighLimit); context.getReader().readChildNodes(elementName -> { Terminal terminal = TerminalRefSerDe.readTerminal(context, network); switch (elementName) { From 1d7ba1d5028f0d17dd2c83327826ade856d3544c Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 15:29:39 +0100 Subject: [PATCH 24/42] Add readOptionalBooleanAttribute Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 7 ++++++- .../com/powsybl/commons/io/TreeDataReader.java | 4 +++- .../com/powsybl/commons/json/JsonReader.java | 13 +++++++++++-- .../java/com/powsybl/commons/xml/XmlReader.java | 15 ++++++++++++--- .../iidm/serde/AbstractTransformerSerDe.java | 17 ++++++++++++----- .../powsybl/iidm/serde/DanglingLineSerDe.java | 2 +- .../com/powsybl/iidm/serde/GeneratorSerDe.java | 2 +- .../extensions/BranchObservabilitySerDe.java | 2 +- .../extensions/InjectionObservabilitySerDe.java | 5 ++++- 9 files changed, 51 insertions(+), 16 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index d7e8f404855..534db9c5cfc 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -176,7 +176,7 @@ public int readIntAttribute(String name, int defaultValue) { } @Override - public Boolean readBooleanAttribute(String name) { + public boolean readBooleanAttribute(String name) { return readBoolean(); } @@ -185,6 +185,11 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { return readBoolean(); } + @Override + public Boolean readOptionalBooleanAttribute(String name) { + return readBoolean() ? readBoolean() : null; + } + @Override public > T readEnumAttribute(String name, Class clazz) { return readEnum(clazz); diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java index 183c7edef5d..844aec831e9 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java @@ -46,10 +46,12 @@ interface ChildNodeReader { int readIntAttribute(String name, int defaultValue); - Boolean readBooleanAttribute(String name); + boolean readBooleanAttribute(String name); boolean readBooleanAttribute(String name, boolean defaultValue); + Boolean readOptionalBooleanAttribute(String name); + > T readEnumAttribute(String name, Class clazz); > T readEnumAttribute(String name, Class clazz, T defaultValue); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java index 818efeefc9c..ebec870311f 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java @@ -136,8 +136,12 @@ public int readIntAttribute(String name, int defaultValue) { } @Override - public Boolean readBooleanAttribute(String name) { - return Objects.requireNonNull(name).equals(getFieldName()) ? getBooleanValue() : null; + public boolean readBooleanAttribute(String name) { + String fieldName = getFieldName(); + if (!Objects.requireNonNull(name).equals(fieldName)) { + throw new PowsyblException("JSON parsing: expected '" + name + "' but got '" + fieldName + "'"); + } + return getBooleanValue(); } @Override @@ -145,6 +149,11 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { return Objects.requireNonNull(name).equals(getFieldName()) ? getBooleanValue() : defaultValue; } + @Override + public Boolean readOptionalBooleanAttribute(String name) { + return Objects.requireNonNull(name).equals(getFieldName()) ? getBooleanValue() : null; + } + private double getDoubleValue() { try { currentJsonTokenConsumed = true; diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java index 02abfdfafa5..cc181846ccb 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java @@ -82,7 +82,7 @@ public String readStringAttribute(String name) { public int readIntAttribute(String name) { Integer value = XmlUtil.readIntegerAttribute(reader, name); if (value == null) { - throw new PowsyblException("XML parsing: unknown required attribute '" + name + "'"); + throw new PowsyblException("XML parsing: cannot find required attribute '" + name + "'"); } return value; } @@ -98,8 +98,12 @@ public int readIntAttribute(String name, int defaultValue) { } @Override - public Boolean readBooleanAttribute(String name) { - return XmlUtil.readBooleanAttribute(reader, name); + public boolean readBooleanAttribute(String name) { + Boolean value = XmlUtil.readBooleanAttribute(reader, name); + if (value == null) { + throw new PowsyblException("XML parsing: cannot find required attribute '" + name + "'"); + } + return value; } @Override @@ -107,6 +111,11 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { return XmlUtil.readBooleanAttribute(reader, name, defaultValue); } + @Override + public Boolean readOptionalBooleanAttribute(String name) { + return XmlUtil.readBooleanAttribute(reader, name); + } + @Override public String readContent() { try { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 1ab9df8bdc5..68e3332e838 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -74,9 +74,10 @@ private static void writeTapChanger(TapChanger tc, NetworkSerializerContex protected static void writeRatioTapChanger(String name, RatioTapChanger rtc, NetworkSerializerContext context) { context.getWriter().writeStartNode(context.getVersion().getNamespaceURI(context.isValid()), name); - if (rtc.hasLoadTapChangingCapabilities() || rtc.isRegulating()) { - context.getWriter().writeBooleanAttribute(ATTR_REGULATING, rtc.isRegulating()); - } + + Boolean optionalRegulatingValue = rtc.hasLoadTapChangingCapabilities() || rtc.isRegulating() ? rtc.isRegulating() : null; + context.getWriter().writeOptionalBooleanAttribute(ATTR_REGULATING, optionalRegulatingValue); + writeTapChanger(rtc, context); context.getWriter().writeBooleanAttribute("loadTapChangingCapabilities", rtc.hasLoadTapChangingCapabilities()); context.getWriter().writeDoubleAttribute("targetV", rtc.getTargetV()); @@ -95,7 +96,10 @@ protected static void writeRatioTapChanger(String name, RatioTapChanger rtc, Net } protected static void readRatioTapChanger(String elementName, RatioTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { - boolean regulating = context.getReader().readBooleanAttribute(ATTR_REGULATING, false); + Boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING); + if (regulating == null) { + regulating = false; + } int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); @@ -173,7 +177,10 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net } protected static void readPhaseTapChanger(String name, PhaseTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { - boolean regulating = context.getReader().readBooleanAttribute(ATTR_REGULATING, false); + Boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING); + if (regulating == null) { + regulating = false; + } int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index 894b202ff0f..7ab5aceba16 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -147,7 +147,7 @@ public static void readRootElementAttributesInternal(DanglingLineAdder adder, Vo double g = context.getReader().readDoubleAttribute("g"); double b = context.getReader().readDoubleAttribute("b"); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { - Boolean voltageRegulationOn = context.getReader().readBooleanAttribute("generationVoltageRegulationOn"); + Boolean voltageRegulationOn = context.getReader().readOptionalBooleanAttribute("generationVoltageRegulationOn"); Double minP = context.getReader().readOptionalDoubleAttribute(GENERATION_MIN_P); Double maxP = context.getReader().readOptionalDoubleAttribute(GENERATION_MAX_P); Double targetP = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_P); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java index 8530828df7d..ee1880e2986 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/GeneratorSerDe.java @@ -58,7 +58,7 @@ protected Generator readRootElementAttributes(GeneratorAdder adder, VoltageLevel double minP = context.getReader().readDoubleAttribute("minP"); double maxP = context.getReader().readDoubleAttribute("maxP"); double ratedS = context.getReader().readDoubleAttribute("ratedS"); - Boolean voltageRegulatorOn = context.getReader().readBooleanAttribute("voltageRegulatorOn"); + boolean voltageRegulatorOn = context.getReader().readBooleanAttribute("voltageRegulatorOn"); double targetP = context.getReader().readDoubleAttribute("targetP"); double targetV = context.getReader().readDoubleAttribute("targetV"); double targetQ = context.getReader().readDoubleAttribute("targetQ"); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java index d8919dc7179..e7d47671905 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java @@ -73,7 +73,7 @@ public BranchObservability read(T identifiable, DeserializerContext context) context.getReader().readChildNodes(elementName -> { var side = context.getReader().readEnumAttribute(SIDE, TwoSides.class); var standardDeviation = context.getReader().readDoubleAttribute(STANDARD_DEVIATION); - var redundant = context.getReader().readBooleanAttribute(REDUNDANT); + var redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT); context.getReader().readEndNode(); switch (elementName) { case QUALITY_P -> readQualityP(standardDeviation, redundant, side, adder); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java index 3270fe8d536..ee7d69b4a3f 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java @@ -62,7 +62,10 @@ public InjectionObservability read(T identifiable, DeserializerContext contex context.getReader().readChildNodes(elementName -> { var standardDeviation = context.getReader().readDoubleAttribute(STANDARD_DEVIATION); - var redundant = context.getReader().readBooleanAttribute(REDUNDANT, false); + var redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT); + if (redundant == null) { + redundant = false; + } context.getReader().readEndNode(); switch (elementName) { case QUALITY_P -> adder.withStandardDeviationP(standardDeviation).withRedundantP(redundant); From 0f51e41bba2619e62430febf5da938acde9191a9 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 15:34:10 +0100 Subject: [PATCH 25/42] Remove unused imports Signed-off-by: Florian Dupuy --- .../java/com/powsybl/commons/io/AbstractTreeDataWriter.java | 4 ---- .../src/main/java/com/powsybl/commons/io/TreeDataWriter.java | 3 --- .../iidm/serde/extensions/DiscreteMeasurementsSerDe.java | 5 ++--- .../test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java | 1 - 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java index 6a9ea5e08c9..c963f7ea86c 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataWriter.java @@ -7,10 +7,6 @@ */ package com.powsybl.commons.io; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.IntSupplier; - /** * @author Florian Dupuy {@literal } */ diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java index 5c9cea42f96..2bce938bd67 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataWriter.java @@ -8,9 +8,6 @@ import java.util.Collection; import java.util.Map; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.IntSupplier; /** * @author Geoffroy Jamgotchian {@literal } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java index 3ef9ccf1221..3d486eecc6f 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/DiscreteMeasurementsSerDe.java @@ -10,10 +10,10 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.extensions.AbstractExtensionSerDe; import com.powsybl.commons.extensions.ExtensionSerDe; -import com.powsybl.commons.io.TreeDataReader; -import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.commons.io.DeserializerContext; import com.powsybl.commons.io.SerializerContext; +import com.powsybl.commons.io.TreeDataReader; +import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.iidm.network.Identifiable; import com.powsybl.iidm.network.extensions.DiscreteMeasurement; import com.powsybl.iidm.network.extensions.DiscreteMeasurementAdder; @@ -21,7 +21,6 @@ import com.powsybl.iidm.network.extensions.DiscreteMeasurementsAdder; import java.util.Map; -import java.util.Optional; /** * @author Miora Ralambotiana {@literal } diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java index 143fa613e56..86d01fff81a 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java @@ -13,7 +13,6 @@ import com.powsybl.iidm.network.extensions.ConnectablePosition; import com.powsybl.iidm.network.extensions.ConnectablePositionAdder; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.IOException; From 1989c66f973713c87ac7679d338ce805bf1ec5f9 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 16:15:22 +0100 Subject: [PATCH 26/42] Fixes Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 17 +++++++++++++---- .../com/powsybl/iidm/serde/ShuntSerDe.java | 11 +++++++---- .../iidm/serde/VoltageAngleLimitSerDe.java | 2 +- .../extensions/ConnectablePositionSerDe.java | 4 ++-- .../eurostag-tutorial1-lf-extensions.bin | Bin 1724 -> 1714 bytes .../resources/V1_11/eurostag-tutorial1-lf.bin | Bin 1578 -> 1572 bytes 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 534db9c5cfc..dc3ea71abe8 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -142,7 +142,10 @@ public double readDoubleAttribute(String name, double defaultValue) { @Override public Double readOptionalDoubleAttribute(String name) { - return readBoolean() ? readDouble() : null; + if (!readBoolean()) { + return null; + } + return readDouble(); } @Override @@ -167,7 +170,10 @@ public int readIntAttribute(String name) { @Override public Integer readOptionalIntAttribute(String name) { - return readBoolean() ? readInt() : null; + if (!readBoolean()) { + return null; + } + return readInt(); } @Override @@ -187,7 +193,10 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { @Override public Boolean readOptionalBooleanAttribute(String name) { - return readBoolean() ? readBoolean() : null; + if (!readBoolean()) { + return null; + } + return readBoolean(); } @Override @@ -197,7 +206,7 @@ public > T readEnumAttribute(String name, Class clazz) { @Override public > T readEnumAttribute(String name, Class clazz, T defaultValue) { - return clazz.getEnumConstants()[readInt()]; + return readEnum(clazz); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java index 43a96942a18..97ea2bf4aae 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java @@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory; import java.util.List; +import java.util.OptionalInt; import java.util.function.Consumer; import static com.powsybl.iidm.serde.ConnectableSerDeUtil.readNodeOrBus; @@ -64,9 +65,11 @@ protected void writeRootElementAttributes(ShuntCompensator sc, VoltageLevel vl, int currentSectionCount = model instanceof ShuntCompensatorLinearModel ? sc.getSectionCount() : 1; context.getWriter().writeIntAttribute("currentSectionCount", currentSectionCount); }); - if (sc.findSectionCount().isPresent()) { - IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> context.getWriter().writeIntAttribute("sectionCount", sc.getSectionCount())); - } + + IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { + OptionalInt sectionCount = sc.findSectionCount(); + context.getWriter().writeOptionalIntAttribute("sectionCount", sectionCount.isPresent() ? sectionCount.getAsInt() : null); + }); IidmSerDeUtil.writeBooleanAttributeFromMinimumVersion(ROOT_ELEMENT_NAME, "voltageRegulatorOn", sc.isVoltageRegulatorOn(), false, IidmSerDeUtil.ErrorMessage.NOT_DEFAULT_NOT_SUPPORTED, IidmVersion.V_1_2, context); IidmSerDeUtil.writeDoubleAttributeFromMinimumVersion(ROOT_ELEMENT_NAME, "targetV", sc.getTargetV(), IidmSerDeUtil.ErrorMessage.NOT_DEFAULT_NOT_SUPPORTED, IidmVersion.V_1_2, context); @@ -143,7 +146,7 @@ protected void readRootElementAttributes(ShuntCompensatorAdder adder, VoltageLev .add(); }); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { - Integer sectionCount = context.getReader().readIntAttribute("sectionCount"); + Integer sectionCount = context.getReader().readOptionalIntAttribute("sectionCount"); if (sectionCount != null) { adder.setSectionCount(sectionCount); } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java index 18ff23492dc..7134ed35e21 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java @@ -39,7 +39,7 @@ public static void write(VoltageAngleLimit voltageAngleLimit, NetworkSerializerC context.getWriter().writeStringAttribute(ID, context.getAnonymizer().anonymizeString(voltageAngleLimit.getId())); OptionalDouble lowLimit = voltageAngleLimit.getLowLimit(); - OptionalDouble highLimit = voltageAngleLimit.getLowLimit(); + OptionalDouble highLimit = voltageAngleLimit.getHighLimit(); context.getWriter().writeOptionalDoubleAttribute(LOW_LIMIT, lowLimit.isPresent() ? lowLimit.getAsDouble() : null); context.getWriter().writeOptionalDoubleAttribute(HIGH_LIMIT, highLimit.isPresent() ? highLimit.getAsDouble() : null); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java index d31223ed24a..3652c904ed2 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java @@ -66,13 +66,13 @@ private void writePosition(String connectableId, ConnectablePosition.Feeder feed context.getWriter().writeStringAttribute("name", feeder.getName().orElse(connectableId)); break; case V_1_1: - feeder.getName().ifPresent(name -> context.getWriter().writeStringAttribute("name", name)); + context.getWriter().writeStringAttribute("name", feeder.getName().orElse(null)); break; default: throw new PowsyblException("Unsupported version (" + extVersionStr + ") for " + ConnectablePosition.NAME); } context.getWriter().writeOptionalIntAttribute("order", feeder.getOrder().orElse(null)); - context.getWriter().writeStringAttribute("direction", feeder.getDirection().name()); + context.getWriter().writeEnumAttribute("direction", feeder.getDirection()); context.getWriter().writeEndNode(); } diff --git a/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin b/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin index 9548068665454930a5c38ebe6964d106db4db4bc..2068b2bb396aa27888f5aa5d7a331597be33957b 100644 GIT binary patch delta 41 rcmdnPyNP$h3KlL#1|R?tjFY#rC@?ZkHe^-Z{EuZKBQr>78k-sbzPSkQ delta 78 zcmdnQyN7qf3Kl~KAYior0HP3p(INQ&gvZUm<>wJ*6z}Kb@94t791`w7`9F*5<{vB* S8QIyK{6j+geJA&@sQ~~(s}Rrt diff --git a/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf.bin b/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf.bin index 9b7cad27809ea7d6747f7f540cc911798010783b..ab0da6293edc65b71d2548db1002f33d59a802fe 100644 GIT binary patch delta 29 hcmZ3*vxH}ZKMNNl0}y}+#>p`(3XF`K8(3B`0svDk1#SQU delta 43 ucmZ3&vx;YfKMOAd5HQ+*08tDKlOtIaIG97i{ef(r$&D Date: Wed, 10 Jan 2024 16:41:20 +0100 Subject: [PATCH 27/42] Use optionals when reading optional values Signed-off-by: Florian Dupuy --- .../extensions/CgmesTapChangersSerDe.java | 8 +++--- .../com/powsybl/commons/binary/BinReader.java | 18 ++++++------- .../powsybl/commons/io/TreeDataReader.java | 9 +++---- .../com/powsybl/commons/json/JsonReader.java | 12 ++++----- .../com/powsybl/commons/xml/XmlReader.java | 10 +++---- .../java/com/powsybl/commons/xml/XmlUtil.java | 11 ++++++-- .../iidm/serde/AbstractTransformerSerDe.java | 23 +++++----------- .../iidm/serde/ConnectableSerDeUtil.java | 8 +++--- .../powsybl/iidm/serde/DanglingLineSerDe.java | 27 ++++++++++--------- .../com/powsybl/iidm/serde/ShuntSerDe.java | 6 ++--- .../com/powsybl/iidm/serde/TieLineSerDe.java | 17 ++++++------ .../iidm/serde/VoltageAngleLimitSerDe.java | 9 +++---- .../extensions/BranchObservabilitySerDe.java | 2 +- .../extensions/ConnectablePositionSerDe.java | 5 ++-- .../InjectionObservabilitySerDe.java | 5 +--- 15 files changed, 80 insertions(+), 90 deletions(-) diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java index 8f1b5f97060..30776711c68 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java @@ -10,16 +10,15 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.extensions.AbstractExtensionSerDe; import com.powsybl.commons.extensions.ExtensionSerDe; -import com.powsybl.commons.io.TreeDataReader; -import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.commons.io.DeserializerContext; import com.powsybl.commons.io.SerializerContext; +import com.powsybl.commons.io.TreeDataReader; +import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.iidm.network.Connectable; import com.powsybl.iidm.serde.NetworkDeserializerContext; import com.powsybl.iidm.serde.NetworkSerializerContext; import java.util.Map; -import java.util.Optional; /** * @author Miora Vedelago {@literal } @@ -74,8 +73,7 @@ public CgmesTapChangers read(C extendable, DeserializerContext context) { .setType(reader.readStringAttribute("type")) .setHiddenStatus(reader.readBooleanAttribute("hidden", false)) .setControlId(reader.readStringAttribute("controlId")); - Optional.ofNullable(reader.readOptionalIntAttribute("step")) - .ifPresent(adder::setStep); + reader.readOptionalIntAttribute("step").ifPresent(adder::setStep); context.getReader().readEndNode(); adder.add(); } else { diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index dc3ea71abe8..81a777a7b49 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -141,11 +141,11 @@ public double readDoubleAttribute(String name, double defaultValue) { } @Override - public Double readOptionalDoubleAttribute(String name) { + public OptionalDouble readOptionalDoubleAttribute(String name) { if (!readBoolean()) { - return null; + return OptionalDouble.empty(); } - return readDouble(); + return OptionalDouble.of(readDouble()); } @Override @@ -169,11 +169,11 @@ public int readIntAttribute(String name) { } @Override - public Integer readOptionalIntAttribute(String name) { + public OptionalInt readOptionalIntAttribute(String name) { if (!readBoolean()) { - return null; + return OptionalInt.empty(); } - return readInt(); + return OptionalInt.of(readInt()); } @Override @@ -192,11 +192,11 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { } @Override - public Boolean readOptionalBooleanAttribute(String name) { + public Optional readOptionalBooleanAttribute(String name) { if (!readBoolean()) { - return null; + return Optional.empty(); } - return readBoolean(); + return Optional.of(readBoolean()); } @Override diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java index 844aec831e9..46d3fb8afab 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java @@ -6,8 +6,7 @@ */ package com.powsybl.commons.io; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author Geoffroy Jamgotchian {@literal } @@ -32,7 +31,7 @@ interface ChildNodeReader { double readDoubleAttribute(String name, double defaultValue); - Double readOptionalDoubleAttribute(String name); + OptionalDouble readOptionalDoubleAttribute(String name); float readFloatAttribute(String name); @@ -42,7 +41,7 @@ interface ChildNodeReader { int readIntAttribute(String name); - Integer readOptionalIntAttribute(String name); + OptionalInt readOptionalIntAttribute(String name); int readIntAttribute(String name, int defaultValue); @@ -50,7 +49,7 @@ interface ChildNodeReader { boolean readBooleanAttribute(String name, boolean defaultValue); - Boolean readOptionalBooleanAttribute(String name); + Optional readOptionalBooleanAttribute(String name); > T readEnumAttribute(String name, Class clazz); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java index ebec870311f..b4a6b771ad5 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java @@ -84,8 +84,8 @@ public double readDoubleAttribute(String name, double defaultValue) { } @Override - public Double readOptionalDoubleAttribute(String name) { - return Objects.requireNonNull(name).equals(getFieldName()) ? getDoubleValue() : null; + public OptionalDouble readOptionalDoubleAttribute(String name) { + return Objects.requireNonNull(name).equals(getFieldName()) ? OptionalDouble.of(getDoubleValue()) : OptionalDouble.empty(); } @Override @@ -126,8 +126,8 @@ public int readIntAttribute(String name) { } @Override - public Integer readOptionalIntAttribute(String name) { - return Objects.requireNonNull(name).equals(getFieldName()) ? getIntValue() : null; + public OptionalInt readOptionalIntAttribute(String name) { + return Objects.requireNonNull(name).equals(getFieldName()) ? OptionalInt.of(getIntValue()) : OptionalInt.empty(); } @Override @@ -150,8 +150,8 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { } @Override - public Boolean readOptionalBooleanAttribute(String name) { - return Objects.requireNonNull(name).equals(getFieldName()) ? getBooleanValue() : null; + public Optional readOptionalBooleanAttribute(String name) { + return Objects.requireNonNull(name).equals(getFieldName()) ? Optional.of(getBooleanValue()) : Optional.empty(); } private double getDoubleValue() { diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java index cc181846ccb..91183725e52 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java @@ -64,7 +64,7 @@ public double readDoubleAttribute(String name, double defaultValue) { } @Override - public Double readOptionalDoubleAttribute(String name) { + public OptionalDouble readOptionalDoubleAttribute(String name) { return XmlUtil.readOptionalDoubleAttribute(reader, name); } @@ -88,8 +88,8 @@ public int readIntAttribute(String name) { } @Override - public Integer readOptionalIntAttribute(String name) { - return XmlUtil.readIntegerAttribute(reader, name); + public OptionalInt readOptionalIntAttribute(String name) { + return XmlUtil.readOptionalIntegerAttribute(reader, name); } @Override @@ -112,8 +112,8 @@ public boolean readBooleanAttribute(String name, boolean defaultValue) { } @Override - public Boolean readOptionalBooleanAttribute(String name) { - return XmlUtil.readBooleanAttribute(reader, name); + public Optional readOptionalBooleanAttribute(String name) { + return Optional.ofNullable(XmlUtil.readBooleanAttribute(reader, name)); } @Override diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java b/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java index e41064cfbc2..dfb260c4273 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlUtil.java @@ -19,6 +19,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Objects; +import java.util.OptionalDouble; +import java.util.OptionalInt; import java.util.function.Supplier; /** @@ -112,6 +114,11 @@ public static Integer readIntegerAttribute(XMLStreamReader reader, String name) return attributeValue != null ? Integer.valueOf(attributeValue) : null; } + public static OptionalInt readOptionalIntegerAttribute(XMLStreamReader reader, String name) { + String attributeValue = reader.getAttributeValue(null, name); + return attributeValue != null ? OptionalInt.of(Integer.parseInt(attributeValue)) : OptionalInt.empty(); + } + public static int readIntAttribute(XMLStreamReader reader, String name, int defaultValue) { String attributeValue = reader.getAttributeValue(null, name); return attributeValue != null ? Integer.parseInt(attributeValue) : defaultValue; @@ -132,9 +139,9 @@ public static double readDoubleAttribute(XMLStreamReader reader, String name, do return attributeValue != null ? Double.parseDouble(attributeValue) : defaultValue; } - public static Double readOptionalDoubleAttribute(XMLStreamReader reader, String name) { + public static OptionalDouble readOptionalDoubleAttribute(XMLStreamReader reader, String name) { String attributeValue = reader.getAttributeValue(null, name); - return attributeValue != null ? Double.parseDouble(attributeValue) : null; + return attributeValue != null ? OptionalDouble.of(Double.parseDouble(attributeValue)) : OptionalDouble.empty(); } public static float readFloatAttribute(XMLStreamReader reader, String name, float defaultValue) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 68e3332e838..fe123077cbc 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -12,6 +12,7 @@ import com.powsybl.iidm.network.PhaseTapChanger.RegulationMode; import com.powsybl.iidm.serde.util.IidmSerDeUtil; +import java.util.OptionalInt; import java.util.function.DoubleConsumer; /** @@ -96,12 +97,9 @@ protected static void writeRatioTapChanger(String name, RatioTapChanger rtc, Net } protected static void readRatioTapChanger(String elementName, RatioTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { - Boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING); - if (regulating == null) { - regulating = false; - } + boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING).orElse(false); int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); - Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); + OptionalInt tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); boolean loadTapChangingCapabilities = context.getReader().readBooleanAttribute("loadTapChangingCapabilities"); double targetV = context.getReader().readDoubleAttribute("targetV"); @@ -111,9 +109,7 @@ protected static void readRatioTapChanger(String elementName, RatioTapChangerAdd .setLoadTapChangingCapabilities(loadTapChangingCapabilities) .setTargetV(targetV) .setRegulating(regulating); - if (tapPosition != null) { - adder.setTapPosition(tapPosition); - } + tapPosition.ifPresent(adder::setTapPosition); boolean[] hasTerminalRef = new boolean[1]; context.getReader().readChildNodes(subElementName -> { @@ -177,12 +173,9 @@ protected static void writePhaseTapChanger(String name, PhaseTapChanger ptc, Net } protected static void readPhaseTapChanger(String name, PhaseTapChangerAdder adder, Terminal terminal, NetworkDeserializerContext context) { - Boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING); - if (regulating == null) { - regulating = false; - } + boolean regulating = context.getReader().readOptionalBooleanAttribute(ATTR_REGULATING).orElse(false); int lowTapPosition = context.getReader().readIntAttribute(ATTR_LOW_TAP_POSITION); - Integer tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); + OptionalInt tapPosition = context.getReader().readOptionalIntAttribute(ATTR_TAP_POSITION); double targetDeadband = readTargetDeadband(context, regulating); RegulationMode regulationMode = context.getReader().readEnumAttribute("regulationMode", RegulationMode.class); double regulationValue = context.getReader().readDoubleAttribute("regulationValue"); @@ -192,9 +185,7 @@ protected static void readPhaseTapChanger(String name, PhaseTapChangerAdder adde .setRegulationMode(regulationMode) .setRegulationValue(regulationValue) .setRegulating(regulating); - if (tapPosition != null) { - adder.setTapPosition(tapPosition); - } + tapPosition.ifPresent(adder::setTapPosition); boolean[] hasTerminalRef = new boolean[1]; context.getReader().readChildNodes(elementName -> { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index 3177d074584..64e0fd24f3e 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -184,10 +184,10 @@ public static void readPQ(Integer index, Terminal t, TreeDataReader reader) { } public static void readOptionalPQ(Integer index, Terminal t, TreeDataReader reader) { - Double p = reader.readOptionalDoubleAttribute("p" + indexToString(index)); - Double q = reader.readOptionalDoubleAttribute("q" + indexToString(index)); - Optional.ofNullable(p).ifPresent(t::setP); - Optional.ofNullable(q).ifPresent(t::setQ); + reader.readOptionalDoubleAttribute("p" + indexToString(index)) + .ifPresent(t::setP); + reader.readOptionalDoubleAttribute("q" + indexToString(index)) + .ifPresent(t::setQ); } public static void readActivePowerLimits(ActivePowerLimitsAdder activePowerLimitsAdder, TreeDataReader reader) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index 7ab5aceba16..f7de82a03b2 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -11,6 +11,7 @@ import com.powsybl.iidm.serde.util.IidmSerDeUtil; import java.util.Optional; +import java.util.OptionalDouble; import java.util.function.Function; import java.util.function.Supplier; @@ -147,20 +148,20 @@ public static void readRootElementAttributesInternal(DanglingLineAdder adder, Vo double g = context.getReader().readDoubleAttribute("g"); double b = context.getReader().readDoubleAttribute("b"); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { - Boolean voltageRegulationOn = context.getReader().readOptionalBooleanAttribute("generationVoltageRegulationOn"); - Double minP = context.getReader().readOptionalDoubleAttribute(GENERATION_MIN_P); - Double maxP = context.getReader().readOptionalDoubleAttribute(GENERATION_MAX_P); - Double targetP = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_P); - Double targetV = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_V); - Double targetQ = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_Q); - if (voltageRegulationOn != null) { + Optional voltageRegulationOn = context.getReader().readOptionalBooleanAttribute("generationVoltageRegulationOn"); + OptionalDouble minP = context.getReader().readOptionalDoubleAttribute(GENERATION_MIN_P); + OptionalDouble maxP = context.getReader().readOptionalDoubleAttribute(GENERATION_MAX_P); + OptionalDouble targetP = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_P); + OptionalDouble targetV = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_V); + OptionalDouble targetQ = context.getReader().readOptionalDoubleAttribute(GENERATION_TARGET_Q); + if (voltageRegulationOn.isPresent()) { DanglingLineAdder.GenerationAdder generationAdder = adder.newGeneration() - .setVoltageRegulationOn(voltageRegulationOn); - Optional.ofNullable(minP).ifPresent(generationAdder::setMinP); - Optional.ofNullable(maxP).ifPresent(generationAdder::setMaxP); - Optional.ofNullable(targetP).ifPresent(generationAdder::setTargetP); - Optional.ofNullable(targetV).ifPresent(generationAdder::setTargetV); - Optional.ofNullable(targetQ).ifPresent(generationAdder::setTargetQ); + .setVoltageRegulationOn(voltageRegulationOn.get()); + minP.ifPresent(generationAdder::setMinP); + maxP.ifPresent(generationAdder::setMaxP); + targetP.ifPresent(generationAdder::setTargetP); + targetV.ifPresent(generationAdder::setTargetV); + targetQ.ifPresent(generationAdder::setTargetQ); generationAdder.add(); } }); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java index 97ea2bf4aae..d7eb37e5c18 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java @@ -146,10 +146,8 @@ protected void readRootElementAttributes(ShuntCompensatorAdder adder, VoltageLev .add(); }); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_3, context, () -> { - Integer sectionCount = context.getReader().readOptionalIntAttribute("sectionCount"); - if (sectionCount != null) { - adder.setSectionCount(sectionCount); - } + OptionalInt sectionCount = context.getReader().readOptionalIntAttribute("sectionCount"); + sectionCount.ifPresent(adder::setSectionCount); }); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_2, context, () -> { boolean voltageRegulatorOn = context.getReader().readBooleanAttribute("voltageRegulatorOn"); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java index a9a738d980c..79b23004d5d 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import java.util.Optional; +import java.util.OptionalDouble; import static com.powsybl.iidm.serde.ConnectableSerDeUtil.*; @@ -158,16 +159,16 @@ protected TieLine readRootElementAttributes(TieLineAdder adder, Network network, String pairingKey = context.getReader().readStringAttribute("ucteXnodeCode"); DanglingLineAdder adderDl1 = readVlAndNodeOrBus(context, network, 1); DanglingLineAdder adderDl2 = readVlAndNodeOrBus(context, network, 2); - Double p1 = context.getReader().readOptionalDoubleAttribute("p1"); - Double q1 = context.getReader().readOptionalDoubleAttribute("q1"); - Double p2 = context.getReader().readOptionalDoubleAttribute("p2"); - Double q2 = context.getReader().readOptionalDoubleAttribute("q2"); + OptionalDouble p1 = context.getReader().readOptionalDoubleAttribute("p1"); + OptionalDouble q1 = context.getReader().readOptionalDoubleAttribute("q1"); + OptionalDouble p2 = context.getReader().readOptionalDoubleAttribute("p2"); + OptionalDouble q2 = context.getReader().readOptionalDoubleAttribute("q2"); DanglingLine dl1 = readDanglingLine(adderDl1, pairingKey, context, 1); DanglingLine dl2 = readDanglingLine(adderDl2, pairingKey, context, 2); - Optional.ofNullable(p1).ifPresent(dl1.getTerminal()::setP); - Optional.ofNullable(q1).ifPresent(dl1.getTerminal()::setQ); - Optional.ofNullable(p2).ifPresent(dl2.getTerminal()::setP); - Optional.ofNullable(q2).ifPresent(dl2.getTerminal()::setQ); + p1.ifPresent(dl1.getTerminal()::setP); + q1.ifPresent(dl1.getTerminal()::setQ); + p2.ifPresent(dl2.getTerminal()::setP); + q2.ifPresent(dl2.getTerminal()::setQ); adder.setDanglingLine1(dl1.getId()).setDanglingLine2(dl2.getId()); }); IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_10, context, () -> { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java index 7134ed35e21..8f4751fe76d 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageAngleLimitSerDe.java @@ -15,7 +15,6 @@ import com.powsybl.iidm.network.VoltageAngleLimitAdder; import com.powsybl.iidm.serde.util.IidmSerDeUtil; -import java.util.Optional; import java.util.OptionalDouble; /** @@ -53,13 +52,13 @@ public static void read(Network network, NetworkDeserializerContext context) { IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_11, context, () -> { String id = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(ID)); - Double lowLimit = context.getReader().readOptionalDoubleAttribute(LOW_LIMIT); - Double highLimit = context.getReader().readOptionalDoubleAttribute(HIGH_LIMIT); + OptionalDouble lowLimit = context.getReader().readOptionalDoubleAttribute(LOW_LIMIT); + OptionalDouble highLimit = context.getReader().readOptionalDoubleAttribute(HIGH_LIMIT); VoltageAngleLimitAdder adder = network.newVoltageAngleLimit(); adder.setId(id); - Optional.ofNullable(lowLimit).ifPresent(adder::setLowLimit); - Optional.ofNullable(highLimit).ifPresent(adder::setHighLimit); + lowLimit.ifPresent(adder::setLowLimit); + highLimit.ifPresent(adder::setHighLimit); context.getReader().readChildNodes(elementName -> { Terminal terminal = TerminalRefSerDe.readTerminal(context, network); switch (elementName) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java index e7d47671905..32313d57722 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/BranchObservabilitySerDe.java @@ -73,7 +73,7 @@ public BranchObservability read(T identifiable, DeserializerContext context) context.getReader().readChildNodes(elementName -> { var side = context.getReader().readEnumAttribute(SIDE, TwoSides.class); var standardDeviation = context.getReader().readDoubleAttribute(STANDARD_DEVIATION); - var redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT); + var redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT).orElse(null); context.getReader().readEndNode(); switch (elementName) { case QUALITY_P -> readQualityP(standardDeviation, redundant, side, adder); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java index 3652c904ed2..8cad5d748de 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ConnectablePositionSerDe.java @@ -22,7 +22,6 @@ import java.io.InputStream; import java.util.List; -import java.util.Optional; /** * @author Geoffroy Jamgotchian {@literal } @@ -96,8 +95,8 @@ public void write(ConnectablePosition connectablePosition, SerializerContext private void readPosition(DeserializerContext context, ConnectablePositionAdder.FeederAdder adder) { String name = context.getReader().readStringAttribute("name"); - Optional.ofNullable(context.getReader().readOptionalIntAttribute("order")). - ifPresent(adder::withOrder); + context.getReader().readOptionalIntAttribute("order") + .ifPresent(adder::withOrder); ConnectablePosition.Direction direction = context.getReader().readEnumAttribute("direction", ConnectablePosition.Direction.class); context.getReader().readEndNode(); if (name != null) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java index ee7d69b4a3f..f5db6b2df76 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/InjectionObservabilitySerDe.java @@ -62,10 +62,7 @@ public InjectionObservability read(T identifiable, DeserializerContext contex context.getReader().readChildNodes(elementName -> { var standardDeviation = context.getReader().readDoubleAttribute(STANDARD_DEVIATION); - var redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT); - if (redundant == null) { - redundant = false; - } + boolean redundant = context.getReader().readOptionalBooleanAttribute(REDUNDANT).orElse(false); context.getReader().readEndNode(); switch (elementName) { case QUALITY_P -> adder.withStandardDeviationP(standardDeviation).withRedundantP(redundant); From 9d596330e7ff7355cd81a14bd72356dd8bc9aecb Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 10 Jan 2024 17:34:52 +0100 Subject: [PATCH 28/42] Read with UTF8 Signed-off-by: Florian Dupuy --- .../src/main/java/com/powsybl/commons/binary/BinReader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 81a777a7b49..5f396b0e4ab 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Supplier; @@ -51,7 +52,7 @@ private String readString() { if (nbBytesRead != stringNbBytes) { throw new PowsyblException("Cannot read the full string, bytes missing: " + (stringNbBytes - nbBytesRead)); } - return new String(stringBytes); + return new String(stringBytes, StandardCharsets.UTF_8); } catch (IOException e) { throw new UncheckedIOException(e); } From d14b3eab1cabff63692207d92aa21d2444a9f5d5 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 11 Jan 2024 11:51:44 +0100 Subject: [PATCH 29/42] Buffered streams Signed-off-by: Florian Dupuy --- .../main/java/com/powsybl/commons/binary/BinReader.java | 7 ++----- .../main/java/com/powsybl/commons/binary/BinWriter.java | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 5f396b0e4ab..e744e00e3a6 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -10,10 +10,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.io.TreeDataReader; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; +import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Supplier; @@ -30,7 +27,7 @@ public class BinReader implements TreeDataReader { private final Map dictionary = new HashMap<>(); public BinReader(InputStream is) throws IOException { - this.dis = new DataInputStream(Objects.requireNonNull(is)); + this.dis = new DataInputStream(new BufferedInputStream(Objects.requireNonNull(is))); readDictionary(); } diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 49284e2e336..143762da10f 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -34,7 +34,7 @@ public class BinWriter implements TreeDataWriter { public BinWriter(OutputStream outputStream, String rootVersion) { this.rootVersion = Objects.requireNonNull(rootVersion); - this.dos = new DataOutputStream(Objects.requireNonNull(outputStream)); + this.dos = new DataOutputStream(new BufferedOutputStream(Objects.requireNonNull(outputStream))); this.buffer = new ByteArrayOutputStream(); this.tmpDos = new DataOutputStream(buffer); } From 53f2628ffee64d617fafc45da6048aba109fc23d Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 13:38:32 +0100 Subject: [PATCH 30/42] Fix Signed-off-by: Florian Dupuy --- commons/src/main/java/com/powsybl/commons/binary/BinWriter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 143762da10f..4a59961618a 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -239,6 +239,7 @@ public void close() { writeString(extensionVersion, dos); }); dos.write(buffer.toByteArray()); + dos.close(); } catch (IOException e) { throw new UncheckedIOException(e); } From 45551dcfb2ff275df105473e5ac5d900a585851d Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 15:03:12 +0100 Subject: [PATCH 31/42] Use inputStream::readNBytes instead of inputStream::read Signed-off-by: Florian Dupuy --- .../main/java/com/powsybl/commons/binary/BinReader.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index e744e00e3a6..5c037eadbf2 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -44,10 +44,9 @@ private String readString() { if (stringNbBytes == 0) { return null; } - byte[] stringBytes = new byte[stringNbBytes]; - int nbBytesRead = dis.read(stringBytes, 0, stringNbBytes); - if (nbBytesRead != stringNbBytes) { - throw new PowsyblException("Cannot read the full string, bytes missing: " + (stringNbBytes - nbBytesRead)); + byte[] stringBytes = dis.readNBytes(stringNbBytes); + if (stringBytes.length != stringNbBytes) { + throw new PowsyblException("Cannot read the full string, bytes missing: " + (stringNbBytes - stringBytes.length)); } return new String(stringBytes, StandardCharsets.UTF_8); } catch (IOException e) { From b8b7838baf30c327fc614c388ac29c8c4211c6ed Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 16:00:46 +0100 Subject: [PATCH 32/42] Add exporter/importer Signed-off-by: Florian Dupuy --- .../powsybl/iidm/serde/BinaryExporter.java | 52 ++++++++++++++ .../powsybl/iidm/serde/BinaryImporter.java | 69 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java create mode 100644 iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java new file mode 100644 index 00000000000..9c4dc22e2af --- /dev/null +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2024, 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.serde; + +import com.google.auto.service.AutoService; +import com.powsybl.commons.config.PlatformConfig; +import com.powsybl.commons.io.TreeDataFormat; +import com.powsybl.iidm.network.Exporter; + +import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; + +/** + * Binary export of an IIDM model. + * + * @author Florian Dupuy {@literal } + */ +@AutoService(Exporter.class) +public class BinaryExporter extends AbstractTreeDataExporter { + + public BinaryExporter() { + this(PlatformConfig.defaultConfig()); + } + + public BinaryExporter(PlatformConfig platformConfig) { + super(platformConfig); + } + + @Override + public String getFormat() { + return "BIIDM"; + } + + @Override + public String getComment() { + return "IIDM binary v" + CURRENT_IIDM_VERSION.toString(".") + " exporter"; + } + + @Override + protected TreeDataFormat getTreeDataFormat() { + return TreeDataFormat.JSON; + } + + @Override + protected String getExtension() { + return "biidm"; + } +} diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java new file mode 100644 index 00000000000..8b413f39ce2 --- /dev/null +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024, 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.serde; + +import com.google.auto.service.AutoService; +import com.powsybl.commons.datasource.ReadOnlyDataSource; +import com.powsybl.commons.io.TreeDataFormat; +import com.powsybl.iidm.network.Importer; + +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; + +/** + * Binary import of an IIDM model. + * + * @author Florian Dupuy {@literal } + */ +@AutoService(Importer.class) +public class BinaryImporter extends AbstractTreeDataImporter { + + private static final String[] EXTENSIONS = {"biidm", "bin", "iidm.bin"}; + + @Override + protected String[] getExtensions() { + return EXTENSIONS; + } + + @Override + public String getFormat() { + return "BIIDM"; + } + + @Override + public String getComment() { + return "IIDM binary v " + CURRENT_IIDM_VERSION.toString(".") + " importer"; + } + + @Override + protected boolean exists(ReadOnlyDataSource dataSource, String ext) throws IOException { + if (ext != null) { + try (DataInputStream dis = new DataInputStream(dataSource.newInputStream(null, ext))) { + int versionNbBytes = dis.readShort(); + if (versionNbBytes > 0 && versionNbBytes < 50) { // large enough for version string + byte[] stringBytes = dis.readNBytes(versionNbBytes); + if (stringBytes.length == versionNbBytes) { + String version = new String(stringBytes, StandardCharsets.UTF_8); + return version.matches("^\\d+_\\d+(_\\d+)?$"); + } + } + } + } + return false; + } + + @Override + protected ImportOptions createImportOptions(Properties parameters) { + return super.createImportOptions(parameters) + .setFormat(TreeDataFormat.BIN); + } +} From 33e1d2a8576d32ce2096df86f9cef3c8e4038cbd Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 16:23:06 +0100 Subject: [PATCH 33/42] Introduce TreeDataHeader Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 43 ++++++++++--------- .../com/powsybl/commons/binary/BinWriter.java | 25 +++++++---- .../commons/io/AbstractTreeDataReader.java | 11 +++++ .../powsybl/commons/io/TreeDataHeader.java | 17 ++++++++ .../powsybl/commons/io/TreeDataReader.java | 9 ++-- .../com/powsybl/commons/json/JsonReader.java | 2 +- .../com/powsybl/commons/xml/XmlReader.java | 2 +- .../com/powsybl/iidm/serde/NetworkSerDe.java | 18 +++----- 8 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 commons/src/main/java/com/powsybl/commons/io/TreeDataHeader.java diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 5c037eadbf2..5ef106940ca 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -8,6 +8,7 @@ package com.powsybl.commons.binary; import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.io.TreeDataHeader; import com.powsybl.commons.io.TreeDataReader; import java.io.*; @@ -26,9 +27,28 @@ public class BinReader implements TreeDataReader { private final DataInputStream dis; private final Map dictionary = new HashMap<>(); - public BinReader(InputStream is) throws IOException { + public BinReader(InputStream is) { this.dis = new DataInputStream(new BufferedInputStream(Objects.requireNonNull(is))); - readDictionary(); + } + + @Override + public TreeDataHeader readHeader() { + try { + TreeDataHeader header = new TreeDataHeader(readString(), readExtensionVersions()); + readDictionary(); + return header; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public Map readExtensionVersions() throws IOException { + int nbVersions = dis.readShort(); + Map versions = new HashMap<>(); + for (int i = 0; i < nbVersions; i++) { + versions.put(readString(), readString()); + } + return versions; } private void readDictionary() throws IOException { @@ -108,25 +128,6 @@ private List readArray(Supplier valueReader) { } } - @Override - public String readRootVersion() { - return readString(); - } - - @Override - public Map readVersions() { - try { - int nbVersions = dis.readShort(); - Map versions = new HashMap<>(); - for (int i = 0; i < nbVersions; i++) { - versions.put(readString(), readString()); - } - return versions; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - @Override public double readDoubleAttribute(String name) { return readDouble(); diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 4a59961618a..8d3d49c51c2 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -230,14 +230,7 @@ public void writeOptionalBooleanAttribute(String name, Boolean value) { public void close() { try { tmpDos.flush(); - writeIndex(nodeNamesIndex.size(), dos); - nodeNamesIndex.forEach((name, index) -> writeString(name, dos)); - writeString(rootVersion, dos); - writeIndex(extensionVersions.size(), dos); - extensionVersions.forEach((extensionName, extensionVersion) -> { - writeString(extensionName, dos); - writeString(extensionVersion, dos); - }); + writeHeader(); dos.write(buffer.toByteArray()); dos.close(); } catch (IOException e) { @@ -245,6 +238,22 @@ public void close() { } } + private void writeHeader() { + // iidm version + writeString(rootVersion, dos); + + // extensions versions + writeIndex(extensionVersions.size(), dos); + extensionVersions.forEach((extensionName, extensionVersion) -> { + writeString(extensionName, dos); + writeString(extensionVersion, dos); + }); + + // dictionary + writeIndex(nodeNamesIndex.size(), dos); + nodeNamesIndex.forEach((name, index) -> writeString(name, dos)); + } + @Override public void setVersions(Map extensionVersions) { this.extensionVersions = Objects.requireNonNull(extensionVersions); diff --git a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataReader.java index 9669e647a41..cafc604580c 100644 --- a/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/AbstractTreeDataReader.java @@ -7,11 +7,22 @@ */ package com.powsybl.commons.io; +import java.util.Map; + /** * @author Florian Dupuy {@literal } */ public abstract class AbstractTreeDataReader implements TreeDataReader { + @Override + public TreeDataHeader readHeader() { + return new TreeDataHeader(readRootVersion(), readExtensionVersions()); + } + + protected abstract String readRootVersion(); + + protected abstract Map readExtensionVersions(); + @Override public double readDoubleAttribute(String name) { return readDoubleAttribute(name, Double.NaN); diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataHeader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataHeader.java new file mode 100644 index 00000000000..3b6e25b3659 --- /dev/null +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataHeader.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2024, 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.commons.io; + +import java.util.Map; + +/** + * @author Florian Dupuy {@literal } + */ +public record TreeDataHeader(String rootVersion, Map extensionVersions) { + +} diff --git a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java index 46d3fb8afab..59e0a58afdf 100644 --- a/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java +++ b/commons/src/main/java/com/powsybl/commons/io/TreeDataReader.java @@ -6,7 +6,10 @@ */ package com.powsybl.commons.io; -import java.util.*; +import java.util.List; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; /** * @author Geoffroy Jamgotchian {@literal } @@ -23,9 +26,7 @@ interface ChildNodeReader { void onStartNode(String nodeName); } - String readRootVersion(); - - Map readVersions(); + TreeDataHeader readHeader(); double readDoubleAttribute(String name); diff --git a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java index b4a6b771ad5..4268fd519a8 100644 --- a/commons/src/main/java/com/powsybl/commons/json/JsonReader.java +++ b/commons/src/main/java/com/powsybl/commons/json/JsonReader.java @@ -50,7 +50,7 @@ public String readRootVersion() { } @Override - public Map readVersions() { + public Map readExtensionVersions() { if (!(EXTENSION_VERSIONS_NAME.equals(getFieldName()))) { return Collections.emptyMap(); } diff --git a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java index 91183725e52..d8df00967d9 100644 --- a/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java +++ b/commons/src/main/java/com/powsybl/commons/xml/XmlReader.java @@ -47,7 +47,7 @@ public String readRootVersion() { } @Override - public Map readVersions() { + public Map readExtensionVersions() { Map versions = new HashMap<>(); for (ExtensionSerDe e : extensionProviders) { String namespaceUri = reader.getNamespaceURI(e.getNamespacePrefix()); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java index 4724706fb4c..3995718fa60 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java @@ -20,6 +20,7 @@ import com.powsybl.commons.extensions.ExtensionProviders; import com.powsybl.commons.extensions.ExtensionSerDe; import com.powsybl.commons.io.TreeDataFormat; +import com.powsybl.commons.io.TreeDataHeader; import com.powsybl.commons.io.TreeDataReader; import com.powsybl.commons.io.TreeDataWriter; import com.powsybl.commons.json.JsonReader; @@ -515,18 +516,10 @@ private static TreeDataReader createTreeDataReader(InputStream is, ImportOptions return switch (config.getFormat()) { case XML -> createXmlReader(is, config); case JSON -> createJsonReader(is, config); - case BIN -> createBinReader(is); + case BIN -> new BinReader(is); }; } - private static TreeDataReader createBinReader(InputStream is) { - try { - return new BinReader(is); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - private static TreeDataReader createJsonReader(InputStream is, ImportOptions config) { try { return new JsonReader(is, NETWORK_ROOT_ELEMENT_NAME, createArrayNameToSingleNameMap(config)); @@ -698,10 +691,9 @@ public static Network read(TreeDataReader reader, ImportOptions config, Anonymiz Objects.requireNonNull(networkFactory); Objects.requireNonNull(reporter); - IidmVersion iidmVersion = IidmVersion.of(reader.readRootVersion(), "."); - Map extensionVersions = reader.readVersions(); - - NetworkDeserializerContext context = new NetworkDeserializerContext(anonymizer, reader, config, iidmVersion, extensionVersions); + TreeDataHeader header = reader.readHeader(); + IidmVersion iidmVersion = IidmVersion.of(header.rootVersion(), "."); + NetworkDeserializerContext context = new NetworkDeserializerContext(anonymizer, reader, config, iidmVersion, header.extensionVersions()); Network network = initNetwork(networkFactory, context, reader, null); network.getReporterContext().pushReporter(reporter); From 80c02d0b332bbca871064f6e7de5fda280cf048e Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 16:28:52 +0100 Subject: [PATCH 34/42] Update & move unit test references from V1_11 to V1_12 Signed-off-by: Florian Dupuy --- .../iidm/serde/EurostagBinaryTest.java | 4 ++-- .../eurostag-tutorial1-lf-extensions.bin | Bin 1714 -> 1716 bytes .../eurostag-tutorial1-lf.bin | Bin 1572 -> 1574 bytes 3 files changed, 2 insertions(+), 2 deletions(-) rename iidm/iidm-serde/src/test/resources/{V1_11 => V1_12}/eurostag-tutorial1-lf-extensions.bin (86%) rename iidm/iidm-serde/src/test/resources/{V1_11 => V1_12}/eurostag-tutorial1-lf.bin (86%) diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java index 86d01fff81a..b023fe1d383 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java @@ -35,7 +35,7 @@ void roundTripTest() throws IOException { getVersionedNetworkPath("eurostag-tutorial1-lf.bin", CURRENT_IIDM_VERSION)); //backward compatibility - roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf.bin", IidmVersion.V_1_11); + roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf.bin", IidmVersion.V_1_12); } @Test @@ -52,6 +52,6 @@ void roundTripTestWithExtension() throws IOException { getVersionedNetworkPath("eurostag-tutorial1-lf-extensions.bin", CURRENT_IIDM_VERSION)); //backward compatibility - roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf-extensions.bin", IidmVersion.V_1_11); + roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf-extensions.bin", IidmVersion.V_1_12); } } diff --git a/iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin similarity index 86% rename from iidm/iidm-serde/src/test/resources/V1_11/eurostag-tutorial1-lf-extensions.bin rename to iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin index 2068b2bb396aa27888f5aa5d7a331597be33957b..cbafb36a731041a126bc2448312c16596c2aa63a 100644 GIT binary patch delta 30 mcmdnQyM>pHfyGeI&}ia4?TL&xH*+y=WM*Pu*u0zNJ0k#y5(zK> delta 25 hcmdnOyNP$A!7Ua;JwwBZY}%VS88fyGeI(1?Ly!pe;sH!?FZFl Date: Mon, 15 Jan 2024 16:31:15 +0100 Subject: [PATCH 35/42] fix Signed-off-by: Florian Dupuy --- .../src/main/java/com/powsybl/iidm/serde/BinaryExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java index 9c4dc22e2af..eeb4e4dbdc3 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryExporter.java @@ -42,7 +42,7 @@ public String getComment() { @Override protected TreeDataFormat getTreeDataFormat() { - return TreeDataFormat.JSON; + return TreeDataFormat.BIN; } @Override From 4cfc263844281bf1f566d73fcc317537690c40b4 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 15 Jan 2024 17:43:37 +0100 Subject: [PATCH 36/42] Fix regex for BinaryImporter Signed-off-by: Florian Dupuy --- .../src/main/java/com/powsybl/iidm/serde/BinaryImporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java index 8b413f39ce2..303dd50fbfe 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java @@ -53,7 +53,7 @@ protected boolean exists(ReadOnlyDataSource dataSource, String ext) throws IOExc byte[] stringBytes = dis.readNBytes(versionNbBytes); if (stringBytes.length == versionNbBytes) { String version = new String(stringBytes, StandardCharsets.UTF_8); - return version.matches("^\\d+_\\d+(_\\d+)?$"); + return version.matches("^\\d+\\.\\d+(\\.\\d+)?$"); } } } From 77d5ca07dfad2d867243ecb13dc0360da9191ede Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 11:42:16 +0100 Subject: [PATCH 37/42] Fix serialization/deserialization bugs Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 4 +++- .../iidm/serde/AbstractTransformerSerDe.java | 6 ++++-- .../iidm/serde/OverloadManagementSystemSerDe.java | 15 ++++++--------- .../java/com/powsybl/iidm/serde/ShuntSerDe.java | 12 +++++++++--- .../java/com/powsybl/iidm/serde/TieLineSerDe.java | 2 +- .../com/powsybl/iidm/serde/VoltageLevelSerDe.java | 2 +- .../serde/extensions/ActivePowerControlSerDe.java | 2 +- .../serde/extensions/LoadAsymmetricalSerDe.java | 2 +- .../TwoWindingsTransformerFortescueSerDe.java | 4 ++-- 9 files changed, 28 insertions(+), 21 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index 5ef106940ca..a9075facaaa 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -209,7 +209,9 @@ public > T readEnumAttribute(String name, Class clazz, T de @Override public String readContent() { - return readString(); + String content = readString(); + readEndNode(); + return content; } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java index 908271af402..8f927931d58 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTransformerSerDe.java @@ -244,8 +244,10 @@ private static void readSteps(NetworkDeserializerContext context, TapChangerStep * @param consumer the method will used apparent power value read */ protected static void readRatedS(String name, NetworkDeserializerContext context, DoubleConsumer consumer) { - double ratedS = context.getReader().readDoubleAttribute(name); - consumer.accept(ratedS); + IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_2, context, () -> { + double ratedS = context.getReader().readDoubleAttribute(name); + consumer.accept(ratedS); + }); } /** diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDe.java index 5904a83a955..c0daff70056 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDe.java @@ -37,7 +37,7 @@ protected String getRootElementName() { protected void writeRootElementAttributes(OverloadManagementSystem oms, Substation substation, NetworkSerializerContext context) { context.getWriter().writeBooleanAttribute("enabled", oms.isEnabled()); context.getWriter().writeStringAttribute("monitoredElementId", context.getAnonymizer().anonymizeString(oms.getMonitoredElementId())); - context.getWriter().writeStringAttribute("side", oms.getMonitoredSide().name()); + context.getWriter().writeEnumAttribute("side", oms.getMonitoredSide()); } @Override @@ -53,7 +53,7 @@ private void writeTripping(OverloadManagementSystem.Tripping tripping, NetworkSe writeTrippingCommonAttributes(tripping, context); context.getWriter().writeStringAttribute("branchId", context.getAnonymizer().anonymizeString(branchTripping.getBranchToOperateId())); - context.getWriter().writeStringAttribute("side", branchTripping.getSideToOperate().name()); + context.getWriter().writeEnumAttribute("side", branchTripping.getSideToOperate()); context.getWriter().writeEndNode(); } case SWITCH_TRIPPING -> { @@ -71,7 +71,7 @@ private void writeTripping(OverloadManagementSystem.Tripping tripping, NetworkSe writeTrippingCommonAttributes(tripping, context); context.getWriter().writeStringAttribute("threeWindingsTransformerId", context.getAnonymizer().anonymizeString(twtTripping.getThreeWindingsTransformerToOperateId())); - context.getWriter().writeStringAttribute("side", twtTripping.getSideToOperate().name()); + context.getWriter().writeEnumAttribute("side", twtTripping.getSideToOperate()); context.getWriter().writeEndNode(); } default -> throw new PowsyblException("Unexpected tripping type: " + tripping.getType()); @@ -100,8 +100,7 @@ protected void readRootElementAttributes(OverloadManagementSystemAdder adder, NetworkDeserializerContext context) { boolean enabled = context.getReader().readBooleanAttribute("enabled", true); String monitoredElementId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("monitoredElementId")); - String side = context.getReader().readStringAttribute("side"); - ThreeSides monitoredSide = side == null ? ThreeSides.ONE : ThreeSides.valueOf(side); + ThreeSides monitoredSide = context.getReader().readEnumAttribute("side", ThreeSides.class, ThreeSides.ONE); if (adder != null) { adder.setEnabled(enabled) .setMonitoredElementId(monitoredElementId) @@ -131,8 +130,7 @@ protected void readSubElements(String id, OverloadManagementSystemAdder adder, private static void readBranchTripping(OverloadManagementSystemAdder adder, NetworkDeserializerContext context, String key, String name, double currentLimit, boolean openAction) { String branchId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("branchId")); - String side = context.getReader().readStringAttribute("side"); - TwoSides sideToOperate = side == null ? TwoSides.ONE : TwoSides.valueOf(side); + TwoSides sideToOperate = context.getReader().readEnumAttribute("side", TwoSides.class, TwoSides.ONE); context.getReader().readEndNode(); if (adder != null) { adder.newBranchTripping() @@ -165,8 +163,7 @@ private static void readThreeWindingsTransformerTripping(OverloadManagementSyste String key, String name, double currentLimit, boolean openAction) { String twtId = context.getAnonymizer().deanonymizeString( context.getReader().readStringAttribute("threeWindingsTransformerId")); - String side = context.getReader().readStringAttribute("side"); - ThreeSides sideToOperate = side == null ? ThreeSides.ONE : ThreeSides.valueOf(side); + ThreeSides sideToOperate = context.getReader().readEnumAttribute("side", ThreeSides.class, ThreeSides.ONE); context.getReader().readEndNode(); if (adder != null) { adder.newThreeWindingsTransformerTripping() diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java index d7eb37e5c18..e386f4a78a8 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ShuntSerDe.java @@ -158,9 +158,15 @@ protected void readRootElementAttributes(ShuntCompensatorAdder adder, VoltageLev .setVoltageRegulatorOn(voltageRegulatorOn); }); readNodeOrBus(adder, context, parent.getTopologyKind()); - double p = context.getReader().readDoubleAttribute("p"); - double q = context.getReader().readDoubleAttribute("q"); - toApply.add(sc -> sc.getTerminal().setP(p).setQ(q)); + IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_8, context, () -> { + double q = context.getReader().readDoubleAttribute("q"); + toApply.add(sc -> sc.getTerminal().setQ(q)); + }); + IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_9, context, () -> { + double p = context.getReader().readDoubleAttribute("p"); + double q = context.getReader().readDoubleAttribute("q"); + toApply.add(sc -> sc.getTerminal().setP(p).setQ(q)); + }); } @Override diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java index 79b23004d5d..ec4e51daead 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TieLineSerDe.java @@ -36,7 +36,7 @@ protected String getRootElementName() { private static void writeDanglingLine(DanglingLine danglingLine, NetworkSerializerContext context, int side) { Boundary boundary = danglingLine.getBoundary(); context.getWriter().writeStringAttribute("id_" + side, context.getAnonymizer().anonymizeString(danglingLine.getId())); - danglingLine.getOptionalName().ifPresent(name -> context.getWriter().writeStringAttribute("name_" + side, context.getAnonymizer().anonymizeString(name))); + context.getWriter().writeStringAttribute("name_" + side, danglingLine.getOptionalName().map(n -> context.getAnonymizer().anonymizeString(n)).orElse(null)); context.getWriter().writeDoubleAttribute("r_" + side, danglingLine.getR()); context.getWriter().writeDoubleAttribute("x_" + side, danglingLine.getX()); // TODO change serialization diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java index 8008bd0e8be..a755993a3c9 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/VoltageLevelSerDe.java @@ -338,7 +338,7 @@ protected void readSubElements(VoltageLevel vl, NetworkDeserializerContext conte private void readNodeBreakerTopology(VoltageLevel vl, NetworkDeserializerContext context) { IidmSerDeUtil.runUntilMaximumVersion(IidmVersion.V_1_1, context, () -> { - context.getReader().readStringAttribute(NODE_COUNT); + context.getReader().readIntAttribute(NODE_COUNT); LOGGER.trace("attribute " + NODE_BREAKER_TOPOLOGY_ELEMENT_NAME + ".nodeCount is ignored."); }); context.getReader().readChildNodes(elementName -> { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java index 5b78fdd3216..de0670ab858 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java @@ -75,7 +75,7 @@ public List getXsdAsStreamList() { @Override public ActivePowerControl read(T identifiable, DeserializerContext context) { boolean participate = context.getReader().readBooleanAttribute("participate"); - float droop = context.getReader().readFloatAttribute("droop"); + double droop = context.getReader().readDoubleAttribute("droop"); double participationFactor = Double.NaN; NetworkDeserializerContext networkContext = (NetworkDeserializerContext) context; String extVersionStr = networkContext.getExtensionVersion(this).orElseThrow(IllegalStateException::new); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/LoadAsymmetricalSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/LoadAsymmetricalSerDe.java index ce194037da4..cdfdbc5e803 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/LoadAsymmetricalSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/LoadAsymmetricalSerDe.java @@ -30,7 +30,7 @@ public LoadAsymmetricalSerDe() { @Override public void write(LoadAsymmetrical loadAsym, SerializerContext context) { - context.getWriter().writeStringAttribute("connectionType", loadAsym.getConnectionType().name()); + context.getWriter().writeEnumAttribute("connectionType", loadAsym.getConnectionType()); context.getWriter().writeDoubleAttribute("deltaPa", loadAsym.getDeltaPa(), 0); context.getWriter().writeDoubleAttribute("deltaQa", loadAsym.getDeltaQa(), 0); context.getWriter().writeDoubleAttribute("deltaPb", loadAsym.getDeltaPb(), 0); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/TwoWindingsTransformerFortescueSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/TwoWindingsTransformerFortescueSerDe.java index 13d2c0f9a38..24e2822195c 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/TwoWindingsTransformerFortescueSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/TwoWindingsTransformerFortescueSerDe.java @@ -33,8 +33,8 @@ public void write(TwoWindingsTransformerFortescue twtFortescue, SerializerContex context.getWriter().writeDoubleAttribute("rz", twtFortescue.getRz(), Double.NaN); context.getWriter().writeDoubleAttribute("xz", twtFortescue.getXz(), Double.NaN); context.getWriter().writeBooleanAttribute("freeFluxes", twtFortescue.isFreeFluxes()); - context.getWriter().writeStringAttribute("connectionType1", twtFortescue.getConnectionType1().name()); - context.getWriter().writeStringAttribute("connectionType2", twtFortescue.getConnectionType2().name()); + context.getWriter().writeEnumAttribute("connectionType1", twtFortescue.getConnectionType1()); + context.getWriter().writeEnumAttribute("connectionType2", twtFortescue.getConnectionType2()); context.getWriter().writeDoubleAttribute("groundingR1", twtFortescue.getGroundingR1(), 0); context.getWriter().writeDoubleAttribute("groundingX1", twtFortescue.getGroundingX1(), 0); context.getWriter().writeDoubleAttribute("groundingR2", twtFortescue.getGroundingR2(), 0); From 644fffc1da7f97812a78c6df2cb0efdfecb82b11 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 11:43:21 +0100 Subject: [PATCH 38/42] Add binary transformation in all formats round trip Signed-off-by: Florian Dupuy --- .../powsybl/iidm/serde/AbstractIidmSerDeTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/AbstractIidmSerDeTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/AbstractIidmSerDeTest.java index 169a85e4316..2a18d6b6a83 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/AbstractIidmSerDeTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/AbstractIidmSerDeTest.java @@ -260,8 +260,19 @@ private static Network jsonWriteAndRead(Network networkInput, ExportOptions opti TreeDataFormat previousFormat = options.getFormat(); options.setFormat(TreeDataFormat.JSON); Anonymizer anonymizer = NetworkSerDe.write(networkInput, options, path); + + Network network1; + try (InputStream is = Files.newInputStream(path)) { + network1 = NetworkSerDe.read(is, new ImportOptions().setFormat(TreeDataFormat.JSON), anonymizer); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + options.setFormat(TreeDataFormat.BIN); + anonymizer = NetworkSerDe.write(network1, options, path); + try (InputStream is = Files.newInputStream(path)) { - Network networkOutput = NetworkSerDe.read(is, new ImportOptions().setFormat(TreeDataFormat.JSON), anonymizer); + Network networkOutput = NetworkSerDe.read(is, new ImportOptions().setFormat(TreeDataFormat.BIN), anonymizer); options.setFormat(previousFormat); return networkOutput; } catch (IOException e) { From 73a291579ac52f85c6eb4f85d0650137c0fb2fbe Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 14:36:43 +0100 Subject: [PATCH 39/42] Add magic number at file start Signed-off-by: Florian Dupuy --- .../com/powsybl/commons/binary/BinReader.java | 12 ++++++++- .../com/powsybl/commons/binary/BinWriter.java | 9 +++++-- .../powsybl/iidm/serde/BinaryImporter.java | 15 +++-------- .../com/powsybl/iidm/serde/NetworkSerDe.java | 7 +++-- .../iidm/serde/EurostagBinaryTest.java | 24 ++++++++++++------ .../eurostag-tutorial1-lf-extensions.bin | Bin 1716 -> 1727 bytes .../resources/V1_12/eurostag-tutorial1-lf.bin | Bin 1574 -> 1585 bytes 7 files changed, 43 insertions(+), 24 deletions(-) diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java index a9075facaaa..b45f63eb025 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinReader.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinReader.java @@ -26,14 +26,17 @@ public class BinReader implements TreeDataReader { private final DataInputStream dis; private final Map dictionary = new HashMap<>(); + private final byte[] binaryMagicNumber; - public BinReader(InputStream is) { + public BinReader(InputStream is, byte[] binaryMagicNumber) { + this.binaryMagicNumber = binaryMagicNumber; this.dis = new DataInputStream(new BufferedInputStream(Objects.requireNonNull(is))); } @Override public TreeDataHeader readHeader() { try { + readMagicNumber(); TreeDataHeader header = new TreeDataHeader(readString(), readExtensionVersions()); readDictionary(); return header; @@ -42,6 +45,13 @@ public TreeDataHeader readHeader() { } } + private void readMagicNumber() throws IOException { + byte[] read = dis.readNBytes(binaryMagicNumber.length); + if (!Arrays.equals(read, binaryMagicNumber)) { + throw new PowsyblException("Unexpected bytes at file start"); + } + } + public Map readExtensionVersions() throws IOException { int nbVersions = dis.readShort(); Map versions = new HashMap<>(); diff --git a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java index 8d3d49c51c2..14bb1860f21 100644 --- a/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java +++ b/commons/src/main/java/com/powsybl/commons/binary/BinWriter.java @@ -31,8 +31,10 @@ public class BinWriter implements TreeDataWriter { private final ByteArrayOutputStream buffer; private final Map nodeNamesIndex = new LinkedHashMap<>(); private Map extensionVersions; + private final byte[] binaryMagicNumber; - public BinWriter(OutputStream outputStream, String rootVersion) { + public BinWriter(OutputStream outputStream, byte[] binaryMagicNumber, String rootVersion) { + this.binaryMagicNumber = Objects.requireNonNull(binaryMagicNumber); this.rootVersion = Objects.requireNonNull(rootVersion); this.dos = new DataOutputStream(new BufferedOutputStream(Objects.requireNonNull(outputStream))); this.buffer = new ByteArrayOutputStream(); @@ -238,7 +240,10 @@ public void close() { } } - private void writeHeader() { + private void writeHeader() throws IOException { + // magic number ("Binary IIDM" in ASCII) + dos.write(binaryMagicNumber); + // iidm version writeString(rootVersion, dos); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java index 303dd50fbfe..27460f369d1 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/BinaryImporter.java @@ -12,9 +12,9 @@ import com.powsybl.commons.io.TreeDataFormat; import com.powsybl.iidm.network.Importer; -import java.io.DataInputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.InputStream; +import java.util.Arrays; import java.util.Properties; import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; @@ -47,15 +47,8 @@ public String getComment() { @Override protected boolean exists(ReadOnlyDataSource dataSource, String ext) throws IOException { if (ext != null) { - try (DataInputStream dis = new DataInputStream(dataSource.newInputStream(null, ext))) { - int versionNbBytes = dis.readShort(); - if (versionNbBytes > 0 && versionNbBytes < 50) { // large enough for version string - byte[] stringBytes = dis.readNBytes(versionNbBytes); - if (stringBytes.length == versionNbBytes) { - String version = new String(stringBytes, StandardCharsets.UTF_8); - return version.matches("^\\d+\\.\\d+(\\.\\d+)?$"); - } - } + try (InputStream dis = dataSource.newInputStream(null, ext)) { + return Arrays.equals(dis.readNBytes(NetworkSerDe.BIIDM_MAGIC_NUMBER.length), NetworkSerDe.BIIDM_MAGIC_NUMBER); } } return false; diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java index 9d83f0beaea..ea63e8cab90 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java @@ -80,6 +80,9 @@ public final class NetworkSerDe { private static final String ID = "id"; private static final String MINIMUM_VALIDATION_LEVEL = "minimumValidationLevel"; + /** Magic number for binary iidm files ("Binary IIDM" in ASCII) */ + static final byte[] BIIDM_MAGIC_NUMBER = {0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x49, 0x49, 0x44, 0x4d}; + private static final Supplier> EXTENSIONS_SUPPLIER = Suppliers.memoize(() -> ExtensionProviders.createProvider(ExtensionSerDe.class, EXTENSION_CATEGORY_NAME)); @@ -267,7 +270,7 @@ private static JsonWriter createJsonWriter(OutputStream os, ExportOptions option } private static TreeDataWriter createBinWriter(OutputStream os, ExportOptions options) { - return new BinWriter(os, options.getVersion().toString(".")); + return new BinWriter(os, BIIDM_MAGIC_NUMBER, options.getVersion().toString(".")); } private static void writeRootElement(Network n, NetworkSerializerContext context) { @@ -516,7 +519,7 @@ private static TreeDataReader createTreeDataReader(InputStream is, ImportOptions return switch (config.getFormat()) { case XML -> createXmlReader(is, config); case JSON -> createJsonReader(is, config); - case BIN -> new BinReader(is); + case BIN -> new BinReader(is, BIIDM_MAGIC_NUMBER); }; } diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java index b023fe1d383..2d1a6a9738b 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java @@ -16,6 +16,9 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; @@ -26,16 +29,21 @@ class EurostagBinaryTest extends AbstractIidmSerDeTest { @Test void roundTripTest() throws IOException { - ExportOptions exportOptions = new ExportOptions().setFormat(TreeDataFormat.BIN); - ImportOptions importOptions = new ImportOptions().setFormat(TreeDataFormat.BIN); + String fileName = "eurostag-tutorial1-lf.bin"; roundTripTest(EurostagTutorialExample1Factory.createWithLFResults(), - (n, jsonFile) -> NetworkSerDe.write(n, exportOptions, jsonFile), - jsonFile -> NetworkSerDe.read(jsonFile, importOptions), + (n, jsonFile) -> NetworkSerDe.write(n, new ExportOptions().setFormat(TreeDataFormat.BIN), jsonFile), + n -> { + try (InputStream is = Files.newInputStream(n)) { + return Network.read(fileName, is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }, ComparisonUtils::compareBytes, - getVersionedNetworkPath("eurostag-tutorial1-lf.bin", CURRENT_IIDM_VERSION)); + getVersionedNetworkPath(fileName, CURRENT_IIDM_VERSION)); //backward compatibility - roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf.bin", IidmVersion.V_1_12); + roundTripVersionedJsonFromMinToCurrentVersionTest(fileName, IidmVersion.V_1_12); } @Test @@ -46,8 +54,8 @@ void roundTripTestWithExtension() throws IOException { network.getGeneratorStream().findFirst().ifPresent(g -> g.newExtension(ActivePowerControlAdder.class).withDroop(2).withParticipate(true).add()); network.getLoadStream().forEach(l -> l.newExtension(ConnectablePositionAdder.class).newFeeder().withDirection(ConnectablePosition.Direction.BOTTOM).add().add()); roundTripTest(network, - (n, jsonFile) -> NetworkSerDe.write(n, exportOptions, jsonFile), - jsonFile -> NetworkSerDe.read(jsonFile, importOptions), + (n, binFile) -> NetworkSerDe.write(n, exportOptions, binFile), + binFile -> NetworkSerDe.read(binFile, importOptions), ComparisonUtils::compareBytes, getVersionedNetworkPath("eurostag-tutorial1-lf-extensions.bin", CURRENT_IIDM_VERSION)); diff --git a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin index cbafb36a731041a126bc2448312c16596c2aa63a..c110968ce657d5e74fbd9a0c4e732397a5e0f0f7 100644 GIT binary patch delta 19 acmdnOyPucaDKjszs8Yex)5Ukg7B&DvF$Svu delta 8 PcmdnbyM=cn_ZBt)4<`cz diff --git a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf.bin b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf.bin index 24853bab74b85b594e770a0b4e9b841b54446fa9..796dc0566ae03854354d6bf9caa3fdaba45f731c 100644 GIT binary patch delta 19 acmZ3+vyq3}DKjszs8Yex)5Uj#8XEvU`vw01 delta 8 PcmdnUvy5jWw;CG&4Lbr@ From 9fd79cbc1fdcf6c665a5b7eca3f677e6854ebd35 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 14:41:41 +0100 Subject: [PATCH 40/42] Add log about the feature being in beta state Signed-off-by: Florian Dupuy --- .../src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java | 1 + 1 file changed, 1 insertion(+) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java index ea63e8cab90..632324b8e80 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java @@ -270,6 +270,7 @@ private static JsonWriter createJsonWriter(OutputStream os, ExportOptions option } private static TreeDataWriter createBinWriter(OutputStream os, ExportOptions options) { + LOGGER.warn("BETA feature, the resulting binary file is not guaranteed to still be readable in the next releases"); return new BinWriter(os, BIIDM_MAGIC_NUMBER, options.getVersion().toString(".")); } From 37c23ce5b81e9dd45029e5963d9b2c6b3c8975ab Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 14:41:54 +0100 Subject: [PATCH 41/42] Remove unused method Signed-off-by: Florian Dupuy --- .../java/com/powsybl/iidm/serde/DanglingLineSerDe.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java index f7de82a03b2..8ceda109fdf 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/DanglingLineSerDe.java @@ -95,13 +95,6 @@ protected DanglingLineAdder createAdder(VoltageLevel parent) { return parent.newDanglingLine(); } - static boolean hasValidGeneration(DanglingLine dl, NetworkSerializerContext context) { - if (dl.getGeneration() != null) { - return context.getVersion().compareTo(IidmVersion.V_1_3) > 0; - } - return false; - } - @Override protected void writeSubElements(DanglingLine dl, VoltageLevel vl, NetworkSerializerContext context) { if (dl.getGeneration() != null) { From 1b0ce294ad5bad4070da0719f326a579603c20aa Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 16 Jan 2024 15:54:50 +0100 Subject: [PATCH 42/42] Fix the 4 code smells and then the consecutive duplicate Signed-off-by: Florian Dupuy --- .../iidm/serde/ConnectableSerDeUtil.java | 53 +++++++------------ .../com/powsybl/iidm/serde/LineSerDe.java | 2 +- .../serde/TwoWindingsTransformerSerDe.java | 2 +- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java index 7b23c971603..2c1be8668db 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ConnectableSerDeUtil.java @@ -98,13 +98,7 @@ public static void readNodeOrBus(InjectionAdder adder, NetworkDeserializer } public static void readNodeOrBus(InjectionAdder adder, String suffix, NetworkDeserializerContext context, TopologyKind topologyKind) { - switch (topologyKind) { - case NODE_BREAKER -> readNode(adder::setNode, suffix, context); - case BUS_BREAKER -> { - readBus(adder::setBus, suffix, context); - readConnectableBus(adder::setConnectableBus, suffix, context); - } - } + readNodeOrBus(suffix, topologyKind, adder::setNode, adder::setBus, adder::setConnectableBus, context); } private static void readNode(IntConsumer nodeAdder, String suffix, NetworkDeserializerContext context) { @@ -119,27 +113,25 @@ private static void readConnectableBus(Consumer busAdder, String suffix, busAdder.accept(context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute(CONNECTABLE_BUS + suffix))); } - public static void readNodeOrBus(BranchAdder adder, Network network, NetworkDeserializerContext context) { - String voltageLevelId1 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId1")); - adder.setVoltageLevel1(voltageLevelId1); - String suffix1 = String.valueOf(1); - switch (getTopologKind(voltageLevelId1, network)) { - case NODE_BREAKER -> readNode(adder::setNode1, suffix1, context); - case BUS_BREAKER -> { - readBus(adder::setBus1, suffix1, context); - readConnectableBus(adder::setConnectableBus1, suffix1, context); - } - } + public static void readVoltageLevelAndNodeOrBus(BranchAdder adder, Network network, NetworkDeserializerContext context) { + readVoltageLevelAndNodeOrBus("1", adder::setVoltageLevel1, adder::setNode1, adder::setBus1, adder::setConnectableBus1, network, context); + readVoltageLevelAndNodeOrBus("2", adder::setVoltageLevel2, adder::setNode2, adder::setBus2, adder::setConnectableBus2, network, context); + } + + private static void readVoltageLevelAndNodeOrBus(String suffix, Consumer voltageLevelSetter, IntConsumer nodeSetter, Consumer busSetter, Consumer connectableBusSetter, Network network, NetworkDeserializerContext context) { + String voltageLevelId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId" + suffix)); + voltageLevelSetter.accept(voltageLevelId); + readNodeOrBus(suffix, getTopologKind(voltageLevelId, network), nodeSetter, busSetter, connectableBusSetter, context); + } - String voltageLevelId2 = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId2")); - adder.setVoltageLevel2(voltageLevelId2); - String suffix2 = String.valueOf(2); - switch (getTopologKind(voltageLevelId2, network)) { - case NODE_BREAKER -> readNode(adder::setNode2, suffix2, context); + private static void readNodeOrBus(String suffix, TopologyKind topologyKind, IntConsumer nodeSetter, Consumer busSetter, Consumer connectableBusSetter, NetworkDeserializerContext context) { + switch (topologyKind) { + case NODE_BREAKER -> readNode(nodeSetter, suffix, context); case BUS_BREAKER -> { - readBus(adder::setBus2, suffix2, context); - readConnectableBus(adder::setConnectableBus2, suffix2, context); + readBus(busSetter, suffix, context); + readConnectableBus(connectableBusSetter, suffix, context); } + default -> throw new IllegalStateException(); } } @@ -152,16 +144,7 @@ private static TopologyKind getTopologKind(String vlId, Network network) { } public static void readNodeOrBus(int index, LegAdder adder, Network network, NetworkDeserializerContext context) { - String voltageLevelId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("voltageLevelId" + index)); - adder.setVoltageLevel(voltageLevelId); - String suffix = String.valueOf(index); - switch (getTopologKind(voltageLevelId, network)) { - case NODE_BREAKER -> readNode(adder::setNode, suffix, context); - case BUS_BREAKER -> { - readBus(adder::setBus, suffix, context); - readConnectableBus(adder::setConnectableBus, suffix, context); - } - } + readVoltageLevelAndNodeOrBus(String.valueOf(index), adder::setVoltageLevel, adder::setNode, adder::setBus, adder::setConnectableBus, network, context); } public static void writePQ(Integer index, Terminal t, TreeDataWriter writer) { diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java index a430027fc00..f2358814814 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/LineSerDe.java @@ -92,7 +92,7 @@ protected Line readRootElementAttributes(LineAdder adder, Network network, Netwo .setB1(b1) .setG2(g2) .setB2(b2); - readNodeOrBus(adder, network, context); + ConnectableSerDeUtil.readVoltageLevelAndNodeOrBus(adder, network, context); Line l = adder.add(); readOptionalPQ(1, l.getTerminal1(), context.getReader()); readOptionalPQ(2, l.getTerminal2(), context.getReader()); diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java index f34699281f9..949f2fa041a 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/TwoWindingsTransformerSerDe.java @@ -106,7 +106,7 @@ protected TwoWindingsTransformer readRootElementAttributes(TwoWindingsTransforme .setRatedU1(ratedU1) .setRatedU2(ratedU2); readRatedS("ratedS", context, adder::setRatedS); - readNodeOrBus(adder, s.getNetwork(), context); + ConnectableSerDeUtil.readVoltageLevelAndNodeOrBus(adder, s.getNetwork(), context); TwoWindingsTransformer twt = adder.add(); readOptionalPQ(1, twt.getTerminal1(), context.getReader()); readOptionalPQ(2, twt.getTerminal2(), context.getReader());