-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRexsVersion.java
More file actions
361 lines (316 loc) · 11.9 KB
/
RexsVersion.java
File metadata and controls
361 lines (316 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
package info.rexs.schema.constants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import info.rexs.schema.constants.standard.RexsStandardVersions;
/**
* Class representing a version in the REXS (Reusable Engineering EXchange Standard) schema.
*
* @apiNote {@link #equals} and {@link #hashCode} are implemented based on the schema version and schema provider only. Two versions are considered equal if their schema version and schema provider are equal, even if their model version is different.
*/
public class RexsVersion {
/**
* A constant representing an unknown version.
*/
public static final RexsVersion UNKNOWN = new RexsVersion("UNKNOWN", null, "UNKNOWN");
private static final String DEV_VERSION_NAME = "DEV";
/**
* A constant representing the development version.
*/
public static final RexsVersion DEV = new RexsVersion(DEV_VERSION_NAME, null, DEV_VERSION_NAME);
/**
* A map to store all versions by their model identifier.
*/
private static final Map<String, RexsVersion> allModelVersions = new HashMap<>();
static {
// initialize the standard versions
RexsStandardVersions.init();
}
/**
* The (case-insensitive) identifier of the version in the REXS schema.
*/
private final String schemaVersion;
/**
* The (case-insensitive) identifier of the provider in the REXS schema.
*/
private final String schemaProvider;
/**
* The (case-insensitive) identifier of the version in the REXS model.
*/
private final String modelVersion;
/**
* Additional (case-insensitive) identifiers of the versions in the REXS model.
*/
private final List<String> additionalModelVersions = new ArrayList<>();
/**
* Gets the additional model versions.
*
* @return A list of additional model versions.
*/
public List<String> getAdditionalModelVersions() {
return new ArrayList<>(additionalModelVersions);
}
/**
* Creates a new REXS version with additional model versions.
*
* @param schemaVersion The (case-insensitive) identifier of the version in the REXS schema.
* @param schemaProvider The (case-insensitive) identifier of the provider in the REXS schema.
* @param modelVersion The (case-insensitive) identifier of the version in the REXS model.
* @param additionalModelVersions Additional (case-insensitive) identifiers of the versions inthe REXS model.
*/
private RexsVersion(String schemaVersion, String schemaProvider, String modelVersion, List<String> additionalModelVersions) {
this.schemaVersion = schemaVersion;
this.schemaProvider = schemaProvider;
this.modelVersion = modelVersion;
this.additionalModelVersions.addAll(additionalModelVersions);
}
/**
* Creates a new REXS version.
*
* @param schemaVersion The (case-insensitive) identifier of the version in the REXS schema.
* @param schemaProvider The (case-insensitive) identifier of the provider in the REXS schema.
* @param modelVersion The (case-insensitive) identifier of the version in the REXS model.
*/
private RexsVersion(String schemaVersion, String schemaProvider, String modelVersion) {
this.schemaVersion = schemaVersion;
this.schemaProvider = schemaProvider;
this.modelVersion = modelVersion;
}
/**
* Creates a new REXS version and registers it along with any additional model versions.
*
* @param schemaVersion The (case-insensitive) identifier of the version in the REXS schema.
* @param schemaProvider The (case-insensitive) identifier of the provider in the REXS schema.
* @param primaryModelVersion The (case-insensitive) identifier of the primary version in the REXS model.
* @param additionalModelVersions Additional (case-insensitive) identifiers of the versions in the REXS model.
* @return The primary REXS version created.
* @throws IllegalArgumentException if any of the input parameters are invalid.
*/
public static RexsVersion create(String schemaVersion, String schemaProvider, String primaryModelVersion, String... additionalModelVersions) {
// input data validation
if (schemaVersion == null || schemaVersion.isEmpty()) throw new IllegalArgumentException("The schema version cannot be empty");
if (schemaProvider != null && schemaProvider.isEmpty()) schemaProvider = null;
if (primaryModelVersion == null || primaryModelVersion.isEmpty()) throw new IllegalArgumentException("The primary model version cannot be empty");
// check that no entry of additionalModelVersions is empty
for (String additionalModelVersion : additionalModelVersions) {
if (additionalModelVersion == null || additionalModelVersion.isEmpty())
throw new IllegalArgumentException("Additional model versions cannot contain empty entries");
}
// assure that the schema version follows X.X pattern
if (!schemaVersion.matches("\\d+\\.\\d+") && !schemaVersion.equalsIgnoreCase(DEV_VERSION_NAME))
throw new IllegalArgumentException("schemaVersion must follow the pattern X.X");
// create the primary version
RexsVersion primaryVersion = new RexsVersion(schemaVersion, schemaProvider, primaryModelVersion, List.of(additionalModelVersions));
allModelVersions.put(primaryVersion.getModelVersion(), primaryVersion);
// register additional versions
for (String additionalModelVersion : additionalModelVersions) {
allModelVersions.put(additionalModelVersion, primaryVersion);
}
// return the primary version
return primaryVersion;
}
/**
* Finds a version by its model version.
*
* @param modelVersion The model version.
* @return The corresponding RexsVersion2 object, or null if not found.
*/
public static RexsVersion findByModelVersion(String modelVersion) {
// null-check
if (modelVersion == null) {
return UNKNOWN;
}
// check for DEV
if (modelVersion.equalsIgnoreCase(DEV.getModelVersion())) {
return DEV;
}
// Check for registered versions and return the corresponding version or UNKNOWN if not found
return allModelVersions.entrySet().stream()
.filter(entry -> modelVersion.equalsIgnoreCase(entry.getKey()))
.map(Map.Entry::getValue)
.findFirst()
.orElse(UNKNOWN);
}
/**
* Finds a version by its schema version and schema provider.
*
* @param schemaVersion The schema version.
* @param schemaProvider The schema provider.
* @return The corresponding RexsVersion2 object, or null if not found.
*/
public static RexsVersion findBySchema(String schemaVersion, String schemaProvider) {
// null-check
if (schemaVersion == null) {
return UNKNOWN;
}
// replace empty schema provider with null
if (schemaProvider != null && schemaProvider.isEmpty()) {
schemaProvider = null;
}
// check for DEV
if (schemaVersion.equalsIgnoreCase(DEV_VERSION_NAME) && schemaProvider == null) {
return DEV;
}
// check for registered versions (both with and without schema provider)
for (RexsVersion version : allModelVersions.values()) {
if (schemaProvider == null) {
if (schemaVersion.equalsIgnoreCase(version.getSchemaVersion()) && version.schemaProvider == null) {
return version;
}
} else {
if (schemaVersion.equalsIgnoreCase(version.getSchemaVersion()) && schemaProvider.equalsIgnoreCase(version.getSchemaProvider())) {
return version;
}
}
}
// return unknown if nothing matches
return UNKNOWN;
}
/**
* Gets all registered REXS versions.
*
* @return A list of all registered REXS versions.
*/
public static List<RexsVersion> getAll() {
// create a list of all registered versions + DEV
List<RexsVersion> listOfVersions = new ArrayList<>(allModelVersions.values());
listOfVersions.add(DEV);
// return the list without duplicates
return listOfVersions.stream().distinct().toList();
}
/**
* Gets the schema version.
*
* @return The schema version.
*/
public String getSchemaVersion() {
return schemaVersion;
}
/**
* Gets the schema provider.
*
* @return The schema provider.
*/
public String getSchemaProvider() {
return schemaProvider;
}
/**
* Gets the model version.
*
* @return The model version.
*/
public String getModelVersion() {
return modelVersion;
}
/**
* Gets the numeric representation of the REXS version.
* <p>
* The numeric version is derived from the {@link #getSchemaVersion() schemaVersion} as follows:
* <ul>
* <li>Major version is multiplied by {@code 10000}</li>
* <li>Minor version is multiplied by {@code 100}</li>
* <li>Patch version (optional) is multiplied by {@code 1}</li>
* </ul>
* <p>
* Example: {@code "1.6"} results in {@code 10600}.
* </p>
* {@link #DEV} and {@link #UNKNOWN} are handled as special cases. The latest development version is always {@link java.lang.Integer#MAX_VALUE Integer.MAX_VALUE}, the unknown version is returning as {@code -1}.
*
* @return the numeric representation of the REXS version
* @apiNote The {@link #getSchemaProvider() schemaProvider} and {@link #getModelVersion() modelVersion} are not considered in the numeric version.
*/
public int getNumericVersion() {
// return -1 for UNKNOWN
if (this == UNKNOWN) {
return -1;
}
// return max value for DEV
if (this.getSchemaVersion().equalsIgnoreCase(DEV_VERSION_NAME)) {
return Integer.MAX_VALUE;
}
// extract major and minor from the schema version
String[] parts = schemaVersion.split("\\.");
int major = Integer.parseInt(parts[0]);
int minor = Integer.parseInt(parts[1]);
// return the numeric version
return 10000 * major + 100 * minor;
}
/**
* Compares this version with another version.
*
* @param other The other version to compare with.
* @return A negative integer, zero, or a positive integer as this version is less than, equal to, or greater than the specified version.
*/
public int compareTo(RexsVersion other) {
return Integer.compare(this.getNumericVersion(), other.getNumericVersion());
}
/**
* Checks if this version is less than the specified version.
*
* @param other The other version to compare with.
* @return true if this version is less than the specified version, false otherwise.
*/
public boolean isLessThan(RexsVersion other) {
return this.compareTo(other) < 0;
}
/**
* Checks if this version is less than or equivalent to the specified version.
*
* @param other The other version to compare with.
* @return true if this version is less than or equivalent to the specified version, false otherwise.
*/
public boolean isLessThanOrEquivalentTo(RexsVersion other) {
return this.compareTo(other) <= 0;
}
/**
* Checks if this version is greater than the specified version.
*
* @param other The other version to compare with.
* @return true if this version is greater than the specified version, false otherwise.
*/
public boolean isGreaterThan(RexsVersion other) {
return this.compareTo(other) > 0;
}
/**
* Checks if this version is greater than or equivalent to the specified version.
*
* @param other The other version to compare with.
* @return true if this version is greater than or equivalent to the specified version, false otherwise.
*/
public boolean isGreaterThanOrEquivalentTo(RexsVersion other) {
return this.compareTo(other) >= 0;
}
/**
* Checks if this version is equivalent to the specified version.
*
* @param other The other version to compare with.
* @return true if this version is equivalent to the specified version, false otherwise.
*/
public boolean isEquivalentTo(RexsVersion other) {
return this.compareTo(other) == 0;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof RexsVersion other) {
if (this.schemaProvider != null) {
return this.schemaVersion.equals(other.schemaVersion) && this.schemaProvider.equals(other.schemaProvider);
} else {
return this.schemaVersion.equals(other.schemaVersion) && other.schemaProvider == null;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(schemaVersion, schemaProvider);
}
@Override
public String toString() {
return schemaVersion + (schemaProvider != null ? " (" + schemaProvider + ")" : "");
}
}