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
80 public static final Pattern STANDARD_PATTERN = Pattern.compile( "^((?:\\d+\\.)*\\d+)"
81
82
83 + "([-_])?"
84 + "([a-zA-Z]*)"
85 + "([-_])?"
86 + "(\\d*)"
87 + "(?:([-_])?(.*?))?$" );
88
89
90
91
92
93
94
95 public static final Pattern ALTERNATE_PATTERN = Pattern.compile( "^(SNAPSHOT|[a-zA-Z]+[_-]SNAPSHOT)" );
96
97 private Version( List<String> digits, String annotation, String annotationRevision, String buildSpecifier,
98 String annotationSeparator, String annotationRevSeparator, String buildSeparator )
99 {
100 this.digits = digits;
101 this.annotation = annotation;
102 this.annotationRevision = annotationRevision;
103 this.buildSpecifier = buildSpecifier;
104 this.annotationSeparator = annotationSeparator;
105 this.annotationRevSeparator = annotationRevSeparator;
106 this.buildSeparator = buildSeparator;
107 this.strVersion = getVersionString( this, buildSpecifier, buildSeparator );
108
109
110 this.aetherVersion = null;
111 this.mavenArtifactVersion = null;
112 }
113
114
115
116
117
118
119
120 public Version( String version )
121 throws VersionParseException
122 {
123 this.strVersion = version;
124 this.aetherVersion = new AetherVersion( version );
125 this.mavenArtifactVersion = new MavenArtifactVersion( version );
126
127
128 Matcher matcher = ALTERNATE_PATTERN.matcher( strVersion );
129
130 if ( matcher.matches() )
131 {
132 annotation = null;
133 digits = null;
134 buildSpecifier = version;
135 buildSeparator = null;
136 return;
137 }
138
139 Matcher m = STANDARD_PATTERN.matcher( strVersion );
140 if ( m.matches() )
141 {
142 digits = parseDigits( m.group( DIGITS_INDEX ) );
143 if ( !SNAPSHOT_IDENTIFIER.equals( m.group( ANNOTATION_INDEX ) ) )
144 {
145 annotationSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
146 annotation = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
147
148 if ( StringUtils.isNotEmpty( m.group( ANNOTATION_REV_SEPARATOR_INDEX ) )
149 && StringUtils.isEmpty( m.group( ANNOTATION_REVISION_INDEX ) ) )
150 {
151
152 buildSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
153 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
154 }
155 else
156 {
157 annotationRevSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
158 annotationRevision = nullIfEmpty( m.group( ANNOTATION_REVISION_INDEX ) );
159
160 buildSeparator = m.group( BUILD_SEPARATOR_INDEX );
161 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
162 }
163 }
164 else
165 {
166
167 buildSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
168 buildSpecifier = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
169 }
170 }
171 else
172 {
173 throw new VersionParseException( "Unable to parse the version string: \"" + version + "\"" );
174 }
175 }
176
177
178
179
180
181
182 public boolean isSnapshot()
183 {
184 return ArtifactUtils.isSnapshot( strVersion );
185 }
186
187
188
189
190
191
192 public String toString()
193 {
194 return strVersion;
195 }
196
197
198
199
200
201
202
203
204
205 protected static String getVersionString( Version info, String buildSpecifier, String buildSeparator )
206 {
207 StringBuilder sb = new StringBuilder();
208
209 if ( info.digits != null )
210 {
211 sb.append( joinDigitString( info.digits ) );
212 }
213
214 if ( StringUtils.isNotEmpty( info.annotation ) )
215 {
216 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
217 sb.append( info.annotation );
218 }
219
220 if ( StringUtils.isNotEmpty( info.annotationRevision ) )
221 {
222 if ( StringUtils.isEmpty( info.annotation ) )
223 {
224 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
225 }
226 else
227 {
228 sb.append( StringUtils.defaultString( info.annotationRevSeparator ) );
229 }
230 sb.append( info.annotationRevision );
231 }
232
233 if ( StringUtils.isNotEmpty( buildSpecifier ) )
234 {
235 sb.append( StringUtils.defaultString( buildSeparator ) );
236 sb.append( buildSpecifier );
237 }
238
239 return sb.toString();
240 }
241
242
243
244
245
246
247
248 protected static String joinDigitString( List<String> digits )
249 {
250 return digits != null ? StringUtils.join( digits.iterator(), DIGIT_SEPARATOR_STRING ) : null;
251 }
252
253
254
255
256
257
258 private List<String> parseDigits( String strDigits )
259 {
260 return Arrays.asList( StringUtils.split( strDigits, DIGIT_SEPARATOR_STRING ) );
261 }
262
263 private static String nullIfEmpty( String s )
264 {
265 return StringUtils.isEmpty( s ) ? null : s;
266 }
267
268
269
270
271
272
273 public List<String> getDigits()
274 {
275 return digits;
276 }
277
278
279
280
281
282
283 public String getAnnotation()
284 {
285 return annotation;
286 }
287
288
289
290
291
292
293 public String getAnnotationRevSeparator()
294 {
295 return annotationRevSeparator;
296 }
297
298
299
300
301
302
303 public String getAnnotationRevision()
304 {
305 return annotationRevision;
306 }
307
308
309
310
311
312
313 public String getBuildSeparator()
314 {
315 return buildSeparator;
316 }
317
318
319
320
321
322
323 public String getBuildSpecifier()
324 {
325 return buildSpecifier;
326 }
327
328
329
330
331
332
333
334 public Version setDigits( List<String> newDigits )
335 {
336 return new Version( newDigits, this.annotation, this.annotationRevision, this.buildSpecifier,
337 this.annotationSeparator, this.annotationRevSeparator, this.buildSeparator );
338 }
339
340
341
342
343
344
345
346 public Version setAnnotationRevision( String newAnnotationRevision )
347 {
348 return new Version( this.digits, this.annotation, newAnnotationRevision, this.buildSpecifier,
349 this.annotationSeparator,
350 Objects.toString( this.annotationRevSeparator, DEFAULT_ANNOTATION_REV_SEPARATOR ),
351 this.buildSeparator );
352 }
353
354
355
356
357
358
359
360 public Version setBuildSpecifier( String newBuildSpecifier )
361 {
362 return new Version( this.digits, this.annotation, this.annotationRevision, newBuildSpecifier,
363 this.annotationSeparator, this.annotationRevSeparator,
364 Objects.toString( this.buildSeparator, DEFAULT_BUILD_SEPARATOR ) );
365 }
366
367
368
369
370
371
372
373
374
375
376 public int compareTo( Version other )
377 throws VersionComparisonConflictException
378 {
379 int aetherComparisonResult = this.aetherVersion.compareTo( other.aetherVersion );
380 int mavenComparisonResult = this.mavenArtifactVersion.compareTo( other.mavenArtifactVersion );
381
382 if ( aetherComparisonResult < 0 && mavenComparisonResult < 0 )
383 {
384 return -1;
385 }
386 else if ( aetherComparisonResult == 0 && mavenComparisonResult == 0 )
387 {
388 return 0;
389 }
390 else if ( aetherComparisonResult > 0 && mavenComparisonResult > 0 )
391 {
392 return 1;
393 }
394 else
395 {
396 throw new VersionComparisonConflictException( this.strVersion, other.strVersion, aetherComparisonResult,
397 mavenComparisonResult );
398 }
399 }
400
401 }