Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javax/ide/util/Version.java


1   package javax.ide.util;
2   
3   import java.util.HashMap;
4   import java.util.StringTokenizer;
5   
6   /**
7    * Represents the version number of an extension or component. A version
8    * number is an immutable ordered sequence of integer values.
9    * <p>
10   * Version numbers can be represented in two forms. When you construct a 
11   * new Version object using a String representation of the version number, this
12   * String representation is stored and returned by the {@link #toString()} method.
13   * This form of the version number will retain any redundant leading zeros in
14   * any of the integer values which make up the version number.
15   * <p>
16   * Conversely, in the <i>canonical</i> form, a version number does not retain
17   * leading zeros. The canonical form of <tt>new Version( "1.02.03" )</tt> would
18   * be <tt>"1.2.3"</tt>. You can retrieve the canonical form of a Version object
19   * using the {@link #toCanonicalString()} method.
20   */
21  public final class Version implements Comparable
22  {
23    private static final HashMap _convertCache = new HashMap( 100 );
24    private final int[] _numbers;
25    private final String _versionLabel;
26    
27    /**
28     * Constructs a Version object from a String representation.
29     * 
30     * @param versionLabel a String representation of a version number. This must
31     *    start with an integer and contain only integers and periods.
32     * @throws NumberFormatException if the specified version label contains 
33     *    non-numeric characters other than periods.
34     */
35    public Version( String versionLabel ) throws NumberFormatException
36    {
37      _versionLabel = versionLabel;
38      _numbers = convert( versionLabel );
39    }
40    
41    /**
42     * Converts this Version to an int array.
43     * 
44     * @return a newly allocated int array whose length is equal to the number
45     *    of integer values in this version object and whose contents are
46     *    the integer values represented by this version.
47     */
48    public int[] toIntArray()
49    {
50      int[] numbers = new int[ _numbers.length ];
51      System.arraycopy( _numbers, 0, numbers, 0, _numbers.length );
52      
53      return numbers;
54    }
55    
56    
57    //--------------------------------------------------------------------------
58    // Comparable interface.
59    //--------------------------------------------------------------------------
60    
61    /**
62     * Compare this version object with another version object. 
63     * Comparison of two version numbers applies to the canonical form of the 
64     * version number. For example, the result of evaluating the expression
65     * <tt>new Version( "1.05.07" ).compareTo( new Version( "1.5.0006" ) )</tt> is
66     * a positive integer indicating that version 1.5.7 is greater than 1.5.6.
67     * 
68     * @param other another instance of Version.
69     * @return true if this version is equal to the other version.
70     */  
71    public int compareTo( Object other )
72    {
73      if ( this == other )
74      {
75        return 0;
76      }
77  
78      int[] otherNumbers = ((Version) other)._numbers;
79      int len1 = _numbers.length;
80      int len2 = otherNumbers.length;
81      int max = Math.max(len1, len2);
82  
83      for ( int i = 0; i < max; i++ ) 
84      {
85          int d1 = (i < len1 ? _numbers[i] : 0);
86          int d2 = (i < len2 ? otherNumbers[i] : 0);
87          
88          if (d1 != d2) 
89          {
90              return d1 - d2;
91          }
92      }
93      return 0;
94    }
95  
96    //--------------------------------------------------------------------------
97    // Object overrides.
98    //--------------------------------------------------------------------------
99    
100   /**
101    * Get this version number as a string. The string returned is equal to the
102    * string provided in the constructor. For example, 
103    * <tt>new Version( "1.05.06" ).toString();</tt> would return 
104    * <tt>"1.05.06"</tt>.
105    * 
106    * @return the string representation of this version.
107    * @see #toCanonicalString()
108    */
109   public String toString()
110   {
111     return _versionLabel;
112   }
113   
114   /**
115    * Get this version number as a canonicalized string. Leading zeros will be
116    * removed from all numerical components of the version. For example, 
117    * <tt>new Version( "1.05.06" ).toString();</tt> would return 
118    * <tt>"1.5.6"</tt>.
119    * 
120    * @return a canonical string representation of this version.
121    * @see #toString()
122    */
123   public String toCanonicalString()
124   {
125     final int len = _numbers.length;
126     final StringBuffer rtn = new StringBuffer( len * 3 ).append( _numbers[0] );
127 
128     for ( int i = 1; i < len; i++ ) 
129     {
130         rtn.append('.'); // NORES
131         rtn.append( _numbers[ i ] );
132     }
133 
134     return rtn.toString();
135   }
136   
137   /**
138    * Compare this version object with another version object for equality. 
139    * Equality of two version numbers applies to the canonical form of the 
140    * version number. For example, the result of evaluating the expression
141    * <tt>new Version( "1.05.06" ).equals( new Version( "1.5.0006" ) )</tt> is
142    * <tt>true</tt>.
143    * 
144    * @param other another instance of Version.
145    * @return true if this version is equal to the other version.
146    */
147   public boolean equals( Object other )
148   {
149     if ( other == this )
150     {
151       return true;
152     }
153     if ( !(other instanceof Version) )
154     {
155       return false;
156     }
157     
158     final Version version = (Version)other;
159     final int len = _numbers.length;
160 
161     if ( len != version._numbers.length )
162     {
163       return false;
164     }
165     
166     for ( int i = 0; i < len; i++ )
167     {
168       if ( _numbers[ i ] != version._numbers[ i ] )
169       {
170         return false;
171       }
172     }
173 
174     return true;
175   }
176   
177   public int hashCode() 
178   {
179     int hash = 925295;
180     final int len = _numbers.length;
181 
182     for ( int i = 0; i < len; i++ ) 
183     {
184       hash = 37*hash + i;
185     }
186 
187     return hash;
188   }
189 
190   //---------------------------------------------------------------------------
191   // Private methods.
192   //---------------------------------------------------------------------------
193 
194   private int[] convert( String versionLabel ) throws NumberFormatException
195   {
196     int[] numbers = (int[])_convertCache.get( versionLabel );
197     
198     if ( numbers != null )
199     {
200       return numbers;
201     }
202 
203     final StringTokenizer tokenizer = 
204                           new StringTokenizer(versionLabel, ".", true); // NORES
205     final int count = tokenizer.countTokens() + 1;
206     
207     if ( count % 2 != 0 ) 
208     {
209       throw new NumberFormatException(
210                               " Malformed version specification: `" //NORES
211                               + versionLabel + "`.");               //NORES
212     }
213 
214     numbers = new int[ count / 2 ];
215     boolean expectingNumber = true;
216     int i = 0;
217     
218     while ( tokenizer.hasMoreTokens() ) 
219     {
220       final String token = tokenizer.nextToken();
221       
222       if (expectingNumber) 
223       {
224           expectingNumber = false;
225           int piece = Integer.parseInt( token );
226 
227           if (piece < 0) 
228           {
229             throw new NumberFormatException( 
230                             "Malformed version specification: `"  //NORES
231                             + piece + "`."                        //NORES
232                             + "Version number must be > 0.");     //NORES
233           }
234           numbers[ i++ ] = piece;
235       } 
236       else 
237       { 
238         expectingNumber = true;
239       }
240     }
241 
242     return numbers;
243   }
244   
245 }