diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java index f25813fbbc8..df608a0f11b 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java @@ -28,6 +28,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>} @@ -94,4 +96,21 @@ public static Network readCgmesResources(Properties properties, String dir, Stri ReadOnlyDataSource ds = new ResourceDataSource("CGMES input file(s)", new ResourceSet(dir, files)); return Network.read(ds, properties); } + + public static String getFirstMatch(String text, Pattern pattern) { + Matcher matcher = pattern.matcher(text); + if (matcher.find()) { + return matcher.group(1); + } + return null; + } + + public static Set<String> getUniqueMatches(String text, Pattern pattern) { + Set<String> matches = new HashSet<>(); + Matcher matcher = pattern.matcher(text); + while (matcher.find()) { + matches.add(matcher.group(1)); + } + return matches; + } } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/OperationalLimitsGroupTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/OperationalLimitsGroupTest.java index 21b6a67f6e9..e778289b383 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/OperationalLimitsGroupTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/OperationalLimitsGroupTest.java @@ -16,9 +16,9 @@ import java.io.IOException; import java.nio.file.Files; import java.util.*; -import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.powsybl.cgmes.conversion.test.ConversionUtil.getUniqueMatches; import static org.junit.jupiter.api.Assertions.*; /** @@ -65,10 +65,10 @@ void exportSelectedLimitsGroupTest() throws IOException { String exportSelectedLimitsGroupXml = Files.readString(tmpDir.resolve("ExportSelectedLimitsGroup_EQ.xml")); // There is 1 set on side 1 which is selected, and there are 2 sets on side 2 but none of them is selected - assertEquals(1, getOccurrences(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); - assertEquals(3, getOccurrences(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); - assertEquals(0, getOccurrences(exportSelectedLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); - assertEquals(3, getOccurrences(exportSelectedLimitsGroupXml, CURRENT_LIMIT).size()); + assertEquals(1, getUniqueMatches(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); + assertEquals(3, getUniqueMatches(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); + assertEquals(0, getUniqueMatches(exportSelectedLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); + assertEquals(3, getUniqueMatches(exportSelectedLimitsGroupXml, CURRENT_LIMIT).size()); // Manually select one of the limits group on side 2 and export again Line line = network.getLine("Line"); @@ -77,10 +77,10 @@ void exportSelectedLimitsGroupTest() throws IOException { exportSelectedLimitsGroupXml = Files.readString(tmpDir.resolve("ExportSelectedLimitsGroup_EQ.xml")); // That makes 1 set selected on each side = 2 in total - assertEquals(2, getOccurrences(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); - assertEquals(3, getOccurrences(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); - assertEquals(0, getOccurrences(exportSelectedLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); - assertEquals(6, getOccurrences(exportSelectedLimitsGroupXml, CURRENT_LIMIT).size()); + assertEquals(2, getUniqueMatches(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); + assertEquals(3, getUniqueMatches(exportSelectedLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); + assertEquals(0, getUniqueMatches(exportSelectedLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); + assertEquals(6, getUniqueMatches(exportSelectedLimitsGroupXml, CURRENT_LIMIT).size()); } @Test @@ -95,19 +95,10 @@ void exportAllLimitsGroupTest() throws IOException { String exportAllLimitsGroupXml = Files.readString(tmpDir.resolve("ExportAllLimitsGroup_EQ.xml")); // All 3 OperationalLimitsGroup are exported, even though only 2 are selected - assertEquals(3, getOccurrences(exportAllLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); - assertEquals(3, getOccurrences(exportAllLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); - assertEquals(3, getOccurrences(exportAllLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); - assertEquals(9, getOccurrences(exportAllLimitsGroupXml, CURRENT_LIMIT).size()); - } - - private Set<String> getOccurrences(String xml, Pattern pattern) { - Set<String> matches = new HashSet<>(); - Matcher matcher = pattern.matcher(xml); - while (matcher.find()) { - matches.add(matcher.group(1)); - } - return matches; + assertEquals(3, getUniqueMatches(exportAllLimitsGroupXml, OPERATIONAL_LIMIT_SET).size()); + assertEquals(3, getUniqueMatches(exportAllLimitsGroupXml, OPERATIONAL_LIMIT_TYPE).size()); + assertEquals(3, getUniqueMatches(exportAllLimitsGroupXml, ACTIVE_POWER_LIMIT).size()); + assertEquals(9, getUniqueMatches(exportAllLimitsGroupXml, CURRENT_LIMIT).size()); } } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CommonGridModelExportTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CommonGridModelExportTest.java index 26f2917527d..e3d30b1021b 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CommonGridModelExportTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/CommonGridModelExportTest.java @@ -15,7 +15,6 @@ import com.powsybl.cgmes.model.CgmesMetadataModel; import com.powsybl.cgmes.model.CgmesNamespace; import com.powsybl.cgmes.model.CgmesSubset; -import com.powsybl.commons.PowsyblException; import com.powsybl.commons.datasource.DataSource; import com.powsybl.commons.datasource.DirectoryDataSource; import com.powsybl.commons.datasource.MemDataSource; @@ -35,9 +34,9 @@ import java.nio.file.Path; import java.time.ZonedDateTime; import java.util.*; -import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.powsybl.cgmes.conversion.test.ConversionUtil.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -80,8 +79,8 @@ void testIgmExportNoModelsNoPropertiesVersion() throws IOException { String exportedBeSvXml = Files.readString(tmpDir.resolve(basename + "_SV.xml")); // There is no version number for original models, so if exported as IGM they would have version equals to 1 - assertEquals("1", getFirstOccurrence(exportedBeSshXml, REGEX_VERSION)); - assertEquals("1", getFirstOccurrence(exportedBeSvXml, REGEX_VERSION)); + assertEquals("1", getFirstMatch(exportedBeSshXml, REGEX_VERSION)); + assertEquals("1", getFirstMatch(exportedBeSvXml, REGEX_VERSION)); } @Test @@ -99,9 +98,9 @@ void testCgmExportWithModelsVersion() throws IOException { String updatedCgmSvXml = Files.readString(tmpDir.resolve(basename + "_SV.xml")); // Version number should be increased from original models and be the same for all instance files - assertEquals("1", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("1", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("1", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("1", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("1", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("1", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); } @Test @@ -119,20 +118,20 @@ void testCgmExportNoModelsNoProperties() throws IOException { String updatedCgmSvXml = Files.readString(tmpDir.resolve(basename + "_SV.xml")); // Scenario time should be the same for all models - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedBeSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedNlSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedCgmSvXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedBeSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedNlSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedCgmSvXml, REGEX_SCENARIO_TIME)); // Description should be the default one - assertEquals("SSH Model", getFirstOccurrence(updatedBeSshXml, REGEX_DESCRIPTION)); - assertEquals("SSH Model", getFirstOccurrence(updatedNlSshXml, REGEX_DESCRIPTION)); - assertEquals("SV Model", getFirstOccurrence(updatedCgmSvXml, REGEX_DESCRIPTION)); + assertEquals("SSH Model", getFirstMatch(updatedBeSshXml, REGEX_DESCRIPTION)); + assertEquals("SSH Model", getFirstMatch(updatedNlSshXml, REGEX_DESCRIPTION)); + assertEquals("SV Model", getFirstMatch(updatedCgmSvXml, REGEX_DESCRIPTION)); // There is no version number for original models, so if exported as IGM they would have version equals to 1 // Version number for updated models is increased by 1, so it equals to 2 in the end - assertEquals("2", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("2", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("2", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); // The updated CGM SV should depend on the updated IGMs SSH and on the original IGMs TP // Here the version number part of the id 1 for original models and 2 for updated ones @@ -143,27 +142,27 @@ void testCgmExportNoModelsNoProperties() throws IOException { String originalBeTpBdId = "urn:uuid:Network_BE_N_TOPOLOGY_BOUNDARY_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlTpBdId = "urn:uuid:Network_NL_N_TOPOLOGY_BOUNDARY_2021-02-03T04:30:00Z_1_1D__FM"; Set<String> expectedDependencies = Set.of(updatedBeSshId, updatedNlSshId, originalBeTpId, originalNlTpId, originalBeTpBdId, originalNlTpBdId); - assertEquals(expectedDependencies, getOccurrences(updatedCgmSvXml, REGEX_DEPENDENT_ON)); + assertEquals(expectedDependencies, getUniqueMatches(updatedCgmSvXml, REGEX_DEPENDENT_ON)); // Each updated IGM SSH should supersede the original one and depend on the original EQ String originalBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; String originalBeEqId = "urn:uuid:Network_BE_N_EQUIPMENT_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlSshId = "urn:uuid:Network_NL_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlEqId = "urn:uuid:Network_NL_N_EQUIPMENT_2021-02-03T04:30:00Z_1_1D__FM"; - assertEquals(originalBeSshId, getFirstOccurrence(updatedBeSshXml, REGEX_SUPERSEDES)); - assertEquals(originalBeEqId, getFirstOccurrence(updatedBeSshXml, REGEX_DEPENDENT_ON)); - assertEquals(originalNlSshId, getFirstOccurrence(updatedNlSshXml, REGEX_SUPERSEDES)); - assertEquals(originalNlEqId, getFirstOccurrence(updatedNlSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalBeSshId, getFirstMatch(updatedBeSshXml, REGEX_SUPERSEDES)); + assertEquals(originalBeEqId, getFirstMatch(updatedBeSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalNlSshId, getFirstMatch(updatedNlSshXml, REGEX_SUPERSEDES)); + assertEquals(originalNlEqId, getFirstMatch(updatedNlSshXml, REGEX_DEPENDENT_ON)); // Profiles should be consistent with the instance files - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedBeSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedNlSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstOccurrence(updatedCgmSvXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedBeSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedNlSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstMatch(updatedCgmSvXml, REGEX_PROFILE)); // All MAS should be equal to the default one since none has been provided - assertEquals("powsybl.org", getFirstOccurrence(updatedBeSshXml, REGEX_MAS)); - assertEquals("powsybl.org", getFirstOccurrence(updatedNlSshXml, REGEX_MAS)); - assertEquals("powsybl.org", getFirstOccurrence(updatedCgmSvXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedBeSshXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedNlSshXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedCgmSvXml, REGEX_MAS)); } @Test @@ -182,19 +181,19 @@ void testCgmExportWithModelsForSubnetworks() throws IOException { String updatedCgmSvXml = Files.readString(tmpDir.resolve(basename + "_SV.xml")); // Scenario time should be the same for all models - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedBeSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedNlSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedCgmSvXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedBeSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedNlSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedCgmSvXml, REGEX_SCENARIO_TIME)); // IGM descriptions should be the ones provided in subnetwork models, CGM description should be the default one - assertEquals("BE network description", getFirstOccurrence(updatedBeSshXml, REGEX_DESCRIPTION)); - assertEquals("NL network description", getFirstOccurrence(updatedNlSshXml, REGEX_DESCRIPTION)); - assertEquals("SV Model", getFirstOccurrence(updatedCgmSvXml, REGEX_DESCRIPTION)); + assertEquals("BE network description", getFirstMatch(updatedBeSshXml, REGEX_DESCRIPTION)); + assertEquals("NL network description", getFirstMatch(updatedNlSshXml, REGEX_DESCRIPTION)); + assertEquals("SV Model", getFirstMatch(updatedCgmSvXml, REGEX_DESCRIPTION)); // Version number should be increased from original models and be the same for all instance files - assertEquals("2", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("2", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("2", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("2", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); // The updated CGM SV should depend on the updated IGMs SSH and on the original IGMs TP String updatedBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_2_1D__FM"; @@ -203,25 +202,25 @@ void testCgmExportWithModelsForSubnetworks() throws IOException { String originalNlTpId = "urn:uuid:Network_NL_N_TOPOLOGY_2021-02-03T04:30:00Z_1_1D__FM"; String originalTpBdId = "Common TP_BD model ID"; Set<String> expectedDependencies = Set.of(updatedBeSshId, updatedNlSshId, originalBeTpId, originalNlTpId, originalTpBdId); - assertEquals(expectedDependencies, getOccurrences(updatedCgmSvXml, REGEX_DEPENDENT_ON)); + assertEquals(expectedDependencies, getUniqueMatches(updatedCgmSvXml, REGEX_DEPENDENT_ON)); // Each updated IGM SSH should supersede the original one and depend on the original EQ String originalBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlSshId = "urn:uuid:Network_NL_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; - assertEquals(originalBeSshId, getFirstOccurrence(updatedBeSshXml, REGEX_SUPERSEDES)); - assertEquals(originalNlSshId, getFirstOccurrence(updatedNlSshXml, REGEX_SUPERSEDES)); - assertEquals(Set.of("BE EQ model ID"), getOccurrences(updatedBeSshXml, REGEX_DEPENDENT_ON)); - assertEquals(Set.of("NL EQ model ID"), getOccurrences(updatedNlSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalBeSshId, getFirstMatch(updatedBeSshXml, REGEX_SUPERSEDES)); + assertEquals(originalNlSshId, getFirstMatch(updatedNlSshXml, REGEX_SUPERSEDES)); + assertEquals(Set.of("BE EQ model ID"), getUniqueMatches(updatedBeSshXml, REGEX_DEPENDENT_ON)); + assertEquals(Set.of("NL EQ model ID"), getUniqueMatches(updatedNlSshXml, REGEX_DEPENDENT_ON)); // Profiles should be consistent with the instance files - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedBeSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedNlSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstOccurrence(updatedCgmSvXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedBeSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedNlSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstMatch(updatedCgmSvXml, REGEX_PROFILE)); // IGM MAS should be the ones provided in subnetwork models, CGM MAS should be the default one - assertEquals("http://elia.be/CGMES/2.4.15", getFirstOccurrence(updatedBeSshXml, REGEX_MAS)); - assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstOccurrence(updatedNlSshXml, REGEX_MAS)); - assertEquals("powsybl.org", getFirstOccurrence(updatedCgmSvXml, REGEX_MAS)); + assertEquals("http://elia.be/CGMES/2.4.15", getFirstMatch(updatedBeSshXml, REGEX_MAS)); + assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstMatch(updatedNlSshXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedCgmSvXml, REGEX_MAS)); } @Test @@ -242,20 +241,20 @@ void testCgmExportWithModelsForAllNetworks() throws IOException { // The main network has a different scenario time than the subnetworks // All updated models should get that scenario time - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedBeSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedNlSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedCgmSvXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedBeSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedNlSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedCgmSvXml, REGEX_SCENARIO_TIME)); // IGM descriptions should be the ones provided in subnetwork models, CGM description should be the one provided in main network model - assertEquals("BE network description", getFirstOccurrence(updatedBeSshXml, REGEX_DESCRIPTION)); - assertEquals("NL network description", getFirstOccurrence(updatedNlSshXml, REGEX_DESCRIPTION)); - assertEquals("Merged network description", getFirstOccurrence(updatedCgmSvXml, REGEX_DESCRIPTION)); + assertEquals("BE network description", getFirstMatch(updatedBeSshXml, REGEX_DESCRIPTION)); + assertEquals("NL network description", getFirstMatch(updatedNlSshXml, REGEX_DESCRIPTION)); + assertEquals("Merged network description", getFirstMatch(updatedCgmSvXml, REGEX_DESCRIPTION)); // The main network has a different version number (3) than the subnetworks (1) // Updated models should use next version taking into account the max version number of inputs (next version is 4) - assertEquals("4", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); // The updated CGM SV should depend on the updated IGMs SSH and on the original IGMs TP // The model of the main network brings an additional dependency @@ -267,27 +266,27 @@ void testCgmExportWithModelsForAllNetworks() throws IOException { String additionalDependency = "Additional dependency"; Set<String> expectedDependencies = Set.of(updatedBeSshId, updatedNlSshId, originalBeTpId, originalNlTpId, originalTpBdId, additionalDependency); - assertEquals(expectedDependencies, getOccurrences(updatedCgmSvXml, REGEX_DEPENDENT_ON)); + assertEquals(expectedDependencies, getUniqueMatches(updatedCgmSvXml, REGEX_DEPENDENT_ON)); // Each updated IGM SSH should supersede the original one and depend on the original EQ String originalBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2022-03-04T05:30:00Z_1_1D__FM"; String originalNlSshId = "urn:uuid:Network_NL_N_STEADY_STATE_HYPOTHESIS_2022-03-04T05:30:00Z_1_1D__FM"; - assertEquals(originalBeSshId, getFirstOccurrence(updatedBeSshXml, REGEX_SUPERSEDES)); - assertEquals(originalNlSshId, getFirstOccurrence(updatedNlSshXml, REGEX_SUPERSEDES)); - assertEquals(Set.of("BE EQ model ID"), getOccurrences(updatedBeSshXml, REGEX_DEPENDENT_ON)); - assertEquals(Set.of("NL EQ model ID"), getOccurrences(updatedNlSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalBeSshId, getFirstMatch(updatedBeSshXml, REGEX_SUPERSEDES)); + assertEquals(originalNlSshId, getFirstMatch(updatedNlSshXml, REGEX_SUPERSEDES)); + assertEquals(Set.of("BE EQ model ID"), getUniqueMatches(updatedBeSshXml, REGEX_DEPENDENT_ON)); + assertEquals(Set.of("NL EQ model ID"), getUniqueMatches(updatedNlSshXml, REGEX_DEPENDENT_ON)); // Profiles should be consistent with the instance files // The model of the main network brings an additional profile - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedBeSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedNlSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedBeSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedNlSshXml, REGEX_PROFILE)); Set<String> expectedProfiles = Set.of("Additional profile", "http://entsoe.eu/CIM/StateVariables/4/1"); - assertEquals(expectedProfiles, getOccurrences(updatedCgmSvXml, REGEX_PROFILE)); + assertEquals(expectedProfiles, getUniqueMatches(updatedCgmSvXml, REGEX_PROFILE)); // IGM MAS should be the ones provided in subnetwork models, CGM MAS should be the one provided in main network model - assertEquals("http://elia.be/CGMES/2.4.15", getFirstOccurrence(updatedBeSshXml, REGEX_MAS)); - assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstOccurrence(updatedNlSshXml, REGEX_MAS)); - assertEquals("Modeling Authority", getFirstOccurrence(updatedCgmSvXml, REGEX_MAS)); + assertEquals("http://elia.be/CGMES/2.4.15", getFirstMatch(updatedBeSshXml, REGEX_MAS)); + assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstMatch(updatedNlSshXml, REGEX_MAS)); + assertEquals("Modeling Authority", getFirstMatch(updatedCgmSvXml, REGEX_MAS)); } @Test @@ -309,19 +308,19 @@ void testCgmExportWithProperties() throws IOException { String updatedCgmSvXml = Files.readString(tmpDir.resolve(basename + "_SV.xml")); // Scenario time should be the same for all models - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedBeSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedNlSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2021-02-03T04:30:00Z", getFirstOccurrence(updatedCgmSvXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedBeSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedNlSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2021-02-03T04:30:00Z", getFirstMatch(updatedCgmSvXml, REGEX_SCENARIO_TIME)); // Description should be the one provided as parameter and be the same for all instance files - assertEquals("Common Grid Model export", getFirstOccurrence(updatedBeSshXml, REGEX_DESCRIPTION)); - assertEquals("Common Grid Model export", getFirstOccurrence(updatedNlSshXml, REGEX_DESCRIPTION)); - assertEquals("Common Grid Model export", getFirstOccurrence(updatedCgmSvXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedBeSshXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedNlSshXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedCgmSvXml, REGEX_DESCRIPTION)); // Version number should be the one provided as parameter and be the same for all instance files - assertEquals("4", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); // The updated CGM SV should depend on the updated IGMs SSH and on the original IGMs TP String updatedBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_4_1D__FM"; @@ -330,27 +329,27 @@ void testCgmExportWithProperties() throws IOException { String originalNlTpId = "urn:uuid:Network_NL_N_TOPOLOGY_2021-02-03T04:30:00Z_1_1D__FM"; String originalTpBdId = "ENTSOE TP_BD model ID"; Set<String> expectedDependencies = Set.of(updatedBeSshId, updatedNlSshId, originalBeTpId, originalNlTpId, originalTpBdId); - assertEquals(expectedDependencies, getOccurrences(updatedCgmSvXml, REGEX_DEPENDENT_ON)); + assertEquals(expectedDependencies, getUniqueMatches(updatedCgmSvXml, REGEX_DEPENDENT_ON)); // Each updated IGM SSH should supersede the original one and depend on the original EQ String originalBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; String originalBeEqId = "urn:uuid:Network_BE_N_EQUIPMENT_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlSshId = "urn:uuid:Network_NL_N_STEADY_STATE_HYPOTHESIS_2021-02-03T04:30:00Z_1_1D__FM"; String originalNlEqId = "urn:uuid:Network_NL_N_EQUIPMENT_2021-02-03T04:30:00Z_1_1D__FM"; - assertEquals(originalBeSshId, getFirstOccurrence(updatedBeSshXml, REGEX_SUPERSEDES)); - assertEquals(originalBeEqId, getFirstOccurrence(updatedBeSshXml, REGEX_DEPENDENT_ON)); - assertEquals(originalNlSshId, getFirstOccurrence(updatedNlSshXml, REGEX_SUPERSEDES)); - assertEquals(originalNlEqId, getFirstOccurrence(updatedNlSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalBeSshId, getFirstMatch(updatedBeSshXml, REGEX_SUPERSEDES)); + assertEquals(originalBeEqId, getFirstMatch(updatedBeSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalNlSshId, getFirstMatch(updatedNlSshXml, REGEX_SUPERSEDES)); + assertEquals(originalNlEqId, getFirstMatch(updatedNlSshXml, REGEX_DEPENDENT_ON)); // Profiles should be consistent with the instance files - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedBeSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedNlSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstOccurrence(updatedCgmSvXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedBeSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedNlSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/StateVariables/4/1", getFirstMatch(updatedCgmSvXml, REGEX_PROFILE)); // IGM MAS should be the default ones, CGM MAS should be the one provided as parameter - assertEquals("powsybl.org", getFirstOccurrence(updatedBeSshXml, REGEX_MAS)); - assertEquals("powsybl.org", getFirstOccurrence(updatedNlSshXml, REGEX_MAS)); - assertEquals("Regional Coordination Center", getFirstOccurrence(updatedCgmSvXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedBeSshXml, REGEX_MAS)); + assertEquals("powsybl.org", getFirstMatch(updatedNlSshXml, REGEX_MAS)); + assertEquals("Regional Coordination Center", getFirstMatch(updatedCgmSvXml, REGEX_MAS)); } @Test @@ -375,19 +374,19 @@ void testCgmExportWithModelsAndProperties() throws IOException { // The main network has a different scenario time than the subnetworks // All updated models should get that scenario time - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedBeSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedNlSshXml, REGEX_SCENARIO_TIME)); - assertEquals("2022-03-04T05:30:00Z", getFirstOccurrence(updatedCgmSvXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedBeSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedNlSshXml, REGEX_SCENARIO_TIME)); + assertEquals("2022-03-04T05:30:00Z", getFirstMatch(updatedCgmSvXml, REGEX_SCENARIO_TIME)); // Both the models and a property define the description. The property should prevail. - assertEquals("Common Grid Model export", getFirstOccurrence(updatedBeSshXml, REGEX_DESCRIPTION)); - assertEquals("Common Grid Model export", getFirstOccurrence(updatedNlSshXml, REGEX_DESCRIPTION)); - assertEquals("Common Grid Model export", getFirstOccurrence(updatedCgmSvXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedBeSshXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedNlSshXml, REGEX_DESCRIPTION)); + assertEquals("Common Grid Model export", getFirstMatch(updatedCgmSvXml, REGEX_DESCRIPTION)); // Both the models and a property define the version number. The property should prevail. - assertEquals("4", getFirstOccurrence(updatedBeSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedNlSshXml, REGEX_VERSION)); - assertEquals("4", getFirstOccurrence(updatedCgmSvXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedBeSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedNlSshXml, REGEX_VERSION)); + assertEquals("4", getFirstMatch(updatedCgmSvXml, REGEX_VERSION)); // The updated CGM SV should depend on the updated IGMs SSH and on the original IGMs TP // The model of the main network brings an additional dependency @@ -399,26 +398,26 @@ void testCgmExportWithModelsAndProperties() throws IOException { String additionalDependency = "Additional dependency"; Set<String> expectedDependencies = Set.of(updatedBeSshId, updatedNlSshId, originalBeTpId, originalNlTpId, originalTpBdId, additionalDependency); - assertEquals(expectedDependencies, getOccurrences(updatedCgmSvXml, REGEX_DEPENDENT_ON)); + assertEquals(expectedDependencies, getUniqueMatches(updatedCgmSvXml, REGEX_DEPENDENT_ON)); // Each updated IGM SSH should supersede the original one and depend on the original EQ String originalBeSshId = "urn:uuid:Network_BE_N_STEADY_STATE_HYPOTHESIS_2022-03-04T05:30:00Z_1_1D__FM"; String originalNlSshId = "urn:uuid:Network_NL_N_STEADY_STATE_HYPOTHESIS_2022-03-04T05:30:00Z_1_1D__FM"; - assertEquals(originalBeSshId, getFirstOccurrence(updatedBeSshXml, REGEX_SUPERSEDES)); - assertEquals(originalNlSshId, getFirstOccurrence(updatedNlSshXml, REGEX_SUPERSEDES)); - assertEquals(Set.of("BE EQ model ID"), getOccurrences(updatedBeSshXml, REGEX_DEPENDENT_ON)); - assertEquals(Set.of("NL EQ model ID"), getOccurrences(updatedNlSshXml, REGEX_DEPENDENT_ON)); + assertEquals(originalBeSshId, getFirstMatch(updatedBeSshXml, REGEX_SUPERSEDES)); + assertEquals(originalNlSshId, getFirstMatch(updatedNlSshXml, REGEX_SUPERSEDES)); + assertEquals(Set.of("BE EQ model ID"), getUniqueMatches(updatedBeSshXml, REGEX_DEPENDENT_ON)); + assertEquals(Set.of("NL EQ model ID"), getUniqueMatches(updatedNlSshXml, REGEX_DEPENDENT_ON)); // Profiles should be consistent with the instance files, CGM SV has an additional profile - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedBeSshXml, REGEX_PROFILE)); - assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstOccurrence(updatedNlSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedBeSshXml, REGEX_PROFILE)); + assertEquals("http://entsoe.eu/CIM/SteadyStateHypothesis/1/1", getFirstMatch(updatedNlSshXml, REGEX_PROFILE)); Set<String> expectedProfiles = Set.of("Additional profile", "http://entsoe.eu/CIM/StateVariables/4/1"); - assertEquals(expectedProfiles, getOccurrences(updatedCgmSvXml, REGEX_PROFILE)); + assertEquals(expectedProfiles, getUniqueMatches(updatedCgmSvXml, REGEX_PROFILE)); // Both the model and a property define the main network MAS. The property should prevail. - assertEquals("http://elia.be/CGMES/2.4.15", getFirstOccurrence(updatedBeSshXml, REGEX_MAS)); - assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstOccurrence(updatedNlSshXml, REGEX_MAS)); - assertEquals("Regional Coordination Center", getFirstOccurrence(updatedCgmSvXml, REGEX_MAS)); + assertEquals("http://elia.be/CGMES/2.4.15", getFirstMatch(updatedBeSshXml, REGEX_MAS)); + assertEquals("http://tennet.nl/CGMES/2.4.15", getFirstMatch(updatedNlSshXml, REGEX_MAS)); + assertEquals("Regional Coordination Center", getFirstMatch(updatedCgmSvXml, REGEX_MAS)); } @Test @@ -569,8 +568,8 @@ void testFaraoUseCaseManualExport() throws IOException { assertEquals(expectedOutputVersion, sshVersionInOutput); String outputSshXml = Files.readString(tmpFolder.resolve(filenameFromCgmesExport)); - assertEquals(Set.of("myDependency"), getOccurrences(outputSshXml, REGEX_DEPENDENT_ON)); - assertEquals(Set.of("mySupersede"), getOccurrences(outputSshXml, REGEX_SUPERSEDES)); + assertEquals(Set.of("myDependency"), getUniqueMatches(outputSshXml, REGEX_DEPENDENT_ON)); + assertEquals(Set.of("mySupersede"), getUniqueMatches(outputSshXml, REGEX_SUPERSEDES)); } String filenameFromCgmesExport = basename + "_SV.xml"; // We read it from inside the SV file ... @@ -578,7 +577,7 @@ void testFaraoUseCaseManualExport() throws IOException { assertEquals(expectedOutputVersion, svVersionInOutput); // Check the dependencies String outputSvXml = Files.readString(tmpFolder.resolve(filenameFromCgmesExport)); - assertEquals(Set.of("mySvDependency1", "mySvDependency2"), getOccurrences(outputSvXml, REGEX_DEPENDENT_ON)); + assertEquals(Set.of("mySvDependency1", "mySvDependency2"), getUniqueMatches(outputSvXml, REGEX_DEPENDENT_ON)); } private static final Map<Country, String> TSO_BY_COUNTRY = Map.of( @@ -729,21 +728,4 @@ private void addModelForNetwork(Network network, int version) { .add(); } - private String getFirstOccurrence(String xml, Pattern pattern) { - Matcher matcher = pattern.matcher(xml); - if (matcher.find()) { - return matcher.group(1); - } - throw new PowsyblException("Pattern not found " + pattern); - } - - private Set<String> getOccurrences(String xml, Pattern pattern) { - Set<String> matches = new HashSet<>(); - Matcher matcher = pattern.matcher(xml); - while (matcher.find()) { - matches.add(matcher.group(1)); - } - return matches; - } - }