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;
023import java.util.regex.Pattern;
024
025/**
026 * Default implementation of artifact versioning.
027 *
028 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
029 */
030public class DefaultArtifactVersion
031    implements ArtifactVersion
032{
033    private Integer majorVersion;
034
035    private Integer minorVersion;
036
037    private Integer incrementalVersion;
038
039    private Integer buildNumber;
040
041    private String qualifier;
042
043    private ComparableVersion comparable;
044
045    public DefaultArtifactVersion( String version )
046    {
047        parseVersion( version );
048    }
049
050    @Override
051    public int hashCode()
052    {
053        return 11 + comparable.hashCode();
054    }
055
056    @Override
057    public boolean equals( Object other )
058    {
059        if ( this == other )
060        {
061            return true;
062        }
063
064        if ( !( other instanceof ArtifactVersion ) )
065        {
066            return false;
067        }
068
069        return compareTo( (ArtifactVersion) other ) == 0;
070    }
071
072    public int compareTo( ArtifactVersion otherVersion )
073    {
074        if ( otherVersion instanceof DefaultArtifactVersion )
075        {
076            return this.comparable.compareTo( ( (DefaultArtifactVersion) otherVersion ).comparable );
077        }
078        else
079        {
080            return compareTo( new DefaultArtifactVersion( otherVersion.toString() ) );
081        }
082    }
083
084    public int getMajorVersion()
085    {
086        return majorVersion != null ? majorVersion : 0;
087    }
088
089    public int getMinorVersion()
090    {
091        return minorVersion != null ? minorVersion : 0;
092    }
093
094    public int getIncrementalVersion()
095    {
096        return incrementalVersion != null ? incrementalVersion : 0;
097    }
098
099    public int getBuildNumber()
100    {
101        return buildNumber != null ? buildNumber : 0;
102    }
103
104    public String getQualifier()
105    {
106        return qualifier;
107    }
108
109    public final void parseVersion( String version )
110    {
111        comparable = new ComparableVersion( version );
112
113        int index = version.indexOf( "-" );
114
115        String part1;
116        String part2 = null;
117
118        if ( index < 0 )
119        {
120            part1 = version;
121        }
122        else
123        {
124            part1 = version.substring( 0, index );
125            part2 = version.substring( index + 1 );
126        }
127
128        if ( part2 != null )
129        {
130            try
131            {
132                if ( ( part2.length() == 1 ) || !part2.startsWith( "0" ) )
133                {
134                    buildNumber = Integer.valueOf( part2 );
135                }
136                else
137                {
138                    qualifier = part2;
139                }
140            }
141            catch ( NumberFormatException e )
142            {
143                qualifier = part2;
144            }
145        }
146
147        if ( ( !part1.contains( "." ) ) && !part1.startsWith( "0" ) )
148        {
149            try
150            {
151                majorVersion = Integer.valueOf( part1 );
152            }
153            catch ( NumberFormatException e )
154            {
155                // qualifier is the whole version, including "-"
156                qualifier = version;
157                buildNumber = null;
158            }
159        }
160        else
161        {
162            boolean fallback = false;
163
164            StringTokenizer tok = new StringTokenizer( part1, "." );
165            try
166            {
167                majorVersion = getNextIntegerToken( tok );
168                if ( tok.hasMoreTokens() )
169                {
170                    minorVersion = getNextIntegerToken( tok );
171                }
172                if ( tok.hasMoreTokens() )
173                {
174                    incrementalVersion = getNextIntegerToken( tok );
175                }
176                if ( tok.hasMoreTokens() )
177                {
178                    qualifier = tok.nextToken();
179                    fallback = Pattern.compile( "\\d+" ).matcher( qualifier ).matches();
180                }
181
182                // string tokenzier won't detect these and ignores them
183                if ( part1.contains( ".." ) || part1.startsWith( "." ) || part1.endsWith( "." ) )
184                {
185                    fallback = true;
186                }
187            }
188            catch ( NumberFormatException e )
189            {
190                fallback = true;
191            }
192
193            if ( fallback )
194            {
195                // qualifier is the whole version, including "-"
196                qualifier = version;
197                majorVersion = null;
198                minorVersion = null;
199                incrementalVersion = null;
200                buildNumber = null;
201            }
202        }
203    }
204
205    private static Integer getNextIntegerToken( StringTokenizer tok )
206    {
207        String s = tok.nextToken();
208        if ( ( s.length() > 1 ) && s.startsWith( "0" ) )
209        {
210            throw new NumberFormatException( "Number part has a leading 0: '" + s + "'" );
211        }
212        return Integer.valueOf( s );
213    }
214
215    @Override
216    public String toString()
217    {
218        return comparable.toString();
219    }
220}