From f987230dfa148c5f84a38995c0a6696723bfc5fd Mon Sep 17 00:00:00 2001 From: Olivier Perrin Date: Wed, 3 Jan 2024 17:23:01 +0100 Subject: [PATCH] Add 'withAutomationSystems' import option Signed-off-by: Olivier Perrin --- .../iidm/serde/AbstractIdentifiableSerDe.java | 10 ++- .../iidm/serde/AbstractTreeDataImporter.java | 10 ++- .../com/powsybl/iidm/serde/ImportOptions.java | 10 +++ .../serde/OverloadManagementSystemSerDe.java | 68 ++++++++++++------- .../powsybl/iidm/serde/SubstationSerDe.java | 6 +- .../powsybl/iidm/serde/ImportOptionsTest.java | 3 + .../OverloadManagementSystemSerDeTest.java | 35 ++++++++-- .../powsybl/iidm/serde/XMLImporterTest.java | 2 +- 8 files changed, 105 insertions(+), 39 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..85043270f0b 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 @@ -56,11 +56,15 @@ public final void write(T identifiable, P parent, NetworkSerializerContext conte protected String readIdentifierAttributes(A adder, NetworkDeserializerContext context) { String id = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("id")); String name = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("name")); - adder.setId(id) - .setName(name); + if (adder != null) { + adder.setId(id) + .setName(name); + } IidmSerDeUtil.runFromMinimumVersion(IidmVersion.V_1_2, context, () -> { boolean fictitious = context.getReader().readBooleanAttribute("fictitious", false); - adder.setFictitious(fictitious); + if (adder != null) { + adder.setFictitious(fictitious); + } }); return id; } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTreeDataImporter.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTreeDataImporter.java index 2c850181ec6..caddb83a507 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTreeDataImporter.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/AbstractTreeDataImporter.java @@ -50,6 +50,8 @@ public abstract class AbstractTreeDataImporter implements Importer { public static final String EXTENSIONS_LIST = "iidm.import.xml.extensions"; + public static final String WITH_AUTOMATION_SYSTEMS = "iidm.import.xml.with-automation-systems"; + private static final Parameter THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND_PARAMETER = new Parameter(THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND, ParameterType.BOOLEAN, "Throw exception if extension not found", Boolean.FALSE) .addAdditionalNames("throwExceptionIfExtensionNotFound"); @@ -58,6 +60,9 @@ public abstract class AbstractTreeDataImporter implements Importer { = new Parameter(EXTENSIONS_LIST, ParameterType.STRING_LIST, "The list of extension files ", null, EXTENSIONS_SUPPLIER.get().getProviders().stream().map(ExtensionProvider::getExtensionName).collect(Collectors.toList())); + private static final Parameter WITH_AUTOMATION_SYSTEMS_PARAMETER = new Parameter(WITH_AUTOMATION_SYSTEMS, ParameterType.BOOLEAN, + "Import network with automation systems", Boolean.TRUE); + private final ParameterDefaultValueConfig defaultValueConfig; static final String SUFFIX_MAPPING = "_mapping"; @@ -72,7 +77,7 @@ protected AbstractTreeDataImporter(PlatformConfig platformConfig) { @Override public List getParameters() { - return List.of(THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND_PARAMETER, EXTENSIONS_LIST_PARAMETER); + return List.of(THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND_PARAMETER, EXTENSIONS_LIST_PARAMETER, WITH_AUTOMATION_SYSTEMS_PARAMETER); } private String findExtension(ReadOnlyDataSource dataSource) throws IOException { @@ -150,7 +155,8 @@ public Network importData(ReadOnlyDataSource dataSource, NetworkFactory networkF protected ImportOptions createImportOptions(Properties parameters) { return new ImportOptions() .setThrowExceptionIfExtensionNotFound(Parameter.readBoolean(getFormat(), parameters, THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND_PARAMETER, defaultValueConfig)) - .setExtensions(Parameter.readStringList(getFormat(), parameters, EXTENSIONS_LIST_PARAMETER, defaultValueConfig) != null ? new HashSet<>(Parameter.readStringList(getFormat(), parameters, EXTENSIONS_LIST_PARAMETER, defaultValueConfig)) : null); + .setExtensions(Parameter.readStringList(getFormat(), parameters, EXTENSIONS_LIST_PARAMETER, defaultValueConfig) != null ? new HashSet<>(Parameter.readStringList(getFormat(), parameters, EXTENSIONS_LIST_PARAMETER, defaultValueConfig)) : null) + .setWithAutomationSystems(Parameter.readBoolean(getFormat(), parameters, WITH_AUTOMATION_SYSTEMS_PARAMETER, defaultValueConfig)); } } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ImportOptions.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ImportOptions.java index 0f9901dffc6..a701c8451ee 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ImportOptions.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/ImportOptions.java @@ -17,6 +17,7 @@ public class ImportOptions extends AbstractOptions { private boolean throwExceptionIfExtensionNotFound = false; + private boolean withAutomationSystems = true; public ImportOptions() { } @@ -50,4 +51,13 @@ public ImportOptions addExtension(String extension) { public boolean isThrowExceptionIfExtensionNotFound() { return throwExceptionIfExtensionNotFound; } + + public boolean isWithAutomationSystems() { + return withAutomationSystems; + } + + public ImportOptions setWithAutomationSystems(boolean withAutomationSystems) { + this.withAutomationSystems = withAutomationSystems; + return this; + } } 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 55520b4b0bd..075b5cc43b4 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 @@ -10,6 +10,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -100,9 +101,11 @@ protected void readRootElementAttributes(OverloadManagementSystemAdder adder, String monitoredElementId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("monitoredElementId")); String side = context.getReader().readStringAttribute("side"); ThreeSides monitoredSide = side == null ? ThreeSides.ONE : ThreeSides.valueOf(side); - adder.setEnabled(enabled) - .setMonitoredElementId(monitoredElementId) - .setMonitoredElementSide(monitoredSide); + if (adder != null) { + adder.setEnabled(enabled) + .setMonitoredElementId(monitoredElementId) + .setMonitoredElementSide(monitoredSide); + } } @Override @@ -121,25 +124,29 @@ protected void readSubElements(String id, OverloadManagementSystemAdder adder, String side = context.getReader().readStringAttribute("side"); TwoSides sideToOperate = side == null ? TwoSides.ONE : TwoSides.valueOf(side); context.getReader().readEndNode(); - adder.newBranchTripping() - .setKey(key) - .setName(name) - .setCurrentLimit(currentLimit) - .setOpenAction(openAction) - .setBranchToOperateId(branchId) - .setSideToOperate(sideToOperate) - .add(); + if (adder != null) { + adder.newBranchTripping() + .setKey(key) + .setName(name) + .setCurrentLimit(currentLimit) + .setOpenAction(openAction) + .setBranchToOperateId(branchId) + .setSideToOperate(sideToOperate) + .add(); + } } case SWITCH_TRIPPING_TAG -> { String switchId = context.getAnonymizer().deanonymizeString(context.getReader().readStringAttribute("switchId")); context.getReader().readEndNode(); - adder.newSwitchTripping() - .setKey(key) - .setName(name) - .setCurrentLimit(currentLimit) - .setOpenAction(openAction) - .setSwitchToOperateId(switchId) - .add(); + if (adder != null) { + adder.newSwitchTripping() + .setKey(key) + .setName(name) + .setCurrentLimit(currentLimit) + .setOpenAction(openAction) + .setSwitchToOperateId(switchId) + .add(); + } } case THREE_WINDINGS_TRANSFORMER_TRIPPING_TAG -> { String twtId = context.getAnonymizer().deanonymizeString( @@ -147,14 +154,16 @@ protected void readSubElements(String id, OverloadManagementSystemAdder adder, String side = context.getReader().readStringAttribute("side"); ThreeSides sideToOperate = side == null ? ThreeSides.ONE : ThreeSides.valueOf(side); context.getReader().readEndNode(); - adder.newThreeWindingsTransformerTripping() - .setKey(key) - .setName(name) - .setCurrentLimit(currentLimit) - .setOpenAction(openAction) - .setThreeWindingsTransformerToOperateId(twtId) - .setSideToOperate(sideToOperate) - .add(); + if (adder != null) { + adder.newThreeWindingsTransformerTripping() + .setKey(key) + .setName(name) + .setCurrentLimit(currentLimit) + .setOpenAction(openAction) + .setThreeWindingsTransformerToOperateId(twtId) + .setSideToOperate(sideToOperate) + .add(); + } } default -> readSubElement(elementName, id, toApply, context); } @@ -169,4 +178,11 @@ protected boolean postponeElementCreation() { // To avoid this, this latter is postponed. return true; } + + public final void skip(NetworkDeserializerContext context) { + List> toApply = new ArrayList<>(); + String id = readIdentifierAttributes(null, context); + readRootElementAttributes(null, toApply, context); + readSubElements(id, null, toApply, context); + } } 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 de9ae877c1b..2b1c7b4864c 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 @@ -129,6 +129,10 @@ protected void readSubElements(Substation s, NetworkDeserializerContext context) private static void checkSupportedAndReadOverloadManagementSystems(Substation s, NetworkDeserializerContext context) { IidmSerDeUtil.assertMinimumVersion(ROOT_ELEMENT_NAME, OverloadManagementSystemSerDe.ROOT_ELEMENT_NAME, IidmSerDeUtil.ErrorMessage.NOT_SUPPORTED, IidmVersion.V_1_12, context); - OverloadManagementSystemSerDe.INSTANCE.read(s, context); + if (context.getOptions().isWithAutomationSystems()) { + OverloadManagementSystemSerDe.INSTANCE.read(s, context); + } else { + OverloadManagementSystemSerDe.INSTANCE.skip(context); + } } } diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/ImportOptionsTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/ImportOptionsTest.java index f39ca4e68f4..0a84c6e2943 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/ImportOptionsTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/ImportOptionsTest.java @@ -23,7 +23,9 @@ void importOptionsTest() { ImportOptions options = new ImportOptions(); Set extensionsList = Sets.newHashSet("loadFoo", "loadBar"); options.setExtensions(extensionsList); + options.setWithAutomationSystems(false); assertEquals(Boolean.FALSE, options.withNoExtension()); + assertEquals(Boolean.FALSE, options.isWithAutomationSystems()); options.addExtension("loadBar"); assertEquals(2, (int) options.getExtensions().map(Set::size).orElse(-1)); @@ -48,5 +50,6 @@ void importOptionsDefaultValues() { assertEquals(Boolean.FALSE, options.withNoExtension()); assertEquals(-1, (int) options.getExtensions().map(Set::size).orElse(-1)); assertEquals(Boolean.TRUE, options.withAllExtensions()); + assertEquals(Boolean.TRUE, options.isWithAutomationSystems()); } } diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDeTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDeTest.java index 3118f58f4e6..afa835b3540 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDeTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/OverloadManagementSystemSerDeTest.java @@ -62,19 +62,41 @@ void exportDisabledTest(TreeDataFormat format) { private void exportDisabledTest(TreeDataFormat format, IidmVersion version) { // Export the network without the automation systems - ExportResult exportResult = writeNetwork(format, version); + ExportResult exportResult = writeNetwork(format, version, false); // Check that the exported String does NOT contain OMS tags Assertions.assertFalse(exportResult.content().contains(OverloadManagementSystemSerDe.ROOT_ELEMENT_NAME)); // Load the exported String to check if it is really valid - Network networkOutput = readNetwork(format, exportResult); + Network networkOutput = readNetwork(format, exportResult, true); // Check that the read network has substations, lines, ... but no OMS (none were exported) checkNetworkAgainstRef(networkOutput, false); } - private static ExportResult writeNetwork(TreeDataFormat format, IidmVersion version) { + @ParameterizedTest + @MethodSource("provideFormats") + void importDisabledTest(TreeDataFormat format) { + testForAllVersionsSince(IidmVersion.V_1_12, v -> importDisabledTest(format, v)); + } + + private void importDisabledTest(TreeDataFormat format, IidmVersion version) { + // Export the network (with the automation systems) + ExportResult exportResult = writeNetwork(format, version, true); + // Check that the exported String DOES contain OMS tags + Assertions.assertTrue(exportResult.content().contains(OverloadManagementSystemSerDe.ROOT_ELEMENT_NAME)); + // Load the exported String without the automation systems + Network networkOutput = readNetwork(format, exportResult, false); + // Check that the read network has substations, lines, ... but no OMS (none were imported) + checkNetworkAgainstRef(networkOutput, false); + + // Final check: import the same network, but this time with the automation systems + // They should now be present + networkOutput = readNetwork(format, exportResult, true); + checkNetworkAgainstRef(networkOutput, true); + } + + private static ExportResult writeNetwork(TreeDataFormat format, IidmVersion version, boolean withAutomationSystems) { ExportOptions options = new ExportOptions() .setFormat(format) - .setWithAutomationSystems(false) + .setWithAutomationSystems(withAutomationSystems) .setVersion(version.toString(".")); ExportResult exportResult; try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { @@ -87,9 +109,10 @@ private static ExportResult writeNetwork(TreeDataFormat format, IidmVersion vers return exportResult; } - private static Network readNetwork(TreeDataFormat format, ExportResult exportResult) { + private static Network readNetwork(TreeDataFormat format, ExportResult exportResult, boolean withAutomationSystems) { ImportOptions options = new ImportOptions() - .setFormat(format); + .setFormat(format) + .setWithAutomationSystems(withAutomationSystems); Network networkOutput; try (InputStream is = IOUtils.toInputStream(exportResult.content(), "UTF-8")) { networkOutput = NetworkSerDe.read(is, options, exportResult.anonymizer()); diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/XMLImporterTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/XMLImporterTest.java index 01e194663fb..90294d2fc8b 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/XMLImporterTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/XMLImporterTest.java @@ -137,7 +137,7 @@ void getFormat() { @Test void getParameters() { - assertEquals(2, importer.getParameters().size()); + assertEquals(3, importer.getParameters().size()); assertEquals("iidm.import.xml.throw-exception-if-extension-not-found", importer.getParameters().get(0).getName()); assertEquals(Arrays.asList("iidm.import.xml.throw-exception-if-extension-not-found", "throwExceptionIfExtensionNotFound"), importer.getParameters().get(0).getNames()); }