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 public class DefaultVersionInfo
60 implements VersionInfo
61 {
62 private final String strVersion;
63
64 private final List<String> digits;
65
66 private String annotation;
67
68 private String annotationRevision;
69
70 private final String buildSpecifier;
71
72 private String annotationSeparator;
73
74 private String annotationRevSeparator;
75
76 private final String buildSeparator;
77
78 private static final int DIGITS_INDEX = 1;
79
80 private static final int ANNOTATION_SEPARATOR_INDEX = 2;
81
82 private static final int ANNOTATION_INDEX = 3;
83
84 private static final int ANNOTATION_REV_SEPARATOR_INDEX = 4;
85
86 private static final int ANNOTATION_REVISION_INDEX = 5;
87
88 private static final int BUILD_SEPARATOR_INDEX = 6;
89
90 private static final int BUILD_SPECIFIER_INDEX = 7;
91
92 private static final String SNAPSHOT_IDENTIFIER = "SNAPSHOT";
93
94 private static final String DIGIT_SEPARATOR_STRING = ".";
95
96 public static final Pattern STANDARD_PATTERN = Pattern.compile(
97 "^((?:\\d+\\.)*\\d+)"
98 + "([-_])?"
99 + "([a-zA-Z]*)"
100 + "([-_])?"
101 + "(\\d*)"
102 + "(?:([-_])?(.*?))?$" );
103
104
105
106
107
108
109
110
111
112 public static final Pattern ALTERNATE_PATTERN = Pattern.compile(
113 "^(SNAPSHOT|[a-zA-Z]+[_-]SNAPSHOT)"
114 );
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 public int compareTo( VersionInfo obj )
225 {
226 DefaultVersionInfo that = (DefaultVersionInfo) obj;
227
228 int result;
229
230 if ( strVersion.startsWith( that.strVersion ) && !strVersion.equals( that.strVersion )
231 && strVersion.charAt( that.strVersion.length() ) != '-' )
232 {
233 result = 1;
234 }
235 else if ( that.strVersion.startsWith( strVersion ) && !strVersion.equals( that.strVersion )
236 && that.strVersion.charAt( strVersion.length() ) != '-' )
237 {
238 result = -1;
239 }
240 else
241 {
242
243
244 String thisVersion = strVersion.toUpperCase( Locale.ENGLISH ).toLowerCase( Locale.ENGLISH );
245 String thatVersion = that.strVersion.toUpperCase( Locale.ENGLISH ).toLowerCase( Locale.ENGLISH );
246
247 result = new DefaultArtifactVersion( thisVersion ).compareTo( new DefaultArtifactVersion( thatVersion ) );
248 }
249 return result;
250 }
251
252 public boolean equals( Object obj )
253 {
254 if ( !( obj instanceof DefaultVersionInfo ) )
255 {
256 return false;
257 }
258
259 return compareTo( (VersionInfo) obj ) == 0;
260 }
261
262
263
264
265
266
267
268 protected String incrementVersionString( String s )
269 {
270 int n = Integer.valueOf( s ).intValue() + 1;
271 String value = String.valueOf( n );
272 if ( value.length() < s.length() )
273 {
274
275 value = StringUtils.leftPad( value, s.length(), "0" );
276 }
277 return value;
278 }
279
280 public String getSnapshotVersionString()
281 {
282 if ( strVersion.equals( Artifact.SNAPSHOT_VERSION ) )
283 {
284 return strVersion;
285 }
286
287 String baseVersion = getReleaseVersionString();
288
289 if ( baseVersion.length() > 0 )
290 {
291 baseVersion += "-";
292 }
293
294 return baseVersion + Artifact.SNAPSHOT_VERSION;
295 }
296
297 public String getReleaseVersionString()
298 {
299 String baseVersion = strVersion;
300
301 Matcher m = Artifact.VERSION_FILE_PATTERN.matcher( baseVersion );
302 if ( m.matches() )
303 {
304 baseVersion = m.group( 1 );
305 }
306
307 else if ( StringUtils.right( baseVersion, 9 ).equalsIgnoreCase( "-" + Artifact.SNAPSHOT_VERSION ) )
308 {
309 baseVersion = baseVersion.substring( 0, baseVersion.length() - Artifact.SNAPSHOT_VERSION.length() - 1 );
310 }
311 else if ( baseVersion.equals( Artifact.SNAPSHOT_VERSION ) )
312 {
313 baseVersion = "1.0";
314 }
315 return baseVersion;
316 }
317
318 public String toString()
319 {
320 return strVersion;
321 }
322
323 protected static String getVersionString( DefaultVersionInfo info, String buildSpecifier, String buildSeparator )
324 {
325 StringBuilder sb = new StringBuilder();
326
327 if ( info.digits != null )
328 {
329 sb.append( joinDigitString( info.digits ) );
330 }
331
332 if ( StringUtils.isNotEmpty( info.annotation ) )
333 {
334 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
335 sb.append( info.annotation );
336 }
337
338 if ( StringUtils.isNotEmpty( info.annotationRevision ) )
339 {
340 if ( StringUtils.isEmpty( info.annotation ) )
341 {
342 sb.append( StringUtils.defaultString( info.annotationSeparator ) );
343 }
344 else
345 {
346 sb.append( StringUtils.defaultString( info.annotationRevSeparator ) );
347 }
348 sb.append( info.annotationRevision );
349 }
350
351 if ( StringUtils.isNotEmpty( buildSpecifier ) )
352 {
353 sb.append( StringUtils.defaultString( buildSeparator ) );
354 sb.append( buildSpecifier );
355 }
356
357 return sb.toString();
358 }
359
360
361
362
363
364
365 protected static String joinDigitString( List<String> digits )
366 {
367 return digits != null ? StringUtils.join( digits.iterator(), DIGIT_SEPARATOR_STRING ) : null;
368 }
369
370
371
372
373
374
375
376 private List<String> parseDigits( String strDigits )
377 {
378 return Arrays.asList( StringUtils.split( strDigits, DIGIT_SEPARATOR_STRING ) );
379 }
380
381
382
383
384
385 private static String nullIfEmpty( String s )
386 {
387 return StringUtils.isEmpty( s ) ? null : s;
388 }
389
390 public List<String> getDigits()
391 {
392 return digits;
393 }
394
395 public String getAnnotation()
396 {
397 return annotation;
398 }
399
400 public String getAnnotationRevision()
401 {
402 return annotationRevision;
403 }
404
405 public String getBuildSpecifier()
406 {
407 return buildSpecifier;
408 }
409
410 }