View Javadoc
1   package org.apache.maven.artifact.versioning;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.StringTokenizer;
23  import java.util.regex.Pattern;
24  import java.util.NoSuchElementException;
25  
26  /**
27   * Default implementation of artifact versioning.
28   *
29   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
30   */
31  public class DefaultArtifactVersion
32      implements ArtifactVersion
33  {
34      private Integer majorVersion;
35  
36      private Integer minorVersion;
37  
38      private Integer incrementalVersion;
39  
40      private Integer buildNumber;
41  
42      private String qualifier;
43  
44      private ComparableVersion comparable;
45  
46      public DefaultArtifactVersion( String version )
47      {
48          parseVersion( version );
49      }
50  
51      @Override
52      public int hashCode()
53      {
54          return 11 + comparable.hashCode();
55      }
56  
57      @Override
58      public boolean equals( Object other )
59      {
60          if ( this == other )
61          {
62              return true;
63          }
64  
65          if ( !( other instanceof ArtifactVersion ) )
66          {
67              return false;
68          }
69  
70          return compareTo( (ArtifactVersion) other ) == 0;
71      }
72  
73      public int compareTo( ArtifactVersion otherVersion )
74      {
75          if ( otherVersion instanceof DefaultArtifactVersion )
76          {
77              return this.comparable.compareTo( ( (DefaultArtifactVersion) otherVersion ).comparable );
78          }
79          else
80          {
81              return compareTo( new DefaultArtifactVersion( otherVersion.toString() ) );
82          }
83      }
84  
85      public int getMajorVersion()
86      {
87          return majorVersion != null ? majorVersion : 0;
88      }
89  
90      public int getMinorVersion()
91      {
92          return minorVersion != null ? minorVersion : 0;
93      }
94  
95      public int getIncrementalVersion()
96      {
97          return incrementalVersion != null ? incrementalVersion : 0;
98      }
99  
100     public int getBuildNumber()
101     {
102         return buildNumber != null ? buildNumber : 0;
103     }
104 
105     public String getQualifier()
106     {
107         return qualifier;
108     }
109 
110     public final void parseVersion( String version )
111     {
112         comparable = new ComparableVersion( version );
113 
114         int index = version.indexOf( '-' );
115 
116         String part1;
117         String part2 = null;
118 
119         if ( index < 0 )
120         {
121             part1 = version;
122         }
123         else
124         {
125             part1 = version.substring( 0, index );
126             part2 = version.substring( index + 1 );
127         }
128 
129         if ( part2 != null )
130         {
131             try
132             {
133                 if ( ( part2.length() == 1 ) || !part2.startsWith( "0" ) )
134                 {
135                     buildNumber = Integer.valueOf( part2 );
136                 }
137                 else
138                 {
139                     qualifier = part2;
140                 }
141             }
142             catch ( NumberFormatException e )
143             {
144                 qualifier = part2;
145             }
146         }
147 
148         if ( ( !part1.contains( "." ) ) && !part1.startsWith( "0" ) )
149         {
150             try
151             {
152                 majorVersion = Integer.valueOf( part1 );
153             }
154             catch ( NumberFormatException e )
155             {
156                 // qualifier is the whole version, including "-"
157                 qualifier = version;
158                 buildNumber = null;
159             }
160         }
161         else
162         {
163             boolean fallback = false;
164 
165             StringTokenizer tok = new StringTokenizer( part1, "." );
166             try
167             {
168                 majorVersion = getNextIntegerToken( tok );
169                 if ( tok.hasMoreTokens() )
170                 {
171                     minorVersion = getNextIntegerToken( tok );
172                 }
173                 if ( tok.hasMoreTokens() )
174                 {
175                     incrementalVersion = getNextIntegerToken( tok );
176                 }
177                 if ( tok.hasMoreTokens() )
178                 {
179                     qualifier = tok.nextToken();
180                     fallback = Pattern.compile( "\\d+" ).matcher( qualifier ).matches();
181                 }
182 
183                 // string tokenizer won't detect these and ignores them
184                 if ( part1.contains( ".." ) || part1.startsWith( "." ) || part1.endsWith( "." ) )
185                 {
186                     fallback = true;
187                 }
188             }
189             catch ( NumberFormatException e )
190             {
191                 fallback = true;
192             }
193 
194             if ( fallback )
195             {
196                 // qualifier is the whole version, including "-"
197                 qualifier = version;
198                 majorVersion = null;
199                 minorVersion = null;
200                 incrementalVersion = null;
201                 buildNumber = null;
202             }
203         }
204     }
205 
206     private static Integer getNextIntegerToken( StringTokenizer tok )
207     {
208         try
209         {
210             String s = tok.nextToken();
211             if ( ( s.length() > 1 ) && s.startsWith( "0" ) )
212             {
213                 throw new NumberFormatException( "Number part has a leading 0: '" + s + "'" );
214             }
215             return Integer.valueOf( s );
216         }
217         catch ( NoSuchElementException e )
218         {
219             throw new NumberFormatException( "Number is invalid" );
220         }
221     }
222 
223     @Override
224     public String toString()
225     {
226         return comparable.toString();
227     }
228 }