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 org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.ArtifactUtils;
24 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
25 import org.codehaus.plexus.util.StringUtils;
26
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class DefaultVersionInfo
61 implements VersionInfo
62 {
63 private final String strVersion;
64
65 private final List<String> digits;
66
67 private String annotation;
68
69 private String annotationRevision;
70
71 private final String buildSpecifier;
72
73 private String annotationSeparator;
74
75 private String annotationRevSeparator;
76
77 private final String buildSeparator;
78
79 private static final int DIGITS_INDEX = 1;
80
81 private static final int ANNOTATION_SEPARATOR_INDEX = 2;
82
83 private static final int ANNOTATION_INDEX = 3;
84
85 private static final int ANNOTATION_REV_SEPARATOR_INDEX = 4;
86
87 private static final int ANNOTATION_REVISION_INDEX = 5;
88
89 private static final int BUILD_SEPARATOR_INDEX = 6;
90
91 private static final int BUILD_SPECIFIER_INDEX = 7;
92
93 private static final String SNAPSHOT_IDENTIFIER = "SNAPSHOT";
94
95 private static final String DIGIT_SEPARATOR_STRING = ".";
96
97 public static final Pattern STANDARD_PATTERN = Pattern.compile(
98 "^((?:\\d+\\.)*\\d+)"
99 + "([-_])?"
100 + "([a-zA-Z]*)"
101 + "([-_])?"
102 + "(\\d*)"
103 + "(?:([-_])?(.*?))?$" );
104
105
106
107
108
109
110
111
112
113
114 public static final Pattern ALTERNATE_PATTERN = Pattern.compile( "^(SNAPSHOT|[a-zA-Z]+[_-]SNAPSHOT)" );
115
116
117
118
119
120
121 public DefaultVersionInfo( String version )
122 throws VersionParseException
123 {
124 strVersion = version;
125
126
127 Matcher matcher = ALTERNATE_PATTERN.matcher( strVersion );
128
129 if ( matcher.matches() )
130 {
131 annotation = null;
132 digits = null;
133 buildSpecifier = version;
134 buildSeparator = null;
135 return;
136 }
137
138 Matcher m = STANDARD_PATTERN.matcher( strVersion );
139 if ( m.matches() )
140 {
141 digits = parseDigits( m.group( DIGITS_INDEX ) );
142 if ( !SNAPSHOT_IDENTIFIER.equals( m.group( ANNOTATION_INDEX ) ) )
143 {
144 annotationSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
145 annotation = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
146
147 if ( StringUtils.isNotEmpty( m.group( ANNOTATION_REV_SEPARATOR_INDEX ) )
148 && StringUtils.isEmpty( m.group( ANNOTATION_REVISION_INDEX ) ) )
149 {
150
151 buildSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
152 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
153 }
154 else
155 {
156 annotationRevSeparator = m.group( ANNOTATION_REV_SEPARATOR_INDEX );
157 annotationRevision = nullIfEmpty( m.group( ANNOTATION_REVISION_INDEX ) );
158
159 buildSeparator = m.group( BUILD_SEPARATOR_INDEX );
160 buildSpecifier = nullIfEmpty( m.group( BUILD_SPECIFIER_INDEX ) );
161 }
162 }
163 else
164 {
165
166 buildSeparator = m.group( ANNOTATION_SEPARATOR_INDEX );
167 buildSpecifier = nullIfEmpty( m.group( ANNOTATION_INDEX ) );
168 }
169 }
170 else
171 {
172 throw new VersionParseException( "Unable to parse the version string: \"" + version + "\"" );
173 }
174 }
175
176 public DefaultVersionInfo( List<String> digits, String annotation, String annotationRevision, String buildSpecifier,
177 String annotationSeparator, String annotationRevSeparator, String buildSeparator )
178 {
179 this.digits = digits;
180 this.annotation = annotation;
181 this.annotationRevision = annotationRevision;
182 this.buildSpecifier = buildSpecifier;
183 this.annotationSeparator = annotationSeparator;
184 this.annotationRevSeparator = annotationRevSeparator;
185 this.buildSeparator = buildSeparator;
186 this.strVersion = getVersionString( this, buildSpecifier, buildSeparator );
187 }
188
189 public boolean isSnapshot()
190 {
191 return ArtifactUtils.isSnapshot( strVersion );
192 }
193
194 public VersionInfo getNextVersion()
195 {
196 DefaultVersionInfo version = null;
197 if ( digits != null )
198 {
199 List<String> digits = new ArrayList<String>( this.digits );
200 String annotationRevision = this.annotationRevision;
201 if ( StringUtils.isNumeric( annotationRevision ) )
202 {
203 annotationRevision = incrementVersionString( annotationRevision );
204 }
205 else
206 {
207 digits.set( digits.size() - 1, incrementVersionString( (String) digits.get( digits.size() - 1 ) ) );
208 }
209
210 version = new DefaultVersionInfo( digits, annotation, annotationRevision, buildSpecifier,
211 annotationSeparator, annotationRevSeparator, buildSeparator );
212 }
213 return version;
214 }
215
216
217
218
219
220
221
222
223
224
225 public int compareTo( VersionInfo obj )
226 {
227 DefaultVersionInfo that = (DefaultVersionInfo) obj;
228
229 int result;
230
231 if ( strVersion.startsWith( that.strVersion ) && !strVersion.equals( that.strVersion )
232 && strVersion.charAt( that.strVersion.length() ) != '-' )
233 {
234 result = 1;
235 }
236 else if ( that.strVersion.startsWith( strVersion ) && !strVersion.equals( that.strVersion )
237 && that.strVersion.charAt( strVersion.length() ) != '-' )
238 {
239 result = -1;
240 }
241 else
242 {
243
244
245 String thisVersion = strVersion.toUpperCase( Locale.ENGLISH ).toLowerCase( Locale.ENGLISH );
246 String thatVersion = that.strVersion.toUpperCase( Locale.ENGLISH ).toLowerCase( Locale.ENGLISH );
247
248 result = new DefaultArtifactVersion( thisVersion ).compareTo( new DefaultArtifactVersion( thatVersion ) );
249 }
250 return result;
251 }
252
253 public boolean equals( Object obj )
254 {
255 if ( !( obj instanceof DefaultVersionInfo ) )
256 {
257 return false;
258 }
259
260 return compareTo( (VersionInfo) obj ) == 0;
261 }
262
263 public int hashCode()
264 {
265 return strVersion.toLowerCase( Locale.ENGLISH ).hashCode();
266 }
267
268
269
270
271
272
273
274 protected String incrementVersionString( String s )
275 {
276 int n = Integer.valueOf( s ).intValue() + 1;
277 String value = String.valueOf( n );
278 if ( value.length() < s.length() )
279 {
280
281 value = StringUtils.leftPad( value, s.length(), "0" );
282 }
283 return value;
284 }
285
286 public String getSnapshotVersionString()
287 {
288 if ( strVersion.equals( Artifact.SNAPSHOT_VERSION ) )
289 {
290 return strVersion;
291 }
292
293 String baseVersion = getReleaseVersionString();
294
295 if ( baseVersion.length() > 0 )
296 {
297 baseVersion += "-";
298 }
299
300 return baseVersion + Artifact.SNAPSHOT_VERSION;
301 }
302
303 public String getReleaseVersionString()
304 {
305 String baseVersion = strVersion;
306
307 Matcher m = Artifact.VERSION_FILE_PATTERN.matcher( baseVersion );
308 if ( m.matches() )
309 {
310 baseVersion = m.group( 1 );
311 }
312
313 else if ( StringUtils.right( baseVersion, 9 ).equalsIgnoreCase( "-" + Artifact.SNAPSHOT_VERSION ) )
314 {
315 baseVersion = baseVersion.substring( 0, baseVersion.length() - Artifact.SNAPSHOT_VERSION.length() - 1 );
316 }
317 else if ( baseVersion.equals( Artifact.SNAPSHOT_VERSION ) )
318 {
319 baseVersion = "1.0";
320 }
321 return baseVersion;
322 }
323
324 public String toString()
325 {
326 return strVersion;
327 }
328
329 protected static String getVersionString( DefaultVersionInfo info, String buildSpecifier, String buildSeparator )
330 {
331 StringBuilder sb = new StringBuilder();
332
333 if ( info.digits != null )
334 {
335 sb.append( joinDigitString( info.digits ) );
336 }
337
338 if ( StringUtils.isNotEmpty( info.annotation ) )
339 {
340 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
341 sb.append( info.annotation );
342 }
343
344 if ( StringUtils.isNotEmpty( info.annotationRevision ) )
345 {
346 if ( StringUtils.isEmpty( info.annotation ) )
347 {
348 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
349 }
350 else
351 {
352 sb.append( StringUtils.defaultString( info.annotationRevSeparator ) );
353 }
354 sb.append( info.annotationRevision );
355 }
356
357 if ( StringUtils.isNotEmpty( buildSpecifier ) )
358 {
359 sb.append( StringUtils.defaultString( buildSeparator ) );
360 sb.append( buildSpecifier );
361 }
362
363 return sb.toString();
364 }
365
366
367
368
369
370
371 protected static String joinDigitString( List<String> digits )
372 {
373 return digits != null ? StringUtils.join( digits.iterator(), DIGIT_SEPARATOR_STRING ) : null;
374 }
375
376
377
378
379
380
381
382 private List<String> parseDigits( String strDigits )
383 {
384 return Arrays.asList( StringUtils.split( strDigits, DIGIT_SEPARATOR_STRING ) );
385 }
386
387
388
389
390
391 private static String nullIfEmpty( String s )
392 {
393 return StringUtils.isEmpty( s ) ? null : s;
394 }
395
396 public List<String> getDigits()
397 {
398 return digits;
399 }
400
401 public String getAnnotation()
402 {
403 return annotation;
404 }
405
406 public String getAnnotationRevision()
407 {
408 return annotationRevision;
409 }
410
411 public String getBuildSpecifier()
412 {
413 return buildSpecifier;
414 }
415
416 }