Skip to content

Commit ce3249f

Browse files
committed
Add version enums to versionable extension SerDe
Signed-off-by: Florian Dupuy <[email protected]>
1 parent 3f7cfc8 commit ce3249f

12 files changed

+468
-472
lines changed

iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/NetworkSerDe.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private static boolean canTheExtensionBeWritten(ExtensionSerDe extensionSerDe, I
232232
return false;
233233
}
234234
boolean versionExist = true;
235-
if (extensionSerDe instanceof AbstractVersionableNetworkExtensionSerDe<?, ?> networkExtensionSerializer) {
235+
if (extensionSerDe instanceof AbstractVersionableNetworkExtensionSerDe<?, ?, ?> networkExtensionSerializer) {
236236
versionExist = networkExtensionSerializer.versionExists(version);
237237
}
238238
if (!versionExist) {
@@ -324,10 +324,10 @@ private static Map<String, String> getExtensionVersions(Network n, ExportOptions
324324

325325
private static String getExtensionVersion(ExtensionSerDe<?, ?> extensionSerDe, ExportOptions options) {
326326
Optional<String> specifiedVersion = options.getExtensionVersion(extensionSerDe.getExtensionName());
327-
if (extensionSerDe instanceof AbstractVersionableNetworkExtensionSerDe<?, ?> versionable) {
327+
if (extensionSerDe instanceof AbstractVersionableNetworkExtensionSerDe<?, ?, ?> versionable) {
328328
return specifiedVersion
329329
.filter(v -> versionable.checkWritingCompatibility(v, options.getVersion()))
330-
.orElseGet(() -> versionable.getVersion(options.getVersion()));
330+
.orElseGet(() -> versionable.getVersion(options.getVersion()).getVersionString());
331331
} else {
332332
return specifiedVersion.orElseGet(extensionSerDe::getVersion);
333333
}

iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/AbstractVersionableNetworkExtensionSerDe.java

+94-71
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,40 @@
77
*/
88
package com.powsybl.iidm.serde.extensions;
99

10-
import com.google.common.collect.BiMap;
11-
import com.google.common.collect.HashBiMap;
12-
import com.google.common.collect.ImmutableSortedSet;
1310
import com.powsybl.commons.PowsyblException;
1411
import com.powsybl.commons.extensions.Extendable;
1512
import com.powsybl.commons.extensions.Extension;
1613
import com.powsybl.commons.extensions.ExtensionSerDe;
14+
import com.powsybl.commons.io.DeserializerContext;
15+
import com.powsybl.commons.io.SerializerContext;
1716
import com.powsybl.iidm.serde.IidmSerDeConstants;
1817
import com.powsybl.iidm.serde.IidmVersion;
1918
import com.powsybl.iidm.serde.NetworkDeserializerContext;
19+
import com.powsybl.iidm.serde.NetworkSerializerContext;
2020

21+
import java.io.InputStream;
2122
import java.util.*;
23+
import java.util.stream.Collectors;
2224
import java.util.stream.Stream;
2325

2426
/**
2527
* @author Miora Ralambotiana {@literal <miora.ralambotiana at rte-france.com>}
2628
*/
27-
public abstract class AbstractVersionableNetworkExtensionSerDe<T extends Extendable, E extends Extension<T>> implements ExtensionSerDe<T, E> {
29+
public abstract class AbstractVersionableNetworkExtensionSerDe<T extends Extendable, E extends Extension<T>, V extends SerDeVersion<V>>
30+
implements ExtensionSerDe<T, E> {
2831

2932
private static final String INCOMPATIBILITY_NETWORK_VERSION_MESSAGE = "IIDM version of network (";
3033

3134
private final String extensionName;
3235
private final Class<? super E> extensionClass;
33-
private final String namespacePrefix;
34-
private final Map<IidmVersion, ImmutableSortedSet<String>> extensionVersions = new EnumMap<>(IidmVersion.class);
35-
private final BiMap<String, String> namespaceUris = HashBiMap.create();
36-
private final Map<String, String> serializationNameByVersion = new HashMap<>();
37-
private final Map<String, String> namespacePrefixByVersion = new HashMap<>();
38-
39-
public record AlternativeSerializationData(String name, List<String> versions, String namespacePrefix) {
40-
public AlternativeSerializationData(String name, List<String> versions) {
41-
this(name, versions, null);
42-
}
43-
}
44-
45-
protected AbstractVersionableNetworkExtensionSerDe(String extensionName, Class<? super E> extensionClass, String namespacePrefix,
46-
Map<IidmVersion, ImmutableSortedSet<String>> extensionVersions, Map<String, String> namespaceUris) {
47-
this(extensionName, extensionClass, namespacePrefix, extensionVersions, namespaceUris, null);
48-
}
36+
private final List<V> versions;
4937

50-
protected AbstractVersionableNetworkExtensionSerDe(String extensionName, Class<? super E> extensionClass, String namespacePrefix,
51-
Map<IidmVersion, ImmutableSortedSet<String>> extensionVersions,
52-
Map<String, String> namespaceUris,
53-
List<AlternativeSerializationData> alternativeSerializationData) {
38+
protected AbstractVersionableNetworkExtensionSerDe(String extensionName, Class<? super E> extensionClass, V[] versions) {
5439
this.extensionName = Objects.requireNonNull(extensionName);
5540
this.extensionClass = Objects.requireNonNull(extensionClass);
56-
this.namespacePrefix = Objects.requireNonNull(namespacePrefix);
57-
this.extensionVersions.putAll(Objects.requireNonNull(extensionVersions));
58-
this.namespaceUris.putAll(Objects.requireNonNull(namespaceUris));
59-
60-
if (alternativeSerializationData != null) {
61-
Set<String> names = new HashSet<>();
62-
for (AlternativeSerializationData data : alternativeSerializationData) {
63-
if (!names.add(data.name())) {
64-
throw new IllegalArgumentException("Duplicate alternative serialization name: " + data.name());
65-
}
66-
data.versions().forEach(version -> {
67-
this.serializationNameByVersion.put(version, data.name());
68-
if (data.namespacePrefix() != null) {
69-
this.namespacePrefixByVersion.put(version, data.namespacePrefix());
70-
}
71-
});
72-
}
73-
}
41+
this.versions = Arrays.stream(Objects.requireNonNull(versions))
42+
.sorted(Comparator.comparing(SerDeVersion::getVersionNumbers))
43+
.toList();
7444
}
7545

7646
@Override
@@ -80,14 +50,12 @@ public String getExtensionName() {
8050

8151
@Override
8252
public String getSerializationName(String extensionVersion) {
83-
return serializationNameByVersion.getOrDefault(extensionVersion, extensionName);
53+
return versionOf(extensionVersion).getSerializationName();
8454
}
8555

8656
@Override
8757
public Set<String> getSerializationNames() {
88-
Set<String> names = new HashSet<>(serializationNameByVersion.values());
89-
names.add(extensionName);
90-
return names;
58+
return versions.stream().map(SerDeVersion::getSerializationName).collect(Collectors.toUnmodifiableSet());
9159
}
9260

9361
@Override
@@ -107,83 +75,138 @@ public String getNamespaceUri() {
10775

10876
@Override
10977
public Stream<String> getNamespaceUriStream() {
110-
return namespaceUris.values().stream().distinct();
78+
return versions.stream().map(SerDeVersion::getNamespaceUri);
11179
}
11280

11381
@Override
11482
public String getNamespaceUri(String extensionVersion) {
115-
return Optional.ofNullable(namespaceUris.get(extensionVersion))
116-
.orElseThrow(() -> new PowsyblException("Namespace URI null for " + getExtensionName() +
117-
" extension's version " + extensionVersion));
83+
return versionOf(extensionVersion, true).getNamespaceUri();
11884
}
11985

12086
@Override
12187
public String getVersion() {
122-
return getVersion(IidmSerDeConstants.CURRENT_IIDM_VERSION);
88+
return getVersion(IidmSerDeConstants.CURRENT_IIDM_VERSION).getVersionString();
12389
}
12490

12591
public boolean versionExists(IidmVersion networkVersion) {
126-
return extensionVersions.containsKey(networkVersion);
92+
return versions.stream().anyMatch(version -> version.supports(networkVersion));
12793
}
12894

12995
/**
130-
* Get the oldest version of an extension working with a network version.
96+
* Get the greatest version of an extension working with a network version.
13197
*/
132-
public String getVersion(IidmVersion networkVersion) {
133-
return extensionVersions.get(networkVersion).last();
98+
public V getVersion(IidmVersion networkVersion) {
99+
// We should return the default version even if it is not the greatest in SemVer terms
100+
V defaultVersion = getDefaultVersion();
101+
if (defaultVersion.supports(networkVersion)) {
102+
return defaultVersion;
103+
}
104+
for (int i = versions.size() - 1; i >= 0; i--) {
105+
V v = versions.get(i);
106+
if (v.supports(networkVersion)) {
107+
return v;
108+
}
109+
}
110+
throw new PowsyblException("IIDM version " + networkVersion + " is not supported by " + extensionName + " extension");
134111
}
135112

136113
@Override
137114
public String getVersion(String namespaceUri) {
138-
return Optional.ofNullable(namespaceUris.inverse().get(namespaceUri))
115+
return versions.stream()
116+
.filter(version -> version.getNamespaceUri().equals(namespaceUri))
117+
.map(SerDeVersion::getVersionString)
118+
.findFirst()
139119
.orElseThrow(() -> new PowsyblException("The namespace URI " + namespaceUri + " of the " + extensionName + " extension is not supported."));
140120
}
141121

142122
@Override
143123
public Set<String> getVersions() {
144-
return namespaceUris.keySet();
124+
return versions.stream().map(SerDeVersion::getVersionString).collect(Collectors.toUnmodifiableSet());
125+
}
126+
127+
protected V getExtensionVersionImported(DeserializerContext context) {
128+
return ((NetworkDeserializerContext) context).getExtensionVersion(this)
129+
.map(this::versionOf)
130+
.orElseThrow(IllegalStateException::new);
131+
}
132+
133+
protected V getExtensionVersionToExport(SerializerContext context) {
134+
NetworkSerializerContext networkSerializerContext = (NetworkSerializerContext) context;
135+
return networkSerializerContext.getExtensionVersion(getExtensionName())
136+
.map(this::versionOf)
137+
.orElseGet(() -> getVersion(networkSerializerContext.getVersion()));
145138
}
146139

147140
protected void checkReadingCompatibility(NetworkDeserializerContext networkContext) {
148-
IidmVersion version = networkContext.getVersion();
149-
checkCompatibilityNetworkVersion(version);
150-
if (extensionVersions.get(version).stream().noneMatch(v -> networkContext.containsExtensionVersion(getExtensionName(), v))) {
151-
throw new PowsyblException(INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + version.toString(".")
141+
IidmVersion iidmVersion = networkContext.getVersion();
142+
checkCompatibilityNetworkVersion(iidmVersion);
143+
if (versions.stream().filter(v -> v.supports(iidmVersion)).noneMatch(v -> networkContext.containsExtensionVersion(getExtensionName(), v.getVersionString()))) {
144+
throw new PowsyblException(INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + iidmVersion.toString(".")
152145
+ ") is not compatible with the " + extensionName + " extension's namespace URI.");
153146
}
154147
}
155148

156-
public boolean checkWritingCompatibility(String extensionVersion, IidmVersion version) {
157-
checkExtensionVersionSupported(extensionVersion);
158-
checkCompatibilityNetworkVersion(version);
159-
if (!extensionVersions.get(version).contains(extensionVersion)) {
160-
throw new PowsyblException(INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + version.toString(".")
149+
public boolean checkWritingCompatibility(String extensionVersion, IidmVersion iidmVersion) {
150+
if (!versionOf(extensionVersion, true).supports(iidmVersion)) {
151+
throw new PowsyblException(INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + iidmVersion.toString(".")
161152
+ ") is not compatible with " + extensionName + " version " + extensionVersion);
162153
}
163154
return true;
164155
}
165156

166157
private void checkCompatibilityNetworkVersion(IidmVersion version) {
167-
if (!extensionVersions.containsKey(version)) {
158+
if (versions.stream().noneMatch(v -> v.supports(version))) {
168159
throw new PowsyblException(INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + version.toString(".")
169160
+ ") is not supported by the " + getExtensionName() + " extension's XML serializer.");
170161
}
171162
}
172163

173164
@Override
174165
public String getNamespacePrefix() {
175-
return namespacePrefix;
166+
return getDefaultVersion().getNamespacePrefix();
176167
}
177168

178169
@Override
179170
public String getNamespacePrefix(String extensionVersion) {
180-
return namespacePrefixByVersion.getOrDefault(extensionVersion, namespacePrefix);
171+
return versionOf(extensionVersion, true).getNamespacePrefix();
181172
}
182173

183174
@Override
184175
public void checkExtensionVersionSupported(String extensionVersion) {
185-
if (!namespaceUris.containsKey(extensionVersion)) {
186-
throw new PowsyblException("The " + extensionName + " extension version " + extensionVersion + " is not supported.");
176+
versionOf(extensionVersion, true);
177+
}
178+
179+
@Override
180+
public InputStream getXsdAsStream() {
181+
return Objects.requireNonNull(getClass().getResourceAsStream(getDefaultVersion().getXsdResourcePath()));
182+
}
183+
184+
@Override
185+
public List<InputStream> getXsdAsStreamList() {
186+
return versions.stream()
187+
.map(SerDeVersion::getXsdResourcePath)
188+
.map(getClass()::getResourceAsStream)
189+
.map(s -> Objects.requireNonNull(s, "xsd resource not found"))
190+
.toList();
191+
}
192+
193+
protected V getDefaultVersion() {
194+
return versions.get(versions.size() - 1);
195+
}
196+
197+
public V versionOf(String extensionVersion) {
198+
return versionOf(extensionVersion, false);
199+
}
200+
201+
private V versionOf(String extensionVersion, boolean throwIfUnknown) {
202+
Objects.requireNonNull(extensionVersion);
203+
var a = versions.stream()
204+
.filter(v -> extensionVersion.equals(v.getVersionString()))
205+
.findFirst(); // there can only be 0 or exactly 1 match
206+
if (throwIfUnknown) {
207+
return a.orElseThrow(() -> new PowsyblException("The " + extensionName + " extension version " + extensionVersion + " is unknown."));
208+
} else {
209+
return a.orElse(null);
187210
}
188211
}
189212
}

0 commit comments

Comments
 (0)