1 package org.apache.maven.shared.release.versions;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 import org.apache.maven.artifact.ArtifactUtils;
29 import org.codehaus.plexus.util.StringUtils;
30
31
32
33
34 public class Version
35 implements Comparable<Version>, Cloneable
36 {
37 private final AetherVersion aetherVersion;
38
39 private final MavenArtifactVersion mavenArtifactVersion;
40
41 private final String strVersion;
42
43 private final List<String> digits;
44
45 private String annotation;
46
47 private String annotationRevision;
48
49 private final String buildSpecifier;
50
51 private String annotationSeparator;
52
53 private String annotationRevSeparator;
54
55 private String buildSeparator;
56
57 private static final int DIGITS_INDEX = 1;
58
59 private static final int ANNOTATION_SEPARATOR_INDEX = 2;
60
61 private static final int ANNOTATION_INDEX = 3;
62
63 private static final int ANNOTATION_REV_SEPARATOR_INDEX = 4;
64
65 private static final int ANNOTATION_REVISION_INDEX = 5;
66
67 private static final int BUILD_SEPARATOR_INDEX = 6;
68
69 private static final int BUILD_SPECIFIER_INDEX = 7;
70
71 private static final String SNAPSHOT_IDENTIFIER = "SNAPSHOT";
72
73 private static final String DIGIT_SEPARATOR_STRING = ".";
74
75 private static final String DEFAULT_ANNOTATION_REV_SEPARATOR = "-";
76
77 private static final String DEFAULT_BUILD_SEPARATOR = "-";
78
79 public static final Pattern STANDARD_PATTERN = Pattern.compile( "^((?:\\d+\\.)*\\d+)"
80
81
82 + "([-_])?"
83 + "([a-zA-Z]*)"
84 + "([-_])?"
85 + "(\\d*)"
86 + "(?:([-_])?(.*?))?$" );
87
88
89
90
91
92
93 public static final Pattern ALTERNATE_PATTERN = Pattern.compile( "^(SNAPSHOT|[a-zA-Z]+[_-]SNAPSHOT)" );
94
95 private Version( List<String> digits, String annotation, String annotationRevision, String buildSpecifier,
96 String annotationSeparator, String annotationRevSeparator, String buildSeparator )
97 {
98 this.digits = digits;
99 this.annotation = annotation;
100 this.annotationRevision = annotationRevision;
101 this.buildSpecifier = buildSpecifier;
102 this.annotationSeparator = annotationSeparator;
103 this.annotationRevSeparator = annotationRevSeparator;
104 this.buildSeparator = buildSeparator;
105 this.strVersion = getVersionString( this, buildSpecifier, buildSeparator );
106
107
108 this.aetherVersion = null;
109 this.mavenArtifactVersion = null;
110 }
111
112 public Version( String version )
113 throws VersionParseException
114 {
115 this.strVersion = version;
116 this.aetherVersion = new AetherVersion( version );
117 this.mavenArtifactVersion = new MavenArtifactVersion( version );
118
119
120 Matcher matcher = ALTERNATE_PATTERN.matcher( strVersion );
121
122 if ( matcher.matches() )
123 {
124 annotation = null;
125 digits = null;
126 buildSpecifier = version;
127 buildSeparator = null;
128 return;
129 }
130
131 Matcher m = STANDARD_PATTERN.matcher( strVersion );
132 if ( m.matches() )
133 {
134 digits = parseDigits( m.group( DIGITS_INDEX ) );
135 if ( !SNAPSHOT_IDENTIFIER.equals( m.group( ANNOTATION_INDEX ) ) )
136 {
137 annotationSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
138 annotation = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
139
140 if ( StringUtils.isNotEmpty( m.group( ANNOTATION_REV_SEPARATOR_INDEX ) )
141 && StringUtils.isEmpty( m.group( ANNOTATION_REVISION_INDEX ) ) )
142 {
143
144 buildSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
145 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
146 }
147 else
148 {
149 annotationRevSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
150 annotationRevision = nullIfEmpty( m.group( ANNOTATION_REVISION_INDEX ) );
151
152 buildSeparator = m.group( BUILD_SEPARATOR_INDEX );
153 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
154 }
155 }
156 else
157 {
158
159 buildSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
160 buildSpecifier = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
161 }
162 }
163 else
164 {
165 throw new VersionParseException( "Unable to parse the version string: \"" + version + "\"" );
166 }
167 }
168
169 public boolean isSnapshot()
170 {
171 return ArtifactUtils.isSnapshot( strVersion );
172 }
173
174 public String toString()
175 {
176 return strVersion;
177 }
178
179 protected static String getVersionString( Version info, String buildSpecifier, String buildSeparator )
180 {
181 StringBuilder sb = new StringBuilder();
182
183 if ( info.digits != null )
184 {
185 sb.append( joinDigitString( info.digits ) );
186 }
187
188 if ( StringUtils.isNotEmpty( info.annotation ) )
189 {
190 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
191 sb.append( info.annotation );
192 }
193
194 if ( StringUtils.isNotEmpty( info.annotationRevision ) )
195 {
196 if ( StringUtils.isEmpty( info.annotation ) )
197 {
198 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
199 }
200 else
201 {
202 sb.append( StringUtils.defaultString( info.annotationRevSeparator ) );
203 }
204 sb.append( info.annotationRevision );
205 }
206
207 if ( StringUtils.isNotEmpty( buildSpecifier ) )
208 {
209 sb.append( StringUtils.defaultString( buildSeparator ) );
210 sb.append( buildSpecifier );
211 }
212
213 return sb.toString();
214 }
215
216
217
218
219
220
221
222 protected static String joinDigitString( List<String> digits )
223 {
224 return digits != null ? StringUtils.join( digits.iterator(), DIGIT_SEPARATOR_STRING ) : null;
225 }
226
227
228
229
230
231
232 private List<String> parseDigits( String strDigits )
233 {
234 return Arrays.asList( StringUtils.split( strDigits, DIGIT_SEPARATOR_STRING ) );
235 }
236
237 private static String nullIfEmpty( String s )
238 {
239 return StringUtils.isEmpty( s ) ? null : s;
240 }
241
242 public List<String> getDigits()
243 {
244 return digits;
245 }
246
247 public String getAnnotation()
248 {
249 return annotation;
250 }
251
252 public String getAnnotationRevSeparator()
253 {
254 return annotationRevSeparator;
255 }
256
257 public String getAnnotationRevision()
258 {
259 return annotationRevision;
260 }
261
262 public String getBuildSeparator()
263 {
264 return buildSeparator;
265 }
266
267 public String getBuildSpecifier()
268 {
269 return buildSpecifier;
270 }
271
272
273
274
275
276
277 public Version setDigits( List<String> newDigits )
278 {
279 return new Version( newDigits, this.annotation, this.annotationRevision, this.buildSpecifier,
280 this.annotationSeparator, this.annotationRevSeparator, this.buildSeparator );
281 }
282
283
284
285
286
287
288 public Version setAnnotationRevision( String newAnnotationRevision )
289 {
290 return new Version( this.digits, this.annotation, newAnnotationRevision, this.buildSpecifier,
291 this.annotationSeparator,
292 Objects.toString( this.annotationRevSeparator, DEFAULT_ANNOTATION_REV_SEPARATOR ),
293 this.buildSeparator );
294 }
295
296
297
298
299
300
301 public Version setBuildSpecifier( String newBuildSpecifier )
302 {
303 return new Version( this.digits, this.annotation, this.annotationRevision, newBuildSpecifier,
304 this.annotationSeparator, this.annotationRevSeparator,
305 Objects.toString( this.buildSeparator, DEFAULT_BUILD_SEPARATOR ) );
306 }
307
308
309
310
311
312 public int compareTo( Version other )
313 throws VersionComparisonConflictException
314 {
315 int aetherComparisonResult = this.aetherVersion.compareTo( other.aetherVersion );
316 int mavenComparisonResult = this.mavenArtifactVersion.compareTo( other.mavenArtifactVersion );
317
318 if ( aetherComparisonResult < 0 && mavenComparisonResult < 0 )
319 {
320 return -1;
321 }
322 else if ( aetherComparisonResult == 0 && mavenComparisonResult == 0 )
323 {
324 return 0;
325 }
326 else if ( aetherComparisonResult > 0 && mavenComparisonResult > 0 )
327 {
328 return 1;
329 }
330 else
331 {
332 throw new VersionComparisonConflictException( this.strVersion, other.strVersion, aetherComparisonResult,
333 mavenComparisonResult );
334 }
335 }
336
337 }