1
1
package com .devonfw .tools .ide .version ;
2
2
3
+ import com .fasterxml .jackson .annotation .JsonCreator ;
4
+ import com .fasterxml .jackson .annotation .JsonValue ;
5
+
3
6
/**
4
- * Container for a range of versions.
7
+ * Container for a range of versions. The lower and upper bounds can be exclusive or inclusive. If a bound is null, it
8
+ * means that this direction is unbounded. The boolean defining whether this bound is inclusive or exclusive is ignored
9
+ * in this case.
5
10
*/
6
11
public final class VersionRange implements Comparable <VersionRange > {
7
12
8
13
private final VersionIdentifier min ;
9
14
10
15
private final VersionIdentifier max ;
11
16
17
+ private final boolean leftIsExclusive ;
18
+
19
+ private final boolean rightIsExclusive ;
20
+
21
+ private static final String VERSION_SEPARATOR = ">" ;
22
+
23
+ private static final String START_EXCLUDING_PREFIX = "(" ;
24
+
25
+ private static final String START_INCLUDING_PREFIX = "[" ;
26
+
27
+ private static final String END_EXCLUDING_SUFFIX = ")" ;
28
+
29
+ private static final String END_INCLUDING_SUFFIX = "]" ;
30
+
31
+ public static String getVersionSeparator () {
32
+
33
+ return VERSION_SEPARATOR ;
34
+ }
35
+
36
+ public static String getStartExcludingPrefix () {
37
+
38
+ return START_EXCLUDING_PREFIX ;
39
+ }
40
+
41
+ public static String getStartIncludingPrefix () {
42
+
43
+ return START_INCLUDING_PREFIX ;
44
+ }
45
+
46
+ public static String getEndExcludingSuffix () {
47
+
48
+ return END_EXCLUDING_SUFFIX ;
49
+ }
50
+
51
+ public static String getEndIncludingSuffix () {
52
+
53
+ return END_INCLUDING_SUFFIX ;
54
+ }
55
+
12
56
/**
13
57
* The constructor.
14
58
*
@@ -20,6 +64,42 @@ public VersionRange(VersionIdentifier min, VersionIdentifier max) {
20
64
super ();
21
65
this .min = min ;
22
66
this .max = max ;
67
+ this .leftIsExclusive = false ;
68
+ this .rightIsExclusive = false ;
69
+ }
70
+
71
+ /**
72
+ * The constructor.
73
+ *
74
+ * @param min the {@link #getMin() minimum}.
75
+ * @param max the {@link #getMax() maximum}.
76
+ * @param boundaryType the {@link BoundaryType} defining whether the boundaries of the range are inclusive or
77
+ * exclusive.
78
+ */
79
+ public VersionRange (VersionIdentifier min , VersionIdentifier max , BoundaryType boundaryType ) {
80
+
81
+ super ();
82
+ this .min = min ;
83
+ this .max = max ;
84
+ this .leftIsExclusive = BoundaryType .LEFT_OPEN .equals (boundaryType ) || BoundaryType .OPEN .equals (boundaryType );
85
+ this .rightIsExclusive = BoundaryType .RIGHT_OPEN .equals (boundaryType ) || BoundaryType .OPEN .equals (boundaryType );
86
+ }
87
+
88
+ /**
89
+ * The constructor.
90
+ *
91
+ * @param min the {@link #getMin() minimum}.
92
+ * @param max the {@link #getMax() maximum}.
93
+ * @param leftIsExclusive - {@code true} if the {@link #getMin() minimum} is exclusive, {@code false} otherwise.
94
+ * @param rightIsExclusive - {@code true} if the {@link #getMax() maximum} is exclusive, {@code false} otherwise.
95
+ */
96
+ public VersionRange (VersionIdentifier min , VersionIdentifier max , boolean leftIsExclusive , boolean rightIsExclusive ) {
97
+
98
+ super ();
99
+ this .min = min ;
100
+ this .max = max ;
101
+ this .leftIsExclusive = leftIsExclusive ;
102
+ this .rightIsExclusive = rightIsExclusive ;
23
103
}
24
104
25
105
/**
@@ -38,6 +118,38 @@ public VersionIdentifier getMax() {
38
118
return this .max ;
39
119
}
40
120
121
+ /**
122
+ * @return {@code true} if the {@link #getMin() minimum} is exclusive, {@code false} otherwise.
123
+ */
124
+ public boolean isLeftExclusive () {
125
+
126
+ return this .leftIsExclusive ;
127
+ }
128
+
129
+ /**
130
+ * @return {@code true} if the {@link #getMax() maximum} is exclusive, {@code false} otherwise.
131
+ */
132
+ public boolean isRightExclusive () {
133
+
134
+ return this .rightIsExclusive ;
135
+ }
136
+
137
+ /**
138
+ * @return the {@link BoundaryType} defining whether the boundaries of the range are inclusive or exclusive.
139
+ */
140
+ public BoundaryType getBoundaryType () {
141
+
142
+ if (this .leftIsExclusive && this .rightIsExclusive ) {
143
+ return BoundaryType .OPEN ;
144
+ } else if (this .leftIsExclusive ) {
145
+ return BoundaryType .LEFT_OPEN ;
146
+ } else if (this .rightIsExclusive ) {
147
+ return BoundaryType .RIGHT_OPEN ;
148
+ } else {
149
+ return BoundaryType .CLOSED ;
150
+ }
151
+ }
152
+
41
153
/**
42
154
* @param version the {@link VersionIdentifier} to check.
43
155
* @return {@code true} if the given {@link VersionIdentifier} is contained in this {@link VersionRange},
@@ -46,12 +158,18 @@ public VersionIdentifier getMax() {
46
158
public boolean contains (VersionIdentifier version ) {
47
159
48
160
if (this .min != null ) {
49
- if (version .isLess (this .min )) {
161
+ VersionComparisonResult compareMin = version .compareVersion (this .min );
162
+ if (compareMin .isLess ()) {
163
+ return false ;
164
+ } else if (compareMin .isEqual () && this .leftIsExclusive ) {
50
165
return false ;
51
166
}
52
167
}
53
168
if (this .max != null ) {
54
- if (version .isGreater (this .max )) {
169
+ VersionComparisonResult compareMax = version .compareVersion (this .max );
170
+ if (compareMax .isGreater ()) {
171
+ return false ;
172
+ } else if (compareMax .isEqual () && this .rightIsExclusive ) {
55
173
return false ;
56
174
}
57
175
}
@@ -69,33 +187,67 @@ public int compareTo(VersionRange o) {
69
187
}
70
188
return -1 ;
71
189
}
72
- return this .min .compareTo (o .min );
190
+ int compareMins = this .min .compareTo (o .min );
191
+ if (compareMins == 0 ) {
192
+ return this .leftIsExclusive == o .leftIsExclusive ? 0 : this .leftIsExclusive ? 1 : -1 ;
193
+ } else {
194
+ return compareMins ;
195
+ }
73
196
}
74
197
75
198
@ Override
199
+ public boolean equals (Object obj ) {
200
+
201
+ if (this == obj ) {
202
+ return true ;
203
+ } else if ((obj == null ) || (getClass () != obj .getClass ())) {
204
+ return false ;
205
+ }
206
+ VersionRange o = (VersionRange ) obj ;
207
+ if (this .min == null && this .max == null ) {
208
+ return o .min == null && o .max == null ;
209
+ } else if (this .min == null ) {
210
+ return o .min == null && this .max .equals (o .max ) && this .rightIsExclusive == o .rightIsExclusive ;
211
+ } else if (this .max == null ) {
212
+ return this .min .equals (o .min ) && o .max == null && this .leftIsExclusive == o .leftIsExclusive ;
213
+ }
214
+ return this .min .equals (o .min ) && this .leftIsExclusive == o .leftIsExclusive && this .max .equals (o .max )
215
+ && this .rightIsExclusive == o .rightIsExclusive ;
216
+ }
217
+
218
+ @ Override
219
+ @ JsonValue
76
220
public String toString () {
77
221
78
222
StringBuilder sb = new StringBuilder ();
223
+ sb .append (this .leftIsExclusive ? START_EXCLUDING_PREFIX : START_INCLUDING_PREFIX );
79
224
if (this .min != null ) {
80
225
sb .append (this .min );
81
226
}
82
- sb .append ('>' );
227
+ sb .append (VERSION_SEPARATOR );
83
228
if (this .max != null ) {
84
229
sb .append (this .max );
85
230
}
231
+ sb .append (this .rightIsExclusive ? END_EXCLUDING_SUFFIX : END_INCLUDING_SUFFIX );
86
232
return sb .toString ();
87
233
}
88
234
89
235
/**
90
236
* @param value the {@link #toString() string representation} of a {@link VersionRange} to parse.
91
237
* @return the parsed {@link VersionRange}.
92
238
*/
239
+ @ JsonCreator
93
240
public static VersionRange of (String value ) {
94
241
95
- int index = value .indexOf ('>' );
242
+ boolean leftIsExclusive = value .startsWith (START_EXCLUDING_PREFIX );
243
+ boolean rightIsExclusive = value .endsWith (END_EXCLUDING_SUFFIX );
244
+ value = removeAffixes (value );
245
+
246
+ int index = value .indexOf (VERSION_SEPARATOR );
96
247
if (index == -1 ) {
97
248
return null ; // log warning?
98
249
}
250
+
99
251
VersionIdentifier min = null ;
100
252
if (index > 0 ) {
101
253
min = VersionIdentifier .of (value .substring (0 , index ));
@@ -105,7 +257,22 @@ public static VersionRange of(String value) {
105
257
if (!maxString .isEmpty ()) {
106
258
max = VersionIdentifier .of (maxString );
107
259
}
108
- return new VersionRange (min , max );
260
+ return new VersionRange (min , max , leftIsExclusive , rightIsExclusive );
261
+ }
262
+
263
+ private static String removeAffixes (String value ) {
264
+
265
+ if (value .startsWith (START_EXCLUDING_PREFIX )) {
266
+ value = value .substring (START_EXCLUDING_PREFIX .length ());
267
+ } else if (value .startsWith (START_INCLUDING_PREFIX )) {
268
+ value = value .substring (START_INCLUDING_PREFIX .length ());
269
+ }
270
+ if (value .endsWith (END_EXCLUDING_SUFFIX )) {
271
+ value = value .substring (0 , value .length () - END_EXCLUDING_SUFFIX .length ());
272
+ } else if (value .endsWith (END_INCLUDING_SUFFIX )) {
273
+ value = value .substring (0 , value .length () - END_EXCLUDING_SUFFIX .length ());
274
+ }
275
+ return value ;
109
276
}
110
277
111
278
}
0 commit comments