7
7
*/
8
8
package com .powsybl .iidm .serde .extensions ;
9
9
10
- import com .google .common .collect .BiMap ;
11
- import com .google .common .collect .HashBiMap ;
12
- import com .google .common .collect .ImmutableSortedSet ;
13
10
import com .powsybl .commons .PowsyblException ;
14
11
import com .powsybl .commons .extensions .Extendable ;
15
12
import com .powsybl .commons .extensions .Extension ;
16
13
import com .powsybl .commons .extensions .ExtensionSerDe ;
14
+ import com .powsybl .commons .io .DeserializerContext ;
15
+ import com .powsybl .commons .io .SerializerContext ;
17
16
import com .powsybl .iidm .serde .IidmSerDeConstants ;
18
17
import com .powsybl .iidm .serde .IidmVersion ;
19
18
import com .powsybl .iidm .serde .NetworkDeserializerContext ;
19
+ import com .powsybl .iidm .serde .NetworkSerializerContext ;
20
20
21
+ import java .io .InputStream ;
21
22
import java .util .*;
23
+ import java .util .stream .Collectors ;
22
24
import java .util .stream .Stream ;
23
25
24
26
/**
25
27
* @author Miora Ralambotiana {@literal <miora.ralambotiana at rte-france.com>}
26
28
*/
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 > {
28
31
29
32
private static final String INCOMPATIBILITY_NETWORK_VERSION_MESSAGE = "IIDM version of network (" ;
30
33
31
34
private final String extensionName ;
32
35
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 ;
49
37
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 ) {
54
39
this .extensionName = Objects .requireNonNull (extensionName );
55
40
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 ();
74
44
}
75
45
76
46
@ Override
@@ -80,14 +50,12 @@ public String getExtensionName() {
80
50
81
51
@ Override
82
52
public String getSerializationName (String extensionVersion ) {
83
- return serializationNameByVersion . getOrDefault (extensionVersion , extensionName );
53
+ return versionOf (extensionVersion ). getSerializationName ( );
84
54
}
85
55
86
56
@ Override
87
57
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 ());
91
59
}
92
60
93
61
@ Override
@@ -107,83 +75,138 @@ public String getNamespaceUri() {
107
75
108
76
@ Override
109
77
public Stream <String > getNamespaceUriStream () {
110
- return namespaceUris . values (). stream ().distinct ( );
78
+ return versions . stream ().map ( SerDeVersion :: getNamespaceUri );
111
79
}
112
80
113
81
@ Override
114
82
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 ();
118
84
}
119
85
120
86
@ Override
121
87
public String getVersion () {
122
- return getVersion (IidmSerDeConstants .CURRENT_IIDM_VERSION );
88
+ return getVersion (IidmSerDeConstants .CURRENT_IIDM_VERSION ). getVersionString () ;
123
89
}
124
90
125
91
public boolean versionExists (IidmVersion networkVersion ) {
126
- return extensionVersions . containsKey ( networkVersion );
92
+ return versions . stream (). anyMatch ( version -> version . supports ( networkVersion ) );
127
93
}
128
94
129
95
/**
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.
131
97
*/
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" );
134
111
}
135
112
136
113
@ Override
137
114
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 ()
139
119
.orElseThrow (() -> new PowsyblException ("The namespace URI " + namespaceUri + " of the " + extensionName + " extension is not supported." ));
140
120
}
141
121
142
122
@ Override
143
123
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 ()));
145
138
}
146
139
147
140
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 ("." )
152
145
+ ") is not compatible with the " + extensionName + " extension's namespace URI." );
153
146
}
154
147
}
155
148
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 ("." )
161
152
+ ") is not compatible with " + extensionName + " version " + extensionVersion );
162
153
}
163
154
return true ;
164
155
}
165
156
166
157
private void checkCompatibilityNetworkVersion (IidmVersion version ) {
167
- if (! extensionVersions . containsKey ( version )) {
158
+ if (versions . stream (). noneMatch ( v -> v . supports ( version ) )) {
168
159
throw new PowsyblException (INCOMPATIBILITY_NETWORK_VERSION_MESSAGE + version .toString ("." )
169
160
+ ") is not supported by the " + getExtensionName () + " extension's XML serializer." );
170
161
}
171
162
}
172
163
173
164
@ Override
174
165
public String getNamespacePrefix () {
175
- return namespacePrefix ;
166
+ return getDefaultVersion (). getNamespacePrefix () ;
176
167
}
177
168
178
169
@ Override
179
170
public String getNamespacePrefix (String extensionVersion ) {
180
- return namespacePrefixByVersion . getOrDefault (extensionVersion , namespacePrefix );
171
+ return versionOf (extensionVersion , true ). getNamespacePrefix ( );
181
172
}
182
173
183
174
@ Override
184
175
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 );
187
210
}
188
211
}
189
212
}
0 commit comments