From 2836c5a634620cecd162e2243e016b3ac5e58334 Mon Sep 17 00:00:00 2001 From: Luma Date: Wed, 2 Mar 2022 17:40:08 +0100 Subject: [PATCH 1/9] CGMES export to specific CIM version Signed-off-by: Luma --- .../cgmes/conversion/test/export/ExportToCimVersionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java index ed53739f53d..8bf07244472 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java @@ -21,6 +21,7 @@ import org.junit.Test; import java.io.IOException; + import java.util.Properties; import static org.junit.Assert.assertEquals; From 652b52142caf9f6c2a84b0c702e104d3749c0458 Mon Sep 17 00:00:00 2001 From: Luma Date: Thu, 3 Mar 2022 11:39:02 +0100 Subject: [PATCH 2/9] Export to CGMES 3 Signed-off-by: Luma --- .../conversion/export/CgmesExportContext.java | 10 +-- .../conversion/export/CgmesExportUtil.java | 5 +- .../conversion/export/EquipmentExport.java | 2 +- .../export/elements/ModelDescriptionEq.java | 2 +- .../test/export/CgmesExportContextTest.java | 11 ++- .../test/export/ExportToCimVersionTest.java | 34 ++++++-- .../test/export/ExportXmlCompare.java | 80 +++++++++---------- .../powsybl/cgmes/model/CgmesNamespace.java | 71 +++++++++++----- .../cgmes/model/CgmesOnDataSource.java | 9 +-- 9 files changed, 137 insertions(+), 87 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java index d5d6518a718..a3f0d470a16 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java @@ -35,10 +35,10 @@ public class CgmesExportContext { private CgmesTopologyKind topologyKind = CgmesTopologyKind.BUS_BRANCH; private DateTime scenarioTime = DateTime.now(); - private ModelDescription eqModelDescription = new ModelDescription("EQ Model", CgmesNamespace.EQ_PROFILE); - private ModelDescription tpModelDescription = new ModelDescription("TP Model", CgmesNamespace.TP_PROFILE); - private ModelDescription svModelDescription = new ModelDescription("SV Model", CgmesNamespace.SV_PROFILE); - private ModelDescription sshModelDescription = new ModelDescription("SSH Model", CgmesNamespace.SSH_PROFILE); + private ModelDescription eqModelDescription = new ModelDescription("EQ Model", CgmesNamespace.getProfile(cimVersion, "EQ")); + private ModelDescription tpModelDescription = new ModelDescription("TP Model", CgmesNamespace.getProfile(cimVersion, "TP")); + private ModelDescription svModelDescription = new ModelDescription("SV Model", CgmesNamespace.getProfile(cimVersion, "SV")); + private ModelDescription sshModelDescription = new ModelDescription("SSH Model", CgmesNamespace.getProfile(cimVersion, "SSH")); private boolean exportBoundaryPowerFlows = true; private boolean exportFlowsForSwitches = false; @@ -533,7 +533,7 @@ public CgmesExportContext setExportFlowsForSwitches(boolean exportFlowsForSwitch } public String getCimNamespace() { - return CgmesNamespace.getCimNamespace(cimVersion); + return CgmesNamespace.getCim(cimVersion); } public Set getTopologicalNodesByBusViewBus(String busId) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java index 462db11fc75..12aff88344a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java @@ -8,6 +8,7 @@ import com.powsybl.cgmes.conversion.export.CgmesExportContext.ModelDescription; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.CgmesNamespace; import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.LoadDetail; @@ -65,12 +66,12 @@ public static String getUniqueId() { public static void writeRdfRoot(int cimVersion, XMLStreamWriter writer) throws XMLStreamException { writer.setPrefix("entsoe", ENTSOE_NAMESPACE); writer.setPrefix("rdf", RDF_NAMESPACE); - writer.setPrefix("cim", getCimNamespace(cimVersion)); + writer.setPrefix("cim", CgmesNamespace.getCim(cimVersion)); writer.setPrefix("md", MD_NAMESPACE); writer.writeStartElement(RDF_NAMESPACE, "RDF"); writer.writeNamespace("entsoe", ENTSOE_NAMESPACE); writer.writeNamespace("rdf", RDF_NAMESPACE); - writer.writeNamespace("cim", getCimNamespace(cimVersion)); + writer.writeNamespace("cim", CgmesNamespace.getCim(cimVersion)); writer.writeNamespace("md", MD_NAMESPACE); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java index cdcece4d9ba..967a43fa89d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java @@ -42,7 +42,7 @@ public static void write(Network network, XMLStreamWriter writer, CgmesExportCon String cimNamespace = context.getCimNamespace(); // TODO fill EQ Model Description - if (context.getCimVersion() == 16) { + if (context.getCimVersion() >= 16) { ModelDescriptionEq.write(writer, context.getEqModelDescription(), context); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ModelDescriptionEq.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ModelDescriptionEq.java index b2dea58f7e4..ce379c02cc0 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ModelDescriptionEq.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ModelDescriptionEq.java @@ -47,7 +47,7 @@ public static void write(XMLStreamWriter writer, CgmesExportContext.ModelDescrip writer.writeCharacters(modelDescription.getProfile()); writer.writeEndElement(); writer.writeStartElement(MD_NAMESPACE, CgmesNames.PROFILE); - writer.writeCharacters(CgmesNamespace.EQ_OPERATION_PROFILE); + writer.writeCharacters(CgmesNamespace.getProfile(context.getCimVersion(), "EQ_OP")); writer.writeEndElement(); writer.writeStartElement(MD_NAMESPACE, CgmesNames.MODELING_AUTHORITY_SET); writer.writeCharacters(modelDescription.getModelingAuthoritySet()); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CgmesExportContextTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CgmesExportContextTest.java index df784a90a67..6ca3d32cb3a 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CgmesExportContextTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CgmesExportContextTest.java @@ -14,6 +14,7 @@ import com.powsybl.cgmes.extensions.CgmesSvMetadataAdder; import com.powsybl.cgmes.extensions.CgmesTopologyKind; import com.powsybl.cgmes.extensions.CimCharacteristicsAdder; +import com.powsybl.cgmes.model.CgmesNamespace; import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; @@ -25,8 +26,6 @@ import java.util.List; import java.util.Properties; -import static com.powsybl.cgmes.model.CgmesNamespace.CIM_14_NAMESPACE; -import static com.powsybl.cgmes.model.CgmesNamespace.CIM_16_NAMESPACE; import static org.junit.Assert.*; /** @@ -48,7 +47,7 @@ public void networkConstructor() { CgmesExportContext context1 = new CgmesExportContext(network); assertEquals(16, context1.getCimVersion()); - assertEquals(CIM_16_NAMESPACE, context1.getCimNamespace()); + assertEquals(CgmesNamespace.getCim(16), context1.getCimNamespace()); assertEquals(CgmesTopologyKind.BUS_BRANCH, context1.getTopologyKind()); assertEquals(network.getCaseDate(), context1.getScenarioTime()); assertEquals("SV Model", context1.getSvModelDescription().getDescription()); @@ -71,7 +70,7 @@ public void networkConstructor() { CgmesExportContext context2 = new CgmesExportContext(network); assertEquals(14, context2.getCimVersion()); - assertEquals(CIM_14_NAMESPACE, context2.getCimNamespace()); + assertEquals(CgmesNamespace.getCim(14), context2.getCimNamespace()); assertEquals(CgmesTopologyKind.NODE_BREAKER, context2.getTopologyKind()); assertEquals(network.getCaseDate(), context2.getScenarioTime()); assertEquals("test", context2.getSvModelDescription().getDescription()); @@ -86,7 +85,7 @@ public void networkConstructor() { public void emptyConstructor() { CgmesExportContext context = new CgmesExportContext(); assertEquals(16, context.getCimVersion()); - assertEquals(CIM_16_NAMESPACE, context.getCimNamespace()); + assertEquals(CgmesNamespace.getCim(16), context.getCimNamespace()); assertEquals(CgmesTopologyKind.BUS_BRANCH, context.getTopologyKind()); assertTrue(new Duration(DateTime.now(), context.getScenarioTime()).getStandardMinutes() < 1); assertEquals("SV Model", context.getSvModelDescription().getDescription()); @@ -112,7 +111,7 @@ public void getSet() { .setModelingAuthoritySet("cgmes.org"); assertEquals(14, context.getCimVersion()); - assertEquals(CIM_14_NAMESPACE, context.getCimNamespace()); + assertEquals(CgmesNamespace.getCim(14), context.getCimNamespace()); assertEquals(CgmesTopologyKind.NODE_BREAKER, context.getTopologyKind()); assertEquals(DateTime.parse("2020-09-22T17:21:11.381+02:00"), context.getScenarioTime()); assertEquals("test", context.getSvModelDescription().getDescription()); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java index 8bf07244472..5edbadd1404 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java @@ -22,6 +22,8 @@ import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Properties; import static org.junit.Assert.assertEquals; @@ -45,20 +47,40 @@ public void testExportDataSourceEmptyBaseName() throws IOException { @Test public void testExportIEEE14Cim14ToCim16() { + testExportIEEE14Cim14ToCim(16, tempDir()); + } + + @Test + public void testExportIEEE14Cim14ToCim100() { + // Testing export to CGMES 3 + // FIXME(Luma) verify that namespace in headers are correct + // FIXME(Luma) verify that all classes and attributes are valid against profiles (using CIMdesk) + testExportIEEE14Cim14ToCim(100, tempDir()); + } + + private void testExportIEEE14Cim14ToCim(int cimVersion, Path tempDir) { ReadOnlyDataSource dataSource = Cim14SmallCasesCatalog.ieee14().dataSource(); Network networkCim14 = new CgmesImport().importData(dataSource, NetworkFactory.findDefault(), null); CimCharacteristics cim14 = networkCim14.getExtension(CimCharacteristics.class); Properties params = new Properties(); - params.put(CgmesExport.CIM_VERSION, "16"); - ZipFileDataSource zipIEEE14Cim16 = new ZipFileDataSource(tmpDir.resolve("."), "IEEE14"); - new CgmesExport().export(networkCim14, params, zipIEEE14Cim16); + params.put(CgmesExport.CIM_VERSION, Integer.toString(cimVersion)); + ZipFileDataSource zip = new ZipFileDataSource(tempDir.resolve("."), "IEEE14_CIM" + cimVersion); + new CgmesExport().export(networkCim14, params, zip); - Network networkCim16 = Importers.loadNetwork(tmpDir.resolve("IEEE14.zip")); - CimCharacteristics cim16 = networkCim16.getExtension(CimCharacteristics.class); + Network networkCimVersion = Importers.loadNetwork(tempDir.resolve("IEEE14_CIM" + cimVersion + ".zip")); + CimCharacteristics cim = networkCimVersion.getExtension(CimCharacteristics.class); assertEquals(14, cim14.getCimVersion()); - assertEquals(16, cim16.getCimVersion()); + assertEquals(cimVersion, cim.getCimVersion()); } + private Path tempDir() { + boolean debug = true; + if (debug) { + return Paths.get("/Users/zamarrenolm/work/temp/cgmes3"); + } else { + return tmpDir; + } + } } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index 8fcd210a05a..a70b62db1cc 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -7,6 +7,7 @@ package com.powsybl.cgmes.conversion.test.export; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.CgmesNamespace; import com.powsybl.commons.datasource.DataSource; import com.powsybl.commons.datasource.ReadOnlyDataSource; import org.joda.time.DateTime; @@ -32,10 +33,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.powsybl.cgmes.model.CgmesNamespace.CIM_16_NAMESPACE; import static com.powsybl.cgmes.model.CgmesNamespace.RDF_NAMESPACE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author Luma ZamarreƱo @@ -84,7 +83,7 @@ static void compareNetworks(InputStream expected, InputStream actual, Difference .withDifferenceEvaluator(knownDiffs) .withComparisonListeners(ExportXmlCompare::debugComparison) .build(); - assertTrue(!diff.hasDifferences()); + assertFalse(diff.hasDifferences()); } static void compareEQNetworks(InputStream expected, InputStream actual, DifferenceEvaluator knownDiffs) { @@ -100,7 +99,7 @@ static void compareEQNetworks(InputStream expected, InputStream actual, Differen .withDifferenceEvaluator(knownDiffs) .withComparisonListeners(ExportXmlCompare::debugComparison) .build(); - assertTrue(!diff.hasDifferences()); + assertFalse(diff.hasDifferences()); } static boolean isConsideredForNetwork(Attr attr) { @@ -111,18 +110,19 @@ private static boolean isConsideredForEQNetwork(Attr attr) { String elementName = attr.getOwnerElement().getLocalName(); boolean ignored = false; if (elementName != null) { - ignored = elementName.equals("danglingLine"); - if (elementName.startsWith("network")) { - ignored |= attr.getLocalName().equals("id") || attr.getLocalName().equals("forecastDistance") || attr.getLocalName().equals("caseDate") || attr.getLocalName().equals("sourceFormat"); + if (elementName.equals("danglingLine")) { + ignored = true; + } else if (elementName.startsWith("network")) { + ignored = attr.getLocalName().equals("id") || attr.getLocalName().equals("forecastDistance") || attr.getLocalName().equals("caseDate") || attr.getLocalName().equals("sourceFormat"); } else if (elementName.startsWith("voltageLevel")) { - ignored |= attr.getLocalName().equals("topologyKind") || attr.getLocalName().equals("lowVoltageLimit") || attr.getLocalName().equals("highVoltageLimit"); + ignored = attr.getLocalName().equals("topologyKind") || attr.getLocalName().equals("lowVoltageLimit") || attr.getLocalName().equals("highVoltageLimit"); } else if (elementName.startsWith("hvdcLine")) { - ignored |= attr.getLocalName().equals("converterStation1") || attr.getLocalName().equals("converterStation2") || attr.getLocalName().equals("convertersMode"); + ignored = attr.getLocalName().equals("converterStation1") || attr.getLocalName().equals("converterStation2") || attr.getLocalName().equals("convertersMode"); } else if (elementName.contains("TapChanger")) { - ignored |= attr.getLocalName().equals("regulating") || attr.getLocalName().equals("regulationMode") || attr.getLocalName().equals("regulationValue") + ignored = attr.getLocalName().equals("regulating") || attr.getLocalName().equals("regulationMode") || attr.getLocalName().equals("regulationValue") || attr.getLocalName().equals("targetV") || attr.getLocalName().equals("targetDeadband"); } else { - ignored |= attr.getLocalName().contains("node") || attr.getLocalName().contains("bus") || attr.getLocalName().contains("Bus"); + ignored = attr.getLocalName().contains("node") || attr.getLocalName().contains("bus") || attr.getLocalName().contains("Bus"); } } return !ignored; @@ -207,18 +207,18 @@ private static boolean isNodeBreakerProperty(Node n) { private static boolean isDanglingLineConversion(Node n) { String name = n.getLocalName(); - return (name.startsWith("substation") && SMALLGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("voltageLevel") && SMALLGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("line") && SMALLGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("substation") && MINIGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("voltageLevel") && MINIGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("line") && MINIGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("substation") && MICROGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("voltageLevel") && MICROGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent())) - || (name.startsWith("line") && MICROGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent())); - } - - static interface DifferenceBuilder { + return name.startsWith("substation") && SMALLGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("voltageLevel") && SMALLGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("line") && SMALLGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("substation") && MINIGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("voltageLevel") && MINIGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("line") && MINIGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("substation") && MICROGRID_SUBSTATIONS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("voltageLevel") && MICROGRID_VOLTAGELEVELS.contains(n.getAttributes().getNamedItem("name").getTextContent()) + || name.startsWith("line") && MICROGRID_LINES.contains(n.getAttributes().getNamedItem("name").getTextContent()); + } + + interface DifferenceBuilder { DiffBuilder build(InputStream control, InputStream test, DifferenceEvaluator de); } @@ -230,7 +230,7 @@ static DiffBuilder diffSSH(InputStream expected, InputStream actual, DifferenceE return selectingEquivalentSshObjects(ignoringNonPersistentSshIds(withSelectedSshNodes(diff(expected, actual, de)))); } - static void compareSSH(InputStream expected, InputStream actual, DifferenceEvaluator knownDiffs) throws IOException { + static void compareSSH(InputStream expected, InputStream actual, DifferenceEvaluator knownDiffs) { onlyNodeListSequenceDiffs(compare(diffSSH(expected, actual, knownDiffs).checkForIdentical())); } @@ -263,8 +263,8 @@ static ComparisonResult ensuringIncreasedModelVersion(Comparison comparison, Com Node control = comparison.getControlDetails().getTarget(); if (comparison.getType() == ComparisonType.TEXT_VALUE && control.getParentNode().getLocalName().equals("Model.version")) { Node test = comparison.getTestDetails().getTarget(); - int vcontrol = Integer.valueOf(control.getTextContent()); - int vtest = Integer.valueOf(test.getTextContent()); + int vcontrol = Integer.parseInt(control.getTextContent()); + int vtest = Integer.parseInt(test.getTextContent()); if (vtest == vcontrol + 1) { return ComparisonResult.EQUAL; } @@ -307,8 +307,8 @@ static ComparisonResult ignoringStaticVarCompensatorDiffq(Comparison comparison, if (comparison.getType() == ComparisonType.TEXT_VALUE && control.getParentNode().getLocalName().equals("StaticVarCompensator.q")) { Node test = comparison.getTestDetails().getTarget(); // Both elements must exist and have valid numeric values - double qcontrol = Double.valueOf(control.getTextContent()); - double qtest = Double.valueOf(test.getTextContent()); + double qcontrol = Double.parseDouble(control.getTextContent()); + double qtest = Double.parseDouble(test.getTextContent()); // But they could be different // When we export we save in SSH.q the value of the SVC.terminal.q // It would be the result of the power flow calculation @@ -427,8 +427,8 @@ static ComparisonResult ignoringSimilarPowerFlows(Comparison comparison, Compari if (control.getParentNode() != null && control.getParentNode().getNodeType() == Node.ELEMENT_NODE && (control.getParentNode().getLocalName().equals("SvPowerFlow.p") || control.getParentNode().getLocalName().equals("SvPowerFlow.q"))) { - double expected = Double.valueOf(control.getNodeValue()); - double actual = Double.valueOf(comparison.getTestDetails().getTarget().getNodeValue()); + double expected = Double.parseDouble(control.getNodeValue()); + double actual = Double.parseDouble(comparison.getTestDetails().getTarget().getNodeValue()); if (Math.abs(expected - actual) < 0.2d) { return ComparisonResult.EQUAL; } @@ -460,17 +460,13 @@ static ComparisonResult ignoringSimilarPowerFlows(Comparison comparison, Compari private static boolean isJunctionOrBusbarTerminal(Node n) { if (n != null && n.getNodeType() == Node.ELEMENT_NODE && n.getLocalName().equals(CgmesNames.TERMINAL)) { String about = n.getAttributes().getNamedItemNS(RDF_NAMESPACE, "about").getTextContent(); - if (JUNCTIONS_TERMINALS.contains(about)) { - return true; - } else if (BUSBAR_TERMINALS.contains(about)) { - return true; - } + return JUNCTIONS_TERMINALS.contains(about) || BUSBAR_TERMINALS.contains(about); } return false; } private static void isOk(Diff diff) { - assertTrue(!diff.hasDifferences()); + assertFalse(diff.hasDifferences()); } private static void onlyNodeListSequenceDiffs(Diff diff) { @@ -690,10 +686,8 @@ private static void debugNode(Node n) { } private static void debugAttributes(Node n, String indent) { - if (n.getAttributes() != null) { - debugAttribute(n, RDF_NAMESPACE, "resource", indent); - debugAttribute(n, RDF_NAMESPACE, "about", indent); - } + debugAttribute(n, RDF_NAMESPACE, "resource", indent); + debugAttribute(n, RDF_NAMESPACE, "about", indent); } private static void debugAttribute(Node n, String namespace, String localName, String indent) { @@ -732,7 +726,7 @@ private static boolean isConsideredSshNode(Node n) { // Optional attributes with default values if (name.equals("EquivalentInjection.regulationStatus") && n.getTextContent().equals("false")) { return false; - } else if (name.equals("EquivalentInjection.regulationTarget") && Double.valueOf(n.getTextContent()) == 0) { + } else if (name.equals("EquivalentInjection.regulationTarget") && Double.parseDouble(n.getTextContent()) == 0) { return false; } return name.equals("RDF") @@ -798,7 +792,7 @@ private static DiffBuilder ignoringNonPersistentSshIds(DiffBuilder diffBuilder) private static DiffBuilder selectingEquivalentSvObjects(DiffBuilder diffBuilder) { Map prefixUris = new HashMap<>(2); - prefixUris.put("cim", CIM_16_NAMESPACE); + prefixUris.put("cim", CgmesNamespace.getCim(16)); prefixUris.put("rdf", RDF_NAMESPACE); QName resourceAttribute = new QName(RDF_NAMESPACE, "resource"); ElementSelector byResource = ElementSelectors.byNameAndAttributes(resourceAttribute); diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java index 4b420bfb06c..70e768dd6ea 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java @@ -6,6 +6,7 @@ */ package com.powsybl.cgmes.model; +import java.util.Map; import java.util.Set; import java.util.regex.Pattern; @@ -21,32 +22,66 @@ private CgmesNamespace() { // It is used in this project to explore how to support future CGMES versions // We have sample models in cim14 and we use a different set of queries to obtain data - public static final String CIM_100_NAMESPACE = "http://iec.ch/TC57/CIM100#"; - public static final Pattern CIM_100_PLUS_NAMESPACE_PATTERN = Pattern.compile(".*/CIM[0-9]+#$"); - public static final String CIM_16_NAMESPACE = "http://iec.ch/TC57/2013/CIM-schema-cim16#"; - public static final String CIM_14_NAMESPACE = "http://iec.ch/TC57/2009/CIM-schema-cim14#"; + private static final String CIM_100_NAMESPACE = "http://iec.ch/TC57/CIM100#"; + private static final String CIM_16_NAMESPACE = "http://iec.ch/TC57/2013/CIM-schema-cim16#"; + private static final String CIM_14_NAMESPACE = "http://iec.ch/TC57/2009/CIM-schema-cim14#"; + + private static final Map CIM_NAMESPACES = Map.of( + 14, CIM_14_NAMESPACE, + 16, CIM_16_NAMESPACE, + 100, CIM_100_NAMESPACE); + + private static final Set VALID_CIM_NAMESPACES = Set.of(CIM_14_NAMESPACE, CIM_16_NAMESPACE, CIM_100_NAMESPACE); + private static final Pattern CIM_100_PLUS_NAMESPACE_PATTERN = Pattern.compile(".*/CIM[0-9]+#$"); + public static final String RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; public static final String ENTSOE_NAMESPACE = "http://entsoe.eu/CIM/SchemaExtension/3/1#"; public static final String EU_NAMESPACE = "http://iec.ch/TC57/CIM100-European#"; public static final String MD_NAMESPACE = "http://iec.ch/TC57/61970-552/ModelDescription/1#"; - public static final String EQ_PROFILE = "http://entsoe.eu/CIM/EquipmentCore/3/1"; - public static final String EQ_OPERATION_PROFILE = "http://entsoe.eu/CIM/EquipmentOperation/3/1"; - public static final String TP_PROFILE = "http://entsoe.eu/CIM/Topology/4/1"; - public static final String SV_PROFILE = "http://entsoe.eu/CIM/StateVariables/4/1"; - public static final String SSH_PROFILE = "http://entsoe.eu/CIM/SteadyStateHypothesis/1/1"; + private static final String CIM_16_EQ_PROFILE = "http://entsoe.eu/CIM/EquipmentCore/3/1"; + private static final String CIM_16_EQ_OPERATION_PROFILE = "http://entsoe.eu/CIM/EquipmentOperation/3/1"; + private static final String CIM_16_TP_PROFILE = "http://entsoe.eu/CIM/Topology/4/1"; + private static final String CIM_16_SV_PROFILE = "http://entsoe.eu/CIM/StateVariables/4/1"; + private static final String CIM_16_SSH_PROFILE = "http://entsoe.eu/CIM/SteadyStateHypothesis/1/1"; - public static final Set CIM_NAMESPACES = Set.of(CIM_14_NAMESPACE, CIM_16_NAMESPACE, CIM_100_NAMESPACE); + private static final String CIM_100_EQ_PROFILE = "http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0"; + private static final String CIM_100_EQ_OPERATION_PROFILE = "http://iec.ch/TC57/ns/CIM/Operation-EU/3.0"; + private static final String CIM_100_TP_PROFILE = "http://iec.ch/TC57/ns/CIM/Topology-EU/3.0"; + private static final String CIM_100_SV_PROFILE = "http://iec.ch/TC57/ns/CIM/StateVariables-EU/3.0"; + private static final String CIM_100_SSH_PROFILE = "http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0"; - public static String getCimNamespace(int cimVersion) { - if (cimVersion == 14) { - return CIM_14_NAMESPACE; - } - if (cimVersion == 16) { - return CIM_16_NAMESPACE; + private static final Map> PROFILES = Map.of( + 16, Map.of("EQ", CIM_16_EQ_PROFILE, "EQ_OP", CIM_16_EQ_OPERATION_PROFILE, "SSH", CIM_16_SSH_PROFILE, "SV", CIM_16_SV_PROFILE, "TP", CIM_16_TP_PROFILE), + 100, Map.of("EQ", CIM_100_EQ_PROFILE, "EQ_OP", CIM_100_EQ_OPERATION_PROFILE, "SSH", CIM_100_SSH_PROFILE, "SV", CIM_100_SV_PROFILE, "TP", CIM_100_TP_PROFILE) + ); + + public static boolean isValid(String ns) { + // Until CIM16 the CIM namespace contained the string "CIM-schema-cim#" + // Since CIM100 the namespace seems to follow the pattern "/CIM#" + return VALID_CIM_NAMESPACES.contains(ns) || CIM_100_PLUS_NAMESPACE_PATTERN.matcher(ns).matches(); + } + + public static boolean isValidAny(Set namespaces) { + // FIXME(Luma) This is legacy behaviour, we do not consider CIM14 valid in this check + // But I think we do not need to support 14 separately? + return namespaces.contains(CIM_16_NAMESPACE) || namespaces.contains(CIM_100_NAMESPACE); + } + + public static boolean isValidAny14(Set namespaces) { + return namespaces.contains(CIM_14_NAMESPACE); + } + + public static String getCim(int cimVersion) { + if (CIM_NAMESPACES.containsKey(cimVersion)) { + return CIM_NAMESPACES.get(cimVersion); } - if (cimVersion == 100) { - return CIM_100_NAMESPACE; + throw new AssertionError("Unsupported CIM version " + cimVersion); + } + + public static String getProfile(int cimVersion, String profile) { + if (PROFILES.containsKey(cimVersion)) { + return PROFILES.get(cimVersion).get(profile); } throw new AssertionError("Unsupported CIM version " + cimVersion); } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java index 569d6c3a63f..598fc102128 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java @@ -36,7 +36,7 @@ public boolean exists() { if (!foundNamespaces.contains(RDF_NAMESPACE)) { return false; } - return foundNamespaces.contains(CIM_16_NAMESPACE) || foundNamespaces.contains(CIM_100_NAMESPACE); + return CgmesNamespace.isValidAny(foundNamespaces); } public boolean existsCim14() { @@ -45,9 +45,10 @@ public boolean existsCim14() { if (!foundNamespaces.contains(RDF_NAMESPACE)) { return false; } - if (!foundNamespaces.contains(CIM_14_NAMESPACE)) { + if (!CgmesNamespace.isValidAny14(foundNamespaces)) { return false; } + return names().stream().anyMatch(CgmesSubset.EQUIPMENT::isValidName); } @@ -72,9 +73,7 @@ public Set names() { } private static boolean isCimNamespace(String ns) { - // Until CIM16 the CIM namespace contained the string "CIM-schema-cim#" - // Since CIM100 the namespace seems to follow the pattern "/CIM#" - return CIM_NAMESPACES.contains(ns) || CIM_100_PLUS_NAMESPACE_PATTERN.matcher(ns).matches(); + return CgmesNamespace.isValid(ns); } private boolean containsValidNamespace(String name) { From db99f5b14839c73845703565ad8c1ab827954960 Mon Sep 17 00:00:00 2001 From: Luma Date: Thu, 3 Mar 2022 11:55:17 +0100 Subject: [PATCH 3/9] fix hard-coded path Signed-off-by: Luma --- .../cgmes/conversion/test/export/ExportToCimVersionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java index 5edbadd1404..d15736d3ae4 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java @@ -76,8 +76,8 @@ private void testExportIEEE14Cim14ToCim(int cimVersion, Path tempDir) { } private Path tempDir() { - boolean debug = true; - if (debug) { + boolean localEnvironment = false; + if (localEnvironment) { return Paths.get("/Users/zamarrenolm/work/temp/cgmes3"); } else { return tmpDir; From fbc84f02fd234ff9a130f6372f05b56b6d7d085e Mon Sep 17 00:00:00 2001 From: Luma Date: Thu, 3 Mar 2022 16:21:42 +0100 Subject: [PATCH 4/9] Update model description profiles when export CIM version is changed Signed-off-by: Luma --- .../cgmes/conversion/export/CgmesExportContext.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java index a3f0d470a16..b63d5d50dc0 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java @@ -111,6 +111,11 @@ public ModelDescription setModelingAuthoritySet(String modelingAuthoritySet) { public String getProfile() { return profile; } + + public ModelDescription setProfile(String profile) { + this.profile = profile; + return this; + } } public CgmesExportContext(Network network) { @@ -477,6 +482,10 @@ public int getCimVersion() { public CgmesExportContext setCimVersion(int cimVersion) { this.cimVersion = cimVersion; + eqModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "EQ")); + tpModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "TP")); + svModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SV")); + sshModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SSH")); return this; } From 11f66310c92909c5622646e174073ef261adbfa8 Mon Sep 17 00:00:00 2001 From: Luma Date: Fri, 4 Mar 2022 07:46:49 +0100 Subject: [PATCH 5/9] Not all CIM versions have profiles Signed-off-by: Luma --- .../cgmes/conversion/export/CgmesExportContext.java | 10 ++++++---- .../java/com/powsybl/cgmes/model/CgmesNamespace.java | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java index b63d5d50dc0..e3c5461efdb 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java @@ -482,10 +482,12 @@ public int getCimVersion() { public CgmesExportContext setCimVersion(int cimVersion) { this.cimVersion = cimVersion; - eqModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "EQ")); - tpModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "TP")); - svModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SV")); - sshModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SSH")); + if (CgmesNamespace.hasProfiles(cimVersion)) { + eqModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "EQ")); + tpModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "TP")); + svModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SV")); + sshModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SSH")); + } return this; } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java index 70e768dd6ea..5dc3d828ea4 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java @@ -79,6 +79,10 @@ public static String getCim(int cimVersion) { throw new AssertionError("Unsupported CIM version " + cimVersion); } + public static boolean hasProfiles(int cimVersion) { + return PROFILES.containsKey(cimVersion); + } + public static String getProfile(int cimVersion, String profile) { if (PROFILES.containsKey(cimVersion)) { return PROFILES.get(cimVersion).get(profile); From 681695100c32e43e4b1a84ff33433efecdcb220a Mon Sep 17 00:00:00 2001 From: Luma Date: Fri, 4 Mar 2022 17:03:36 +0100 Subject: [PATCH 6/9] use proper CIM namespace in kind of regulating control and control area Signed-off-by: Luma --- .../cgmes/conversion/export/elements/ControlAreaEq.java | 4 ++-- .../cgmes/conversion/export/elements/RegulatingControlEq.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ControlAreaEq.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ControlAreaEq.java index 490f8b4aaf9..58ae1c2cf3e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ControlAreaEq.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/ControlAreaEq.java @@ -18,7 +18,7 @@ * @author Marcos de Miguel */ public final class ControlAreaEq { - private static final String CONTROL_AREA_TYPE = "http://iec.ch/TC57/2013/CIM-schema-cim16#ControlAreaTypeKind.Interchange"; + private static final String CONTROL_AREA_TYPE = "ControlAreaTypeKind.Interchange"; public static void write(String id, String controlAreaName, String energyIdentificationCodeEIC, String cimNamespace, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement(cimNamespace, "ControlArea"); @@ -30,7 +30,7 @@ public static void write(String id, String controlAreaName, String energyIdentif writer.writeCharacters(energyIdentificationCodeEIC); writer.writeEndElement(); writer.writeEmptyElement(cimNamespace, "ControlArea.type"); - writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, CONTROL_AREA_TYPE); + writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, cimNamespace + CONTROL_AREA_TYPE); writer.writeEndElement(); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/RegulatingControlEq.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/RegulatingControlEq.java index 7700ba29dff..6402baf448e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/RegulatingControlEq.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/elements/RegulatingControlEq.java @@ -18,7 +18,7 @@ */ public final class RegulatingControlEq { - public static final String REGULATING_CONTROL_VOLTAGE = "http://iec.ch/TC57/2013/CIM-schema-cim16#RegulatingControlModeKind.voltage"; + public static final String REGULATING_CONTROL_VOLTAGE = "RegulatingControlModeKind.voltage"; public static void write(String id, String regulatingControlName, String terminalId, String cimNamespace, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement(cimNamespace, "RegulatingControl"); @@ -29,7 +29,7 @@ public static void write(String id, String regulatingControlName, String termina writer.writeEmptyElement(cimNamespace, "RegulatingControl.Terminal"); writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, "#" + terminalId); writer.writeEmptyElement(cimNamespace, "RegulatingControl.mode"); - writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, REGULATING_CONTROL_VOLTAGE); + writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, cimNamespace + REGULATING_CONTROL_VOLTAGE); writer.writeEndElement(); } From dd8a0aa912d31949274ac135bb6a1b10240a40bf Mon Sep 17 00:00:00 2001 From: VEDELAGO MIORA Date: Mon, 28 Mar 2022 17:42:04 +0200 Subject: [PATCH 7/9] Small improvements Signed-off-by: VEDELAGO MIORA --- .../com/powsybl/cgmes/model/CgmesNamespace.java | 12 +++--------- .../powsybl/cgmes/model/CgmesOnDataSource.java | 16 ++++++++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java index 5dc3d828ea4..2755f352488 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java @@ -22,9 +22,9 @@ private CgmesNamespace() { // It is used in this project to explore how to support future CGMES versions // We have sample models in cim14 and we use a different set of queries to obtain data - private static final String CIM_100_NAMESPACE = "http://iec.ch/TC57/CIM100#"; - private static final String CIM_16_NAMESPACE = "http://iec.ch/TC57/2013/CIM-schema-cim16#"; - private static final String CIM_14_NAMESPACE = "http://iec.ch/TC57/2009/CIM-schema-cim14#"; + public static final String CIM_100_NAMESPACE = "http://iec.ch/TC57/CIM100#"; + public static final String CIM_16_NAMESPACE = "http://iec.ch/TC57/2013/CIM-schema-cim16#"; + public static final String CIM_14_NAMESPACE = "http://iec.ch/TC57/2009/CIM-schema-cim14#"; private static final Map CIM_NAMESPACES = Map.of( 14, CIM_14_NAMESPACE, @@ -62,12 +62,6 @@ public static boolean isValid(String ns) { return VALID_CIM_NAMESPACES.contains(ns) || CIM_100_PLUS_NAMESPACE_PATTERN.matcher(ns).matches(); } - public static boolean isValidAny(Set namespaces) { - // FIXME(Luma) This is legacy behaviour, we do not consider CIM14 valid in this check - // But I think we do not need to support 14 separately? - return namespaces.contains(CIM_16_NAMESPACE) || namespaces.contains(CIM_100_NAMESPACE); - } - public static boolean isValidAny14(Set namespaces) { return namespaces.contains(CIM_14_NAMESPACE); } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java index 598fc102128..afed60981d3 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesOnDataSource.java @@ -36,7 +36,9 @@ public boolean exists() { if (!foundNamespaces.contains(RDF_NAMESPACE)) { return false; } - return CgmesNamespace.isValidAny(foundNamespaces); + // FIXME(Luma) This is legacy behaviour, we do not consider CIM14 valid in this check + // But I think we do not need to support 14 separately? + return foundNamespaces.contains(CIM_16_NAMESPACE) || foundNamespaces.contains(CIM_100_NAMESPACE); } public boolean existsCim14() { @@ -45,7 +47,9 @@ public boolean existsCim14() { if (!foundNamespaces.contains(RDF_NAMESPACE)) { return false; } - if (!CgmesNamespace.isValidAny14(foundNamespaces)) { + // FIXME(Luma) This is legacy behaviour, we do not consider CIM14 valid in this check + // But I think we do not need to support 14 separately? + if (!foundNamespaces.contains(CIM_14_NAMESPACE)) { return false; } @@ -72,14 +76,10 @@ public Set names() { } } - private static boolean isCimNamespace(String ns) { - return CgmesNamespace.isValid(ns); - } - private boolean containsValidNamespace(String name) { try (InputStream is = dataSource.newInputStream(name)) { Set ns = NamespaceReader.namespaces1(is); - return ns.contains(RDF_NAMESPACE) && ns.stream().anyMatch(CgmesOnDataSource::isCimNamespace); + return ns.contains(RDF_NAMESPACE) && ns.stream().anyMatch(CgmesNamespace::isValid); } catch (XMLStreamException e) { return false; } catch (IOException x) { @@ -102,7 +102,7 @@ public Set namespaces() { public String cimNamespace() { // If no cim namespace is found, return CIM16 namespace return namespaces().stream() - .filter(CgmesOnDataSource::isCimNamespace) + .filter(CgmesNamespace::isValid) .findFirst() .orElseThrow(() -> new CgmesModelException("CIM Namespace not found")); } From 95c593cb9a5f2354f9c9b6c037093000636fb9fd Mon Sep 17 00:00:00 2001 From: VEDELAGO MIORA Date: Mon, 28 Mar 2022 17:44:25 +0200 Subject: [PATCH 8/9] Small improvements Signed-off-by: VEDELAGO MIORA --- .../src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java index 2755f352488..5fda2d0a1f0 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNamespace.java @@ -62,10 +62,6 @@ public static boolean isValid(String ns) { return VALID_CIM_NAMESPACES.contains(ns) || CIM_100_PLUS_NAMESPACE_PATTERN.matcher(ns).matches(); } - public static boolean isValidAny14(Set namespaces) { - return namespaces.contains(CIM_14_NAMESPACE); - } - public static String getCim(int cimVersion) { if (CIM_NAMESPACES.containsKey(cimVersion)) { return CIM_NAMESPACES.get(cimVersion); From 1cf1a697ecbe9a9a77f52e0c23ca9f5202d1b6ff Mon Sep 17 00:00:00 2001 From: Luma Date: Tue, 29 Mar 2022 11:57:16 +0200 Subject: [PATCH 9/9] Test sample network export to CGMES 3, reimport and check Signed-off-by: Luma --- .../test/export/ExportToCimVersionTest.java | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java index d15736d3ae4..b8b2b83c39c 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportToCimVersionTest.java @@ -21,9 +21,6 @@ import org.junit.Test; import java.io.IOException; - -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Properties; import static org.junit.Assert.assertEquals; @@ -47,40 +44,50 @@ public void testExportDataSourceEmptyBaseName() throws IOException { @Test public void testExportIEEE14Cim14ToCim16() { - testExportIEEE14Cim14ToCim(16, tempDir()); + testExportToCim(ieee14Cim14(), "IEEE14", 16); } @Test public void testExportIEEE14Cim14ToCim100() { // Testing export to CGMES 3 - // FIXME(Luma) verify that namespace in headers are correct - // FIXME(Luma) verify that all classes and attributes are valid against profiles (using CIMdesk) - testExportIEEE14Cim14ToCim(100, tempDir()); + // TODO(Luma) verify that all classes and attributes are valid against profiles (using CIMdesk) + // TODO(Luma) Check mRID is exported + // TODO(Luma) Check GeneratingUnit.initialP (removed in CIM100) + // TODO(Luma) Check the way OperationalLimit TypeName is read + // TODO(Luma) Check OperationalLimit value (renamed to normalValue in CIM100) + Network network = ieee14Cim14(); + assertEquals(14, network.getExtension(CimCharacteristics.class).getCimVersion()); + testExportToCim(network, "IEEE14", 100); } - private void testExportIEEE14Cim14ToCim(int cimVersion, Path tempDir) { + private Network ieee14Cim14() { ReadOnlyDataSource dataSource = Cim14SmallCasesCatalog.ieee14().dataSource(); - Network networkCim14 = new CgmesImport().importData(dataSource, NetworkFactory.findDefault(), null); - CimCharacteristics cim14 = networkCim14.getExtension(CimCharacteristics.class); + return new CgmesImport().importData(dataSource, NetworkFactory.findDefault(), null); + } + private void testExportToCim(Network network, String name, int cimVersion) { + String cimZipFilename = name + "_CIM" + cimVersion; Properties params = new Properties(); params.put(CgmesExport.CIM_VERSION, Integer.toString(cimVersion)); - ZipFileDataSource zip = new ZipFileDataSource(tempDir.resolve("."), "IEEE14_CIM" + cimVersion); - new CgmesExport().export(networkCim14, params, zip); + ZipFileDataSource zip = new ZipFileDataSource(tmpDir.resolve("."), cimZipFilename); + new CgmesExport().export(network, params, zip); - Network networkCimVersion = Importers.loadNetwork(tempDir.resolve("IEEE14_CIM" + cimVersion + ".zip")); + // Reimport and verify contents of Network + Network networkCimVersion = Importers.loadNetwork(tmpDir.resolve(cimZipFilename + ".zip")); CimCharacteristics cim = networkCimVersion.getExtension(CimCharacteristics.class); - assertEquals(14, cim14.getCimVersion()); assertEquals(cimVersion, cim.getCimVersion()); - } - - private Path tempDir() { - boolean localEnvironment = false; - if (localEnvironment) { - return Paths.get("/Users/zamarrenolm/work/temp/cgmes3"); - } else { - return tmpDir; - } + // Initial verification: check that we have the same number of elements in both networks + // TODO(Luma) compare the networks + // If the original was bus-branch (like IEEE14) and the exported is node-breaker at least compare attributes + // or select another network for verification (SmallGrid ?) + assertEquals(network.getSubstationCount(), networkCimVersion.getSubstationCount()); + assertEquals(network.getVoltageLevelCount(), networkCimVersion.getVoltageLevelCount()); + assertEquals(network.getLineCount(), networkCimVersion.getLineCount()); + assertEquals(network.getTwoWindingsTransformerCount(), networkCimVersion.getTwoWindingsTransformerCount()); + assertEquals(network.getThreeWindingsTransformerCount(), networkCimVersion.getThreeWindingsTransformerCount()); + assertEquals(network.getGeneratorCount(), networkCimVersion.getGeneratorCount()); + assertEquals(network.getLoadCount(), networkCimVersion.getLoadCount()); + assertEquals(network.getShuntCompensatorCount(), networkCimVersion.getShuntCompensatorCount()); } }