001: /*
002: *******************************************************************************
003: * Copyright (C) 1996-2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007:
008: package com.ibm.icu.util;
009:
010: import java.util.HashMap;
011:
012: /**
013: * Class to store version numbers of the form major.minor.milli.micro.
014: * @author synwee
015: * @stable ICU 2.6
016: */
017: public final class VersionInfo {
018: // public data members -------------------------------------------------
019:
020: /**
021: * Unicode 1.0 version
022: * @stable ICU 2.6
023: */
024: public static final VersionInfo UNICODE_1_0;
025: /**
026: * Unicode 1.0.1 version
027: * @stable ICU 2.6
028: */
029: public static final VersionInfo UNICODE_1_0_1;
030: /**
031: * Unicode 1.1.0 version
032: * @stable ICU 2.6
033: */
034: public static final VersionInfo UNICODE_1_1_0;
035: /**
036: * Unicode 1.1.5 version
037: * @stable ICU 2.6
038: */
039: public static final VersionInfo UNICODE_1_1_5;
040: /**
041: * Unicode 2.0 version
042: * @stable ICU 2.6
043: */
044: public static final VersionInfo UNICODE_2_0;
045: /**
046: * Unicode 2.1.2 version
047: * @stable ICU 2.6
048: */
049: public static final VersionInfo UNICODE_2_1_2;
050: /**
051: * Unicode 2.1.5 version
052: * @stable ICU 2.6
053: */
054: public static final VersionInfo UNICODE_2_1_5;
055: /**
056: * Unicode 2.1.8 version
057: * @stable ICU 2.6
058: */
059: public static final VersionInfo UNICODE_2_1_8;
060: /**
061: * Unicode 2.1.9 version
062: * @stable ICU 2.6
063: */
064: public static final VersionInfo UNICODE_2_1_9;
065: /**
066: * Unicode 3.0 version
067: * @stable ICU 2.6
068: */
069: public static final VersionInfo UNICODE_3_0;
070: /**
071: * Unicode 3.0.1 version
072: * @stable ICU 2.6
073: */
074: public static final VersionInfo UNICODE_3_0_1;
075: /**
076: * Unicode 3.1.0 version
077: * @stable ICU 2.6
078: */
079: public static final VersionInfo UNICODE_3_1_0;
080: /**
081: * Unicode 3.1.1 version
082: * @stable ICU 2.6
083: */
084: public static final VersionInfo UNICODE_3_1_1;
085: /**
086: * Unicode 3.2 version
087: * @stable ICU 2.6
088: */
089: public static final VersionInfo UNICODE_3_2;
090:
091: /**
092: * Unicode 4.0 version
093: * @stable ICU 2.6
094: */
095: public static final VersionInfo UNICODE_4_0;
096:
097: /**
098: * Unicode 4.0.1 version
099: * @draft ICU 3.4
100: * @provisional This API might change or be removed in a future release.
101: */
102: public static final VersionInfo UNICODE_4_0_1;
103:
104: /**
105: * Unicode 4.1 version
106: * @draft ICU 3.4
107: * @provisional This API might change or be removed in a future release.
108: */
109: public static final VersionInfo UNICODE_4_1;
110:
111: /**
112: * Unicode 5.0 version
113: * @draft ICU 3.4
114: * @provisional This API might change or be removed in a future release.
115: */
116: public static final VersionInfo UNICODE_5_0;
117:
118: /**
119: * ICU4J current release version
120: * @stable ICU 2.8
121: */
122: public static final VersionInfo ICU_VERSION;
123:
124: /**
125: * Data version string for ICU's internal data
126: * @internal
127: * @deprecated This API is ICU internal only.
128: */
129: public static final String ICU_DATA_VERSION = "36b";
130:
131: /**
132: * ICU4J collator runtime version
133: * @stable ICU 2.8
134: */
135: public static final VersionInfo UCOL_RUNTIME_VERSION;
136:
137: /**
138: * ICU4J collator builder version
139: * @stable ICU 2.8
140: */
141: public static final VersionInfo UCOL_BUILDER_VERSION;
142:
143: /**
144: * ICU4J collator tailorings version
145: * @stable ICU 2.8
146: */
147: public static final VersionInfo UCOL_TAILORINGS_VERSION;
148:
149: // public methods ------------------------------------------------------
150:
151: /**
152: * Returns an instance of VersionInfo with the argument version.
153: * @param version version String in the format of "major.minor.milli.micro"
154: * or "major.minor.milli" or "major.minor" or "major",
155: * where major, minor, milli, micro are non-negative numbers
156: * <= 255. If the trailing version numbers are
157: * not specified they are taken as 0s. E.g. Version "3.1" is
158: * equivalent to "3.1.0.0".
159: * @return an instance of VersionInfo with the argument version.
160: * @exception throws an IllegalArgumentException when the argument version
161: * is not in the right format
162: * @stable ICU 2.6
163: */
164: public static VersionInfo getInstance(String version) {
165: int length = version.length();
166: int array[] = { 0, 0, 0, 0 };
167: int count = 0;
168: int index = 0;
169:
170: while (count < 4 && index < length) {
171: char c = version.charAt(index);
172: if (c == '.') {
173: count++;
174: } else {
175: c -= '0';
176: if (c < 0 || c > 9) {
177: throw new IllegalArgumentException(
178: INVALID_VERSION_NUMBER_);
179: }
180: array[count] *= 10;
181: array[count] += c;
182: }
183: index++;
184: }
185: if (index != length) {
186: throw new IllegalArgumentException(
187: "Invalid version number: String '" + version
188: + "' exceeds version format");
189: }
190: for (int i = 0; i < 4; i++) {
191: if (array[i] < 0 || array[i] > 255) {
192: throw new IllegalArgumentException(
193: INVALID_VERSION_NUMBER_);
194: }
195: }
196:
197: return getInstance(array[0], array[1], array[2], array[3]);
198: }
199:
200: /**
201: * Returns an instance of VersionInfo with the argument version.
202: * @param major major version, non-negative number <= 255.
203: * @param minor minor version, non-negative number <= 255.
204: * @param milli milli version, non-negative number <= 255.
205: * @param micro micro version, non-negative number <= 255.
206: * @exception throws an IllegalArgumentException when either arguments are
207: * negative or > 255
208: * @stable ICU 2.6
209: */
210: public static VersionInfo getInstance(int major, int minor,
211: int milli, int micro) {
212: // checks if it is in the hashmap
213: // else
214: if (major < 0 || major > 255 || minor < 0 || minor > 255
215: || milli < 0 || milli > 255 || micro < 0 || micro > 255) {
216: throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
217: }
218: int version = getInt(major, minor, milli, micro);
219: Integer key = new Integer(version);
220: Object result = MAP_.get(key);
221: if (result == null) {
222: result = new VersionInfo(version);
223: MAP_.put(key, result);
224: }
225: return (VersionInfo) result;
226: }
227:
228: /**
229: * Returns an instance of VersionInfo with the argument version.
230: * Equivalent to getInstance(major, minor, milli, 0).
231: * @param major major version, non-negative number <= 255.
232: * @param minor minor version, non-negative number <= 255.
233: * @param milli milli version, non-negative number <= 255.
234: * @exception throws an IllegalArgumentException when either arguments are
235: * negative or > 255
236: * @stable ICU 2.6
237: */
238: public static VersionInfo getInstance(int major, int minor,
239: int milli) {
240: return getInstance(major, minor, milli, 0);
241: }
242:
243: /**
244: * Returns an instance of VersionInfo with the argument version.
245: * Equivalent to getInstance(major, minor, 0, 0).
246: * @param major major version, non-negative number <= 255.
247: * @param minor minor version, non-negative number <= 255.
248: * @exception throws an IllegalArgumentException when either arguments are
249: * negative or > 255
250: * @stable ICU 2.6
251: */
252: public static VersionInfo getInstance(int major, int minor) {
253: return getInstance(major, minor, 0, 0);
254: }
255:
256: /**
257: * Returns an instance of VersionInfo with the argument version.
258: * Equivalent to getInstance(major, 0, 0, 0).
259: * @param major major version, non-negative number <= 255.
260: * @exception throws an IllegalArgumentException when either arguments are
261: * negative or > 255
262: * @stable ICU 2.6
263: */
264: public static VersionInfo getInstance(int major) {
265: return getInstance(major, 0, 0, 0);
266: }
267:
268: private static VersionInfo javaVersion;
269:
270: /**
271: * @internal
272: * @deprecated This API is ICU internal only.
273: */
274: public static VersionInfo javaVersion() {
275: if (javaVersion == null) {
276: String s = System.getProperty("java.version");
277: // clean string
278: // preserve only digits, separated by single '.'
279: // ignore over 4 digit sequences
280: // does not test < 255, very odd...
281:
282: char[] chars = s.toCharArray();
283: int r = 0, w = 0, count = 0;
284: boolean numeric = false; // ignore leading non-numerics
285: while (r < chars.length) {
286: char c = chars[r++];
287: if (c < '0' || c > '9') {
288: if (numeric) {
289: if (count == 3) {
290: // only four digit strings allowed
291: break;
292: }
293: numeric = false;
294: chars[w++] = '.';
295: ++count;
296: }
297: } else {
298: numeric = true;
299: chars[w++] = c;
300: }
301: }
302: while (w > 0 && chars[w - 1] == '.') {
303: --w;
304: }
305:
306: String vs = new String(chars, 0, w);
307:
308: javaVersion = VersionInfo.getInstance(vs);
309: }
310: return javaVersion;
311: }
312:
313: /**
314: * Returns the String representative of VersionInfo in the format of
315: * "major.minor.milli.micro"
316: * @return String representative of VersionInfo
317: * @stable ICU 2.6
318: */
319: public String toString() {
320: StringBuffer result = new StringBuffer(7);
321: result.append(getMajor());
322: result.append('.');
323: result.append(getMinor());
324: result.append('.');
325: result.append(getMilli());
326: result.append('.');
327: result.append(getMicro());
328: return result.toString();
329: }
330:
331: /**
332: * Returns the major version number
333: * @return the major version number
334: * @stable ICU 2.6
335: */
336: public int getMajor() {
337: return (m_version_ >> 24) & LAST_BYTE_MASK_;
338: }
339:
340: /**
341: * Returns the minor version number
342: * @return the minor version number
343: * @stable ICU 2.6
344: */
345: public int getMinor() {
346: return (m_version_ >> 16) & LAST_BYTE_MASK_;
347: }
348:
349: /**
350: * Returns the milli version number
351: * @return the milli version number
352: * @stable ICU 2.6
353: */
354: public int getMilli() {
355: return (m_version_ >> 8) & LAST_BYTE_MASK_;
356: }
357:
358: /**
359: * Returns the micro version number
360: * @return the micro version number
361: * @stable ICU 2.6
362: */
363: public int getMicro() {
364: return m_version_ & LAST_BYTE_MASK_;
365: }
366:
367: /**
368: * Checks if this version information is equals to the argument version
369: * @param other object to be compared
370: * @return true if other is equals to this object's version information,
371: * false otherwise
372: * @stable ICU 2.6
373: */
374: public boolean equals(Object other) {
375: return other == this ;
376: }
377:
378: /**
379: * Compares other with this VersionInfo.
380: * @param other VersionInfo to be compared
381: * @return 0 if the argument is a VersionInfo object that has version
382: * information equals to this object.
383: * Less than 0 if the argument is a VersionInfo object that has
384: * version information greater than this object.
385: * Greater than 0 if the argument is a VersionInfo object that
386: * has version information less than this object.
387: * @stable ICU 2.6
388: */
389: public int compareTo(VersionInfo other) {
390: return m_version_ - other.m_version_;
391: }
392:
393: // private data members ----------------------------------------------
394:
395: /**
396: * Version number stored as a byte for each of the major, minor, milli and
397: * micro numbers in the 32 bit int.
398: * Most significant for the major and the least significant contains the
399: * micro numbers.
400: */
401: private int m_version_;
402: /**
403: * Map of singletons
404: */
405: private static final HashMap MAP_ = new HashMap();
406: /**
407: * Last byte mask
408: */
409: private static final int LAST_BYTE_MASK_ = 0xFF;
410: /**
411: * Error statement string
412: */
413: private static final String INVALID_VERSION_NUMBER_ = "Invalid version number: Version number may be negative or greater than 255";
414:
415: // static declaration ------------------------------------------------
416:
417: /**
418: * Initialize versions only after MAP_ has been created
419: */
420: static {
421: UNICODE_1_0 = getInstance(1, 0, 0, 0);
422: UNICODE_1_0_1 = getInstance(1, 0, 1, 0);
423: UNICODE_1_1_0 = getInstance(1, 1, 0, 0);
424: UNICODE_1_1_5 = getInstance(1, 1, 5, 0);
425: UNICODE_2_0 = getInstance(2, 0, 0, 0);
426: UNICODE_2_1_2 = getInstance(2, 1, 2, 0);
427: UNICODE_2_1_5 = getInstance(2, 1, 5, 0);
428: UNICODE_2_1_8 = getInstance(2, 1, 8, 0);
429: UNICODE_2_1_9 = getInstance(2, 1, 9, 0);
430: UNICODE_3_0 = getInstance(3, 0, 0, 0);
431: UNICODE_3_0_1 = getInstance(3, 0, 1, 0);
432: UNICODE_3_1_0 = getInstance(3, 1, 0, 0);
433: UNICODE_3_1_1 = getInstance(3, 1, 1, 0);
434: UNICODE_3_2 = getInstance(3, 2, 0, 0);
435: UNICODE_4_0 = getInstance(4, 0, 0, 0);
436: UNICODE_4_0_1 = getInstance(4, 0, 1, 0);
437: UNICODE_4_1 = getInstance(4, 1, 0, 0);
438: UNICODE_5_0 = getInstance(4, 1, 0, 0);
439: ICU_VERSION = getInstance(3, 6, 0, 0);
440: UCOL_RUNTIME_VERSION = getInstance(6);
441: UCOL_BUILDER_VERSION = getInstance(7);
442: UCOL_TAILORINGS_VERSION = getInstance(1);
443: }
444:
445: // private constructor -----------------------------------------------
446:
447: /**
448: * Constructor with int
449: * @param compactversion a 32 bit int with each byte representing a number
450: */
451: private VersionInfo(int compactversion) {
452: m_version_ = compactversion;
453: }
454:
455: /**
456: * Gets the int from the version numbers
457: * @param major non-negative version number
458: * @param minor non-negativeversion number
459: * @param milli non-negativeversion number
460: * @param micro non-negativeversion number
461: */
462: private static int getInt(int major, int minor, int milli, int micro) {
463: return (major << 24) | (minor << 16) | (milli << 8) | micro;
464: }
465: }
|