001package 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
022import java.util.StringTokenizer;
023
024/**
025 * Default implementation of artifact versioning.
026 *
027 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
028 */
029public 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}