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.contains( "." ) ) && !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.contains( ".." ) || 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    }