Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 @@ -83,6 +82,15 @@ public String getXsd(boolean valid) {
return "iidm_equipment_V" + toString("_") + ".xsd";
}

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("IIDM Version " + version + " is not supported. Max supported version: "
+ CURRENT_IIDM_VERSION.toString(separator)));
}

public static IidmVersion fromNamespaceURI(String namespaceURI) {
String version = namespaceURI.substring(namespaceURI.lastIndexOf('/') + 1);
IidmVersion v = of(version, "_");
Expand All @@ -97,11 +105,4 @@ public static IidmVersion fromNamespaceURI(String namespaceURI) {
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."));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,73 @@ 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 (!NetworkSerDe.NETWORK_ROOT_ELEMENT_NAME.equals(name) || ns.isEmpty()) {
return false;
}

String currentPrefix = extractPrefix(ns);
if (isValidPrefix(currentPrefix)) {
String version = extractVersion(ns);
if (!version.isEmpty()) {
// If it is not supported, this will throw an exception giving details on the encountered version
// and the maximum supported version.
IidmVersion.of(version, "_");
return isValidNamespace(ns);
}
}
}
return false;
} catch (XMLStreamException e) {
// not a valid xml file
return false;
}
return false;
}

private String extractPrefix(String namespace) {
int lastSlash = namespace.lastIndexOf('/');
return (lastSlash > 0) ? namespace.substring(0, lastSlash) : namespace;
}

private String extractVersion(String namespace) {
int lastSlash = namespace.lastIndexOf('/');
return (lastSlash >= 0 && lastSlash < namespace.length() - 1) ? namespace.substring(lastSlash + 1) : "";
}

private boolean isValidPrefix(String prefix) {
return Stream.of(IidmVersion.values())
.map(v -> extractPrefix(v.getNamespaceURI(true)))
.anyMatch(prefix::equals)
|| Stream.of(IidmVersion.values())
.filter(v -> v.compareTo(IidmVersion.V_1_7) >= 0)
.map(v -> extractPrefix(v.getNamespaceURI(false)))
.anyMatch(prefix::equals);
}

private boolean isValidNamespace(String ns) {
return 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));
}

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,22 @@ private void writeNetworkWithComment(String fileName) throws IOException {
}
}

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

private static String unsupportedIidmVersion() {
String[] currentIidmVersionSplit = CURRENT_IIDM_VERSION.toString().split("_");
int unsupportedIidmVersionMajor = Integer.parseInt(currentIidmVersionSplit[1]);
int unsupportedIidmVersionMinor = Integer.parseInt(currentIidmVersionSplit[2]) + 1;
return String.format("%d.%d", unsupportedIidmVersionMajor, unsupportedIidmVersionMinor);
}

private String unsupportedIidmVersionNamespaceURI() {
String currentIidmNamespaceURI = CURRENT_IIDM_VERSION.getNamespaceURI();
return currentIidmNamespaceURI.substring(0, currentIidmNamespaceURI.lastIndexOf("/") + 1) + unsupportedIidmVersion();
}

@BeforeEach
public void setUp() throws IOException {
super.setUp();
Expand All @@ -116,6 +134,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 +173,15 @@ 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 = "IIDM Version " + unsupportedIidmVersion() + "is not supported. Max 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