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; 024import java.util.NoSuchElementException; 025 026/** 027 * Default implementation of artifact versioning. 028 * 029 * @author <a href="mailto:brett@apache.org">Brett Porter</a> 030 */ 031public class DefaultArtifactVersion 032 implements ArtifactVersion 033{ 034 private Integer majorVersion; 035 036 private Integer minorVersion; 037 038 private Integer incrementalVersion; 039 040 private Integer buildNumber; 041 042 private String qualifier; 043 044 private ComparableVersion comparable; 045 046 public DefaultArtifactVersion( String version ) 047 { 048 parseVersion( version ); 049 } 050 051 @Override 052 public int hashCode() 053 { 054 return 11 + comparable.hashCode(); 055 } 056 057 @Override 058 public boolean equals( Object other ) 059 { 060 if ( this == other ) 061 { 062 return true; 063 } 064 065 if ( !( other instanceof ArtifactVersion ) ) 066 { 067 return false; 068 } 069 070 return compareTo( (ArtifactVersion) other ) == 0; 071 } 072 073 public int compareTo( ArtifactVersion otherVersion ) 074 { 075 if ( otherVersion instanceof DefaultArtifactVersion ) 076 { 077 return this.comparable.compareTo( ( (DefaultArtifactVersion) otherVersion ).comparable ); 078 } 079 else 080 { 081 return compareTo( new DefaultArtifactVersion( otherVersion.toString() ) ); 082 } 083 } 084 085 public int getMajorVersion() 086 { 087 return majorVersion != null ? majorVersion : 0; 088 } 089 090 public int getMinorVersion() 091 { 092 return minorVersion != null ? minorVersion : 0; 093 } 094 095 public int getIncrementalVersion() 096 { 097 return incrementalVersion != null ? incrementalVersion : 0; 098 } 099 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 tokenzier 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}