KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > osgi > framework > Version


1 /*
2  * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Version.java,v 1.17 2007/02/20 00:07:22 hargrave Exp $
3  *
4  * Copyright (c) OSGi Alliance (2004, 2007). All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.osgi.framework;
20
21 import java.util.NoSuchElementException JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23
24 /**
25  * Version identifier for bundles and packages.
26  *
27  * <p>
28  * Version identifiers have four components.
29  * <ol>
30  * <li>Major version. A non-negative integer.</li>
31  * <li>Minor version. A non-negative integer.</li>
32  * <li>Micro version. A non-negative integer.</li>
33  * <li>Qualifier. A text string. See <code>Version(String)</code> for the
34  * format of the qualifier string.</li>
35  * </ol>
36  *
37  * <p>
38  * <code>Version</code> objects are immutable.
39  *
40  * @since 1.3
41  * @Immutable
42  * @version $Revision: 1.17 $
43  */

44
45 public class Version implements Comparable JavaDoc {
46     private final int major;
47     private final int minor;
48     private final int micro;
49     private final String JavaDoc qualifier;
50     private static final String JavaDoc SEPARATOR = "."; //$NON-NLS-1$
51

52     /**
53      * The empty version "0.0.0". Equivalent to calling
54      * <code>new Version(0,0,0)</code>.
55      */

56     public static final Version emptyVersion = new Version(0, 0, 0);
57
58     /**
59      * Creates a version identifier from the specified numerical components.
60      *
61      * <p>
62      * The qualifier is set to the empty string.
63      *
64      * @param major Major component of the version identifier.
65      * @param minor Minor component of the version identifier.
66      * @param micro Micro component of the version identifier.
67      * @throws IllegalArgumentException If the numerical components are
68      * negative.
69      */

70     public Version(int major, int minor, int micro) {
71         this(major, minor, micro, null);
72     }
73
74     /**
75      * Creates a version identifier from the specifed components.
76      *
77      * @param major Major component of the version identifier.
78      * @param minor Minor component of the version identifier.
79      * @param micro Micro component of the version identifier.
80      * @param qualifier Qualifier component of the version identifier. If
81      * <code>null</code> is specified, then the qualifier will be set
82      * to the empty string.
83      * @throws IllegalArgumentException If the numerical components are negative
84      * or the qualifier string is invalid.
85      */

86     public Version(int major, int minor, int micro, String JavaDoc qualifier) {
87         if (qualifier == null) {
88             qualifier = ""; //$NON-NLS-1$
89
}
90
91         this.major = major;
92         this.minor = minor;
93         this.micro = micro;
94         this.qualifier = qualifier;
95         validate();
96     }
97
98     /**
99      * Created a version identifier from the specified string.
100      *
101      * <p>
102      * Here is the grammar for version strings.
103      *
104      * <pre>
105      * version ::= major('.'minor('.'micro('.'qualifier)?)?)?
106      * major ::= digit+
107      * minor ::= digit+
108      * micro ::= digit+
109      * qualifier ::= (alpha|digit|'_'|'-')+
110      * digit ::= [0..9]
111      * alpha ::= [a..zA..Z]
112      * </pre>
113      *
114      * There must be no whitespace in version.
115      *
116      * @param version String representation of the version identifier.
117      * @throws IllegalArgumentException If <code>version</code> is improperly
118      * formatted.
119      */

120     public Version(String JavaDoc version) {
121         int major = 0;
122         int minor = 0;
123         int micro = 0;
124         String JavaDoc qualifier = ""; //$NON-NLS-1$
125

126         try {
127             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(version, SEPARATOR, true);
128             major = Integer.parseInt(st.nextToken());
129
130             if (st.hasMoreTokens()) {
131                 st.nextToken(); // consume delimiter
132
minor = Integer.parseInt(st.nextToken());
133
134                 if (st.hasMoreTokens()) {
135                     st.nextToken(); // consume delimiter
136
micro = Integer.parseInt(st.nextToken());
137
138                     if (st.hasMoreTokens()) {
139                         st.nextToken(); // consume delimiter
140
qualifier = st.nextToken();
141
142                         if (st.hasMoreTokens()) {
143                             throw new IllegalArgumentException JavaDoc("invalid format"); //$NON-NLS-1$
144
}
145                     }
146                 }
147             }
148         }
149         catch (NoSuchElementException JavaDoc e) {
150             throw new IllegalArgumentException JavaDoc("invalid format"); //$NON-NLS-1$
151
}
152
153         this.major = major;
154         this.minor = minor;
155         this.micro = micro;
156         this.qualifier = qualifier;
157         validate();
158     }
159
160     /**
161      * Called by the Version constructors to validate the version components.
162      *
163      * @throws IllegalArgumentException If the numerical components are negative
164      * or the qualifier string is invalid.
165      */

166     private void validate() {
167         if (major < 0) {
168             throw new IllegalArgumentException JavaDoc("negative major"); //$NON-NLS-1$
169
}
170         if (minor < 0) {
171             throw new IllegalArgumentException JavaDoc("negative minor"); //$NON-NLS-1$
172
}
173         if (micro < 0) {
174             throw new IllegalArgumentException JavaDoc("negative micro"); //$NON-NLS-1$
175
}
176         int length = qualifier.length();
177         for (int i = 0; i < length; i++) {
178             if ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".indexOf(qualifier.charAt(i)) == -1) { //$NON-NLS-1$
179
throw new IllegalArgumentException JavaDoc("invalid qualifier"); //$NON-NLS-1$
180
}
181         }
182     }
183
184     /**
185      * Parses a version identifier from the specified string.
186      *
187      * <p>
188      * See <code>Version(String)</code> for the format of the version string.
189      *
190      * @param version String representation of the version identifier. Leading
191      * and trailing whitespace will be ignored.
192      * @return A <code>Version</code> object representing the version
193      * identifier. If <code>version</code> is <code>null</code> or
194      * the empty string then <code>emptyVersion</code> will be
195      * returned.
196      * @throws IllegalArgumentException If <code>version</code> is improperly
197      * formatted.
198      */

199     public static Version parseVersion(String JavaDoc version) {
200         if (version == null) {
201             return emptyVersion;
202         }
203
204         version = version.trim();
205         if (version.length() == 0) {
206             return emptyVersion;
207         }
208
209         return new Version(version);
210     }
211
212     /**
213      * Returns the major component of this version identifier.
214      *
215      * @return The major component.
216      */

217     public int getMajor() {
218         return major;
219     }
220
221     /**
222      * Returns the minor component of this version identifier.
223      *
224      * @return The minor component.
225      */

226     public int getMinor() {
227         return minor;
228     }
229
230     /**
231      * Returns the micro component of this version identifier.
232      *
233      * @return The micro component.
234      */

235     public int getMicro() {
236         return micro;
237     }
238
239     /**
240      * Returns the qualifier component of this version identifier.
241      *
242      * @return The qualifier component.
243      */

244     public String JavaDoc getQualifier() {
245         return qualifier;
246     }
247
248     /**
249      * Returns the string representation of this version identifier.
250      *
251      * <p>
252      * The format of the version string will be <code>major.minor.micro</code>
253      * if qualifier is the empty string or
254      * <code>major.minor.micro.qualifier</code> otherwise.
255      *
256      * @return The string representation of this version identifier.
257      */

258     public String JavaDoc toString() {
259         String JavaDoc base = major + SEPARATOR + minor + SEPARATOR + micro;
260         if (qualifier.length() == 0) { //$NON-NLS-1$
261
return base;
262         }
263         else {
264             return base + SEPARATOR + qualifier;
265         }
266     }
267
268     /**
269      * Returns a hash code value for the object.
270      *
271      * @return An integer which is a hash code value for this object.
272      */

273     public int hashCode() {
274         return (major << 24) + (minor << 16) + (micro << 8)
275                 + qualifier.hashCode();
276     }
277
278     /**
279      * Compares this <code>Version</code> object to another object.
280      *
281      * <p>
282      * A version is considered to be <b>equal to </b> another version if the
283      * major, minor and micro components are equal and the qualifier component
284      * is equal (using <code>String.equals</code>).
285      *
286      * @param object The <code>Version</code> object to be compared.
287      * @return <code>true</code> if <code>object</code> is a
288      * <code>Version</code> and is equal to this object;
289      * <code>false</code> otherwise.
290      */

291     public boolean equals(Object JavaDoc object) {
292         if (object == this) { // quicktest
293
return true;
294         }
295
296         if (!(object instanceof Version)) {
297             return false;
298         }
299
300         Version other = (Version) object;
301         return (major == other.major) && (minor == other.minor)
302                 && (micro == other.micro) && qualifier.equals(other.qualifier);
303     }
304
305     /**
306      * Compares this <code>Version</code> object to another object.
307      *
308      * <p>
309      * A version is considered to be <b>less than </b> another version if its
310      * major component is less than the other version's major component, or the
311      * major components are equal and its minor component is less than the other
312      * version's minor component, or the major and minor components are equal
313      * and its micro component is less than the other version's micro component,
314      * or the major, minor and micro components are equal and it's qualifier
315      * component is less than the other version's qualifier component (using
316      * <code>String.compareTo</code>).
317      *
318      * <p>
319      * A version is considered to be <b>equal to</b> another version if the
320      * major, minor and micro components are equal and the qualifier component
321      * is equal (using <code>String.compareTo</code>).
322      *
323      * @param object The <code>Version</code> object to be compared.
324      * @return A negative integer, zero, or a positive integer if this object is
325      * less than, equal to, or greater than the specified
326      * <code>Version</code> object.
327      * @throws ClassCastException If the specified object is not a
328      * <code>Version</code>.
329      */

330     public int compareTo(Object JavaDoc object) {
331         if (object == this) { // quicktest
332
return 0;
333         }
334
335         Version other = (Version) object;
336
337         int result = major - other.major;
338         if (result != 0) {
339             return result;
340         }
341
342         result = minor - other.minor;
343