001 package org.apache.maven.artifact.versioning;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.StringTokenizer;
023
024 /**
025 * Default implementation of artifact versioning.
026 *
027 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
028 */
029 public class DefaultArtifactVersion
030 implements ArtifactVersion
031 {
032 private Integer majorVersion;
033
034 private Integer minorVersion;
035
036 private Integer incrementalVersion;
037
038 private Integer buildNumber;
039
040 private String qualifier;
041
042 private ComparableVersion comparable;
043
044 public DefaultArtifactVersion( String version )
045 {
046 parseVersion( version );
047 }
048
049 @Override
050 public int hashCode()
051 {
052 return 11 + comparable.hashCode();
053 }
054
055 @Override
056 public boolean equals( Object other )
057 {
058 if ( this == other )
059 {
060 return true;
061 }
062
063 if ( !( other instanceof ArtifactVersion ) )
064 {
065 return false;
066 }
067
068 return compareTo( (ArtifactVersion) other ) == 0;
069 }
070
071 public int compareTo( ArtifactVersion otherVersion )
072 {
073 if ( otherVersion instanceof DefaultArtifactVersion )
074 {
075 return this.comparable.compareTo( ( (DefaultArtifactVersion) otherVersion).comparable );
076 }
077 else
078 {
079 return compareTo( new DefaultArtifactVersion( otherVersion.toString() ) );
080 }
081 }
082
083 public int getMajorVersion()
084 {
085 return majorVersion != null ? majorVersion : 0;
086 }
087
088 public int getMinorVersion()
089 {
090 return minorVersion != null ? minorVersion : 0;
091 }
092
093 public int getIncrementalVersion()
094 {
095 return incrementalVersion != null ? incrementalVersion : 0;
096 }
097
098 public int getBuildNumber()
099 {
100 return buildNumber != null ? buildNumber : 0;
101 }
102
103 public String getQualifier()
104 {
105 return qualifier;
106 }
107
108 public final void parseVersion( String version )
109 {
110 comparable = new ComparableVersion( version );
111
112 int index = version.indexOf( "-" );
113
114 String part1;
115 String part2 = null;
116
117 if ( index < 0 )
118 {
119 part1 = version;
120 }
121 else
122 {
123 part1 = version.substring( 0, index );
124 part2 = version.substring( index + 1 );
125 }
126
127 if ( part2 != null )
128 {
129 try
130 {
131 if ( ( part2.length() == 1 ) || !part2.startsWith( "0" ) )
132 {
133 buildNumber = Integer.valueOf( part2 );
134 }
135 else
136 {
137 qualifier = part2;
138 }
139 }
140 catch ( NumberFormatException e )
141 {
142 qualifier = part2;
143 }
144 }
145
146 if ( ( part1.indexOf( "." ) < 0 ) && !part1.startsWith( "0" ) )
147 {
148 try
149 {
150 majorVersion = Integer.valueOf( part1 );
151 }
152 catch ( NumberFormatException e )
153 {
154 // qualifier is the whole version, including "-"
155 qualifier = version;
156 buildNumber = null;
157 }
158 }
159 else
160 {
161 boolean fallback = false;
162
163 StringTokenizer tok = new StringTokenizer( part1, "." );
164 try
165 {
166 majorVersion = getNextIntegerToken( tok );
167 if ( tok.hasMoreTokens() )
168 {
169 minorVersion = getNextIntegerToken( tok );
170 }
171 if ( tok.hasMoreTokens() )
172 {
173 incrementalVersion = getNextIntegerToken( tok );
174 }
175 if ( tok.hasMoreTokens() )
176 {
177 fallback = true;
178 }
179
180 // string tokenzier won't detect these and ignores them
181 if ( part1.indexOf( ".." ) >= 0 || part1.startsWith( "." ) || part1.endsWith( "." ) )
182 {
183 fallback = true;
184 }
185 }
186 catch ( NumberFormatException e )
187 {
188 fallback = true;
189 }
190
191 if ( fallback )
192 {
193 // qualifier is the whole version, including "-"
194 qualifier = version;
195 majorVersion = null;
196 minorVersion = null;
197 incrementalVersion = null;
198 buildNumber = null;
199 }
200 }
201 }
202
203 private static Integer getNextIntegerToken( StringTokenizer tok )
204 {
205 String s = tok.nextToken();
206 if ( ( s.length() > 1 ) && s.startsWith( "0" ) )
207 {
208 throw new NumberFormatException( "Number part has a leading 0: '" + s + "'" );
209 }
210 return Integer.valueOf( s );
211 }
212
213 @Override
214 public String toString()
215 {
216 StringBuilder buf = new StringBuilder();
217 if ( majorVersion != null )
218 {
219 buf.append( majorVersion );
220 }
221 if ( minorVersion != null )
222 {
223 buf.append( "." );
224 buf.append( minorVersion );
225 }
226 if ( incrementalVersion != null )
227 {
228 buf.append( "." );
229 buf.append( incrementalVersion );
230 }
231 if ( buildNumber != null )
232 {
233 buf.append( "-" );
234 buf.append( buildNumber );
235 }
236 else if ( qualifier != null )
237 {
238 if ( buf.length() > 0 )
239 {
240 buf.append( "-" );
241 }
242 buf.append( qualifier );
243 }
244 return buf.toString();
245 }
246 }