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 protected static String joinDigitString( List<String> digits )
222 {
223 return digits != null ? StringUtils.join( digits.iterator(), DIGIT_SEPARATOR_STRING ) : null;
224 }
225
226
227
228
229
230
231 private List<String> parseDigits( String strDigits )
232 {
233 return Arrays.asList( StringUtils.split( strDigits, DIGIT_SEPARATOR_STRING ) );
234 }
235
236 private static String nullIfEmpty( String s )
237 {
238 return StringUtils.isEmpty( s ) ? null : s;
239 }
240
241 public List<String> getDigits()
242 {
243 return digits;
244 }
245
246 public String getAnnotation()
247 {
248 return annotation;
249 }
250
251 public String getAnnotationRevSeparator()
252 {
253 return annotationRevSeparator;
254 }
255
256 public String getAnnotationRevision()
257 {
258 return annotationRevision;
259 }
260
261 public String getBuildSeparator()
262 {
263 return buildSeparator;
264 }
265
266 public String getBuildSpecifier()
267 {
268 return buildSpecifier;
269 }
270
271
272
273
274
275
276 public Version setDigits( List<String> newDigits )
277 {
278 return new Version( newDigits, this.annotation, this.annotationRevision, this.buildSpecifier,
279 this.annotationSeparator, this.annotationRevSeparator, this.buildSeparator );
280 }
281
282
283
284
285
286
287 public Version setAnnotationRevision( String newAnnotationRevision )
288 {
289 return new Version( this.digits, this.annotation, newAnnotationRevision, this.buildSpecifier,
290 this.annotationSeparator,
291 Objects.toString( this.annotationRevSeparator, DEFAULT_ANNOTATION_REV_SEPARATOR ),
292 this.buildSeparator );
293 }
294
295
296
297
298
299
300 public Version setBuildSpecifier( String newBuildSpecifier )
301 {
302 return new Version( this.digits, this.annotation, this.annotationRevision, newBuildSpecifier,
303 this.annotationSeparator, this.annotationRevSeparator,
304 Objects.toString( this.buildSeparator, DEFAULT_BUILD_SEPARATOR ) );
305 }
306
307
308
309
310
311 public int compareTo( Version other )
312 throws VersionComparisonConflictException
313 {
314 int aetherComparisonResult = this.aetherVersion.compareTo( other.aetherVersion );
315 int mavenComparisonResult = this.mavenArtifactVersion.compareTo( other.mavenArtifactVersion );
316
317 if ( aetherComparisonResult < 0 && mavenComparisonResult < 0 )
318 {
319 return -1;
320 }
321 else if ( aetherComparisonResult == 0 && mavenComparisonResult == 0 )
322 {
323 return 0;
324 }
325 else if ( aetherComparisonResult > 0 && mavenComparisonResult > 0 )
326 {
327 return 1;
328 }
329 else
330 {
331 throw new VersionComparisonConflictException( this.strVersion, other.strVersion, aetherComparisonResult,
332 mavenComparisonResult );
333 }
334 }
335
336 }