1
1
package org .codehaus .mojo .versions .ordering ;
2
2
3
- import java .util .Iterator ;
3
+ import java .util .ArrayList ;
4
4
import java .util .List ;
5
5
6
6
import org .apache .commons .lang3 .builder .EqualsBuilder ;
7
7
import org .apache .commons .lang3 .builder .HashCodeBuilder ;
8
8
import org .apache .maven .artifact .versioning .ArtifactVersion ;
9
- import org .apache .maven .artifact .versioning .DefaultArtifactVersion ;
10
9
import org .codehaus .mojo .versions .api .Segment ;
11
-
12
- import static org .codehaus .mojo . versions . ordering . ComparableVersion . IntegerItem . ZERO ;
10
+ import org . codehaus . mojo . versions . utils . DefaultArtifactVersionCache ;
11
+ import org .codehaus .plexus . util . StringUtils ;
13
12
14
13
/**
15
- * <p>Represents an artifact version with all segments more major or equal to a given segment
16
- * held in place. It can be thought of as an artifact having +∞ as its upper bound
17
- * on all segments less major than the held segment.</p>
18
- * <p>When compared with another artifact versions, this results with the other object
14
+ * <p>Represents an <b>immutable</b> artifact version with all segments <em>major</em> to the given segment
15
+ * held in place. It can be thought of as an artifact having +∞ as its upper bound
16
+ * on all segments minor to the held segment.</p>
17
+ * <p>For example:</p>
18
+ * <p>A {@link BoundArtifactVersion} of {@code [1.2.3-2, INCREMENTAL]} can be seen as {@code 1.2.+∞}
19
+ * and will be greater than all versions matching the {@code 1.2.*} pattern.</p>
20
+ * <p>A {@link BoundArtifactVersion} of {@code [1.2.3-2, SUBINCREMENTAL]} will be greater
21
+ * * than all versions matching the {@code 1.2.3-2.*} pattern.</p>
22
+ * <p>When compared to another artifact versions, this results with the other object
19
23
* with the segment versions up to the held segment being equal,
20
24
* always comparing lower than this object.</p>
21
25
* <p>This is particularly helpful for -SNAPSHOT and other versions with qualifiers, which
22
26
* are lower than version 0 in the Maven versioning system.</p>
23
27
*/
24
- public class BoundArtifactVersion extends DefaultArtifactVersion {
28
+ public class BoundArtifactVersion implements ArtifactVersion {
25
29
/**
26
30
* Most major segment that can change, i.e. not held in place.
27
31
* All segments that are more major than this one are held in place.
28
32
*/
29
33
private final Segment segment ;
30
34
31
- private final BoundComparableVersion comparator ;
35
+ private final ArtifactVersion comparable ;
32
36
33
37
/**
34
- * Constructs the instance
38
+ * Constructs the instance given the version in a text format.
39
+ * @param artifactVersion version in a text format
40
+ * @param segment most major segment that can change, i.e. <em>not</em> held in place
41
+ */
42
+ public BoundArtifactVersion (String artifactVersion , Segment segment ) {
43
+ this .segment = segment ;
44
+ StringBuilder versionBuilder = new StringBuilder ();
45
+ String [] segments = tokens (artifactVersion );
46
+ for (int segNr = 0 ;
47
+ segNr <= segments .length || segNr <= Segment .SUBINCREMENTAL .value ();
48
+ segNr ++, versionBuilder .append ("." )) {
49
+ if (segNr < segment .value ()) {
50
+ versionBuilder .append (segNr < segments .length ? integerItemOrZero (segments [segNr ]) : "0" );
51
+ } else {
52
+ versionBuilder .append (Integer .MAX_VALUE );
53
+ }
54
+ }
55
+ versionBuilder .append (Integer .MAX_VALUE );
56
+ comparable = DefaultArtifactVersionCache .of (versionBuilder .toString ());
57
+ }
58
+
59
+ /**
60
+ * Constructs the instance given a {@link ArtifactVersion instance}
35
61
* @param artifactVersion artifact version containing the segment version values
36
62
* @param segment most major segment that can change, i.e. <em>not</em> held in place
37
63
*/
38
64
public BoundArtifactVersion (ArtifactVersion artifactVersion , Segment segment ) {
39
- super (artifactVersion .toString ());
40
- this .segment = segment ;
41
- this .comparator = new BoundComparableVersion (this );
65
+ this (artifactVersion .toString (), segment );
66
+ }
67
+
68
+ /**
69
+ * Splits the given version string into tokens, splitting them on the {@code .} or {@code -} characters
70
+ * as well as on letter/digit boundaries.
71
+ * @param version version string
72
+ * @return tokens of the parsed version string
73
+ */
74
+ private static String [] tokens (String version ) {
75
+ if (version == null ) {
76
+ return new String [0 ];
77
+ }
78
+ List <String > result = new ArrayList <>();
79
+ for (int begin = 0 , end = 0 ; end <= version .length (); end ++) {
80
+ if (end == version .length ()
81
+ || version .charAt (end ) == '.'
82
+ || version .charAt (end ) == '-'
83
+ || isTokenBoundary (version .charAt (begin ), version .charAt (end ))) {
84
+ if (end > begin ) {
85
+ result .add (version .substring (begin , end ));
86
+ }
87
+ begin = end + 1 ;
88
+ }
89
+ }
90
+ return result .toArray (new String [0 ]);
91
+ }
92
+
93
+ /**
94
+ * @param c1 character
95
+ * @param c2 another character
96
+ * @return will only return {@code true} if one of the characters is a digit and the other a letter
97
+ */
98
+ private static boolean isTokenBoundary (char c1 , char c2 ) {
99
+ return Character .isDigit (c1 ) ^ Character .isDigit (c2 );
100
+ }
101
+
102
+ private static String integerItemOrZero (String item ) {
103
+ return StringUtils .isNumeric (item ) ? item : "0" ;
42
104
}
43
105
44
106
/**
@@ -56,7 +118,7 @@ public int compareTo(ArtifactVersion other) {
56
118
return -1 ;
57
119
}
58
120
59
- return comparator .compareTo (ComparableVersion . of ( other . toString ()) );
121
+ return comparable .compareTo (other );
60
122
}
61
123
62
124
@ Override
@@ -74,7 +136,7 @@ public boolean equals(Object o) {
74
136
return new EqualsBuilder ()
75
137
.appendSuper (super .equals (o ))
76
138
.append (getSegment (), that .getSegment ())
77
- .append (comparator , that .comparator )
139
+ .append (comparable , that .comparable )
78
140
.isEquals ();
79
141
}
80
142
@@ -83,48 +145,42 @@ public int hashCode() {
83
145
return new HashCodeBuilder (17 , 37 )
84
146
.appendSuper (super .hashCode ())
85
147
.append (getSegment ())
86
- .append (comparator )
148
+ .append (comparable )
87
149
.toHashCode ();
88
150
}
89
151
90
- protected static class BoundComparableVersion extends ComparableVersion {
91
- private BoundArtifactVersion artifactVersion ;
92
-
93
- protected BoundComparableVersion (BoundArtifactVersion artifactVersion ) {
94
- super (artifactVersion .toString ());
95
- this .artifactVersion = artifactVersion ;
96
- }
97
-
98
- @ Override
99
- public int compareTo (ComparableVersion o ) {
100
- // all segments more or equally major than artifactVersion.segment can change
101
- return compareTo (
102
- ((List <Item >) items ).iterator (),
103
- ((Iterable <Item >) o .items ).iterator (),
104
- artifactVersion .segment .value ());
105
- }
152
+ @ Override
153
+ public int getMajorVersion () {
154
+ return comparable .getMajorVersion ();
155
+ }
106
156
107
- private int compareTo (Iterator <Item > left , Iterator <Item > right , int comparisonsLeft ) {
108
- if (comparisonsLeft <= 0 ) {
109
- // always greater than the other version if all more major segments are equal
110
- return 1 ;
111
- }
157
+ @ Override
158
+ public int getMinorVersion () {
159
+ return comparable .getMinorVersion ();
160
+ }
112
161
113
- int result = left .hasNext () && right .hasNext ()
114
- ? integerItemOrZero (left .next ()).compareTo (right .next ())
115
- : left .hasNext () || right .hasNext () ? compareToZero (left , right ) : 1 ;
162
+ @ Override
163
+ public int getIncrementalVersion () {
164
+ return comparable .getIncrementalVersion ();
165
+ }
116
166
117
- return result != 0 ? result : compareTo (left , right , comparisonsLeft - 1 );
118
- }
167
+ @ Override
168
+ public int getBuildNumber () {
169
+ return comparable .getBuildNumber ();
170
+ }
119
171
120
- private static int compareToZero (Iterator <Item > left , Iterator <Item > right ) {
121
- return left .hasNext ()
122
- ? integerItemOrZero (left .next ()).compareTo (ZERO )
123
- : -right .next ().compareTo (ZERO );
124
- }
172
+ @ Override
173
+ public String getQualifier () {
174
+ return comparable .getQualifier ();
175
+ }
125
176
126
- private static Item integerItemOrZero (Item item ) {
127
- return item instanceof IntegerItem ? item : ZERO ;
128
- }
177
+ /**
178
+ * @deprecated do not use: this method would mutate the state and therefore is illegal to use
179
+ * @throws UnsupportedOperationException thrown if the method is called
180
+ */
181
+ @ Override
182
+ @ Deprecated
183
+ public void parseVersion (String version ) {
184
+ throw new UnsupportedOperationException ();
129
185
}
130
186
}
0 commit comments