Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.powsybl.iidm.serde.IidmSerDeConstants.ITESLA_DOMAIN;
import static com.powsybl.iidm.serde.IidmSerDeConstants.POWSYBL_DOMAIN;
import static com.powsybl.iidm.serde.IidmSerDeConstants.*;

/**
* @author Miora Ralambotiana {@literal <miora.ralambotiana at rte-france.com>}
Expand Down Expand Up @@ -82,25 +81,34 @@ public String getXsd(boolean valid) {
return "iidm_equipment_V" + toString("_") + ".xsd";
}

public static IidmVersion fromNamespaceURI(String namespaceURI) {
String version = namespaceURI.substring(namespaceURI.lastIndexOf('/') + 1);
IidmVersion v = of(version, "_");
String namespaceUriV = v.getNamespaceURI();
if (!namespaceURI.equals(namespaceUriV)) {
if (v.compareTo(V_1_7) >= 0 && namespaceURI.equals(v.getNamespaceURI(false))) {
return v;
}
throw new PowsyblException("Namespace " + namespaceURI + " is not supported. " +
"The namespace for IIDM XML version " + v.toString(".") + " is: " + namespaceUriV + ".");
}
return v;
}

public static IidmVersion of(String version, String separator) {
Objects.requireNonNull(version);
return Stream.of(IidmVersion.values())
.filter(v -> version.equals(v.toString(separator)))
.findFirst() // there can only be 0 or exactly 1 match
.orElseThrow(() -> new PowsyblException("Version " + version + " is not supported."));
}

public static int compareVersions(String v1, String v2) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually, we use v1.compareTo(v2) to compare versions. This method may not be needed (and therefore neither parseVersion(...)).

if (v1.isEmpty() || v2.isEmpty()) {
return 0;
}

int[] version1 = parseVersion(v1);
int[] version2 = parseVersion(v2);

if (version1[0] != version2[0]) {
return Integer.compare(version1[0], version2[0]);
}
return Integer.compare(version1[1], version2[1]);
}

private static int[] parseVersion(String v) {
String version = v.startsWith("V_") ? v.substring(2) : v;
String[] parts = version.split("_");
int major = Integer.parseInt(parts[0]);
int minor = Integer.parseInt(parts[1]);
return new int[]{major, minor};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.powsybl.iidm.serde;

import com.google.auto.service.AutoService;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.datasource.ReadOnlyDataSource;
import com.powsybl.commons.xml.XmlUtil;
Expand Down Expand Up @@ -58,32 +59,43 @@ public String getComment() {
}

protected boolean exists(ReadOnlyDataSource dataSource, String ext) throws IOException {
try {
if (ext != null) {
try (InputStream is = dataSource.newInputStream(null, ext)) {
// check the first root element is network and namespace is IIDM
XMLStreamReader xmlsr = getXMLInputFactory().createXMLStreamReader(is);
try {
while (xmlsr.hasNext()) {
int eventType = xmlsr.next();
if (eventType == XMLStreamConstants.START_ELEMENT) {
String name = xmlsr.getLocalName();
String ns = xmlsr.getNamespaceURI();
return NetworkSerDe.NETWORK_ROOT_ELEMENT_NAME.equals(name)
&& (Stream.of(IidmVersion.values()).anyMatch(v -> v.getNamespaceURI().equals(ns))
|| Stream.of(IidmVersion.values()).filter(v -> v.compareTo(IidmVersion.V_1_7) >= 0).anyMatch(v -> v.getNamespaceURI(false).equals(ns)));
}
}
} finally {
cleanClose(xmlsr);
if (ext == null) {
return false;
}

try (InputStream is = dataSource.newInputStream(null, ext)) {
XMLStreamReader xmlsr = getXMLInputFactory().createXMLStreamReader(is);
try {
return isValidNetworkRoot(xmlsr);
} finally {
cleanClose(xmlsr);
}
} catch (XMLStreamException e) {
return false; // not a valid XML file
}
}

private boolean isValidNetworkRoot(XMLStreamReader xmlsr) throws XMLStreamException {
while (xmlsr.hasNext()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment that previously existed was useful:

Suggested change
while (xmlsr.hasNext()) {
// check the first root element is network and namespace is IIDM
while (xmlsr.hasNext()) {

if (xmlsr.next() == XMLStreamConstants.START_ELEMENT) {
String name = xmlsr.getLocalName();
String ns = xmlsr.getNamespaceURI();

if (!ns.isEmpty()) {
String xmlIidmVersion = ns.substring(ns.lastIndexOf('/') + 1);
if (IidmVersion.compareVersions(xmlIidmVersion, CURRENT_IIDM_VERSION.toString()) > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of comparing the strings of the 2 versions, it would be safer to try to load the version corresponding to the namespace, and if it fails to throw the exception with your message (in which you can also add the version that was encountered).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can load the IidmVersion corresponding to a string with IidmVersion.of(String version, String separator).
It throws an exception containing version if no IidmVersion value is found (so the version is not supported). You can just catch this exception and create your exception (with your message untouched) using the caught exception as cause.

throw new PowsyblException("Unsupported IIDM Version (maximum supported version: "
+ CURRENT_IIDM_VERSION.toString(".") + ")");
}
}

return NetworkSerDe.NETWORK_ROOT_ELEMENT_NAME.equals(name)
&& (Stream.of(IidmVersion.values()).anyMatch(v -> v.getNamespaceURI().equals(ns))
|| Stream.of(IidmVersion.values()).filter(v -> v.compareTo(IidmVersion.V_1_7) >= 0)
.anyMatch(v -> v.getNamespaceURI(false).equals(ns)));
}
return false;
} catch (XMLStreamException e) {
// not a valid xml file
return false;
}
return false;
}

private void cleanClose(XMLStreamReader xmlStreamReader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.powsybl.iidm.serde;

import com.google.common.io.ByteStreams;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.datasource.*;
import com.powsybl.commons.report.PowsyblCoreReportResourceBundle;
import com.powsybl.commons.test.PowsyblTestReportResourceBundle;
Expand All @@ -23,6 +24,7 @@
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
Expand Down Expand Up @@ -90,6 +92,19 @@ private void writeNetworkWithComment(String fileName) throws IOException {
}
}

private void writeNetworkUnsupportedIidmVersion(String fileName) throws IOException {
writeNetwork(fileName, unsupportedIidmVersionNamespaceURI(), false);
}

private String unsupportedIidmVersionNamespaceURI() {
String currentIidmVersion = CURRENT_IIDM_VERSION.toString();
String currentIidmNamespaceURI = CURRENT_IIDM_VERSION.getNamespaceURI();
int currentVersionMajor = Integer.parseInt(currentIidmVersion.split("_")[1]);
int currentVersionMinor = Integer.parseInt(currentIidmVersion.split("_")[2]);
String unsupportedIidmVersion = String.format("%d_%d", currentVersionMajor, ++currentVersionMinor);
return currentIidmNamespaceURI.substring(0, currentIidmNamespaceURI.lastIndexOf("/") + 1) + unsupportedIidmVersion;
}

@BeforeEach
public void setUp() throws IOException {
super.setUp();
Expand All @@ -116,6 +131,7 @@ public void setUp() throws IOException {
}
writeNetworkWithComment("/test7.xiidm");
writeNetworkWithExtension("/test8.xiidm", CURRENT_IIDM_VERSION.getNamespaceURI());
writeNetworkUnsupportedIidmVersion("/test9.xiidm");

importer = new XMLImporter();
}
Expand Down Expand Up @@ -154,6 +170,14 @@ void exists() {
assertFalse(importer.exists(new DirectoryDataSource(fileSystem.getPath("/"), "testDummy"))); // namespace URI is not defined
}

@Test
void testUnsupportedIidmVersion() {
Path dir = fileSystem.getPath("/");
ReadOnlyDataSource dataSource = new DirectoryDataSource(dir, "test9");
String expectedError = "Unsupported IIDM Version (maximum supported version: " + CURRENT_IIDM_VERSION.toString(".") + ")";
assertThrows(PowsyblException.class, () -> importer.exists(dataSource), expectedError);
}

@Test
void copy() throws Exception {
importer.copy(new DirectoryDataSource(fileSystem.getPath("/"), "test0"), new DirectoryDataSource(fileSystem.getPath("/"), "test0_copy"));
Expand Down