2 *******************************************************************************
3 * Copyright (C) 1996-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.util;
10 import java.util.concurrent.ConcurrentHashMap;
13 * Class to store version numbers of the form major.minor.milli.micro.
17 public final class VersionInfo implements Comparable<VersionInfo>
19 // public data members -------------------------------------------------
25 public static final VersionInfo UNICODE_1_0;
27 * Unicode 1.0.1 version
30 public static final VersionInfo UNICODE_1_0_1;
32 * Unicode 1.1.0 version
35 public static final VersionInfo UNICODE_1_1_0;
37 * Unicode 1.1.5 version
40 public static final VersionInfo UNICODE_1_1_5;
45 public static final VersionInfo UNICODE_2_0;
47 * Unicode 2.1.2 version
50 public static final VersionInfo UNICODE_2_1_2;
52 * Unicode 2.1.5 version
55 public static final VersionInfo UNICODE_2_1_5;
57 * Unicode 2.1.8 version
60 public static final VersionInfo UNICODE_2_1_8;
62 * Unicode 2.1.9 version
65 public static final VersionInfo UNICODE_2_1_9;
70 public static final VersionInfo UNICODE_3_0;
72 * Unicode 3.0.1 version
75 public static final VersionInfo UNICODE_3_0_1;
77 * Unicode 3.1.0 version
80 public static final VersionInfo UNICODE_3_1_0;
82 * Unicode 3.1.1 version
85 public static final VersionInfo UNICODE_3_1_1;
90 public static final VersionInfo UNICODE_3_2;
96 public static final VersionInfo UNICODE_4_0;
99 * Unicode 4.0.1 version
102 public static final VersionInfo UNICODE_4_0_1;
105 * Unicode 4.1 version
108 public static final VersionInfo UNICODE_4_1;
111 * Unicode 5.0 version
114 public static final VersionInfo UNICODE_5_0;
117 * Unicode 5.1 version
120 public static final VersionInfo UNICODE_5_1;
123 * Unicode 5.2 version
126 public static final VersionInfo UNICODE_5_2;
129 * Unicode 6.0 version
132 public static final VersionInfo UNICODE_6_0;
135 * ICU4J current release version
138 public static final VersionInfo ICU_VERSION;
141 * Data version string for ICU's internal data.
142 * Used for appending to data path (e.g. icudt43b)
144 * @deprecated This API is ICU internal only.
146 public static final String ICU_DATA_VERSION_PATH = "48b";
149 * Data version in ICU4J.
151 * @deprecated This API is ICU internal only.
153 public static final VersionInfo ICU_DATA_VERSION;
156 * Collation runtime version (sort key generator, string comparisons).
157 * If the version is different, sort keys for the same string could be different.
158 * This value may change in subsequent releases of ICU.
161 public static final VersionInfo UCOL_RUNTIME_VERSION;
164 * Collation builder code version.
165 * When this is different, the same tailoring might result
166 * in assigning different collation elements to code points.
167 * This value may change in subsequent releases of ICU.
170 public static final VersionInfo UCOL_BUILDER_VERSION;
173 * This is the version of collation tailorings.
174 * This value may change in subsequent releases of ICU.
177 public static final VersionInfo UCOL_TAILORINGS_VERSION;
180 // public methods ------------------------------------------------------
183 * Returns an instance of VersionInfo with the argument version.
184 * @param version version String in the format of "major.minor.milli.micro"
185 * or "major.minor.milli" or "major.minor" or "major",
186 * where major, minor, milli, micro are non-negative numbers
187 * <= 255. If the trailing version numbers are
188 * not specified they are taken as 0s. E.g. Version "3.1" is
189 * equivalent to "3.1.0.0".
190 * @return an instance of VersionInfo with the argument version.
191 * @exception IllegalArgumentException when the argument version
192 * is not in the right format
195 public static VersionInfo getInstance(String version)
197 int length = version.length();
198 int array[] = {0, 0, 0, 0};
202 while (count < 4 && index < length) {
203 char c = version.charAt(index);
209 if (c < 0 || c > 9) {
210 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
217 if (index != length) {
218 throw new IllegalArgumentException(
219 "Invalid version number: String '" + version + "' exceeds version format");
221 for (int i = 0; i < 4; i ++) {
222 if (array[i] < 0 || array[i] > 255) {
223 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
227 return getInstance(array[0], array[1], array[2], array[3]);
231 * Returns an instance of VersionInfo with the argument version.
232 * @param major major version, non-negative number <= 255.
233 * @param minor minor version, non-negative number <= 255.
234 * @param milli milli version, non-negative number <= 255.
235 * @param micro micro version, non-negative number <= 255.
236 * @exception IllegalArgumentException when either arguments are negative or > 255
239 public static VersionInfo getInstance(int major, int minor, int milli,
242 // checks if it is in the hashmap
244 if (major < 0 || major > 255 || minor < 0 || minor > 255 ||
245 milli < 0 || milli > 255 || micro < 0 || micro > 255) {
246 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
248 int version = getInt(major, minor, milli, micro);
249 Integer key = new Integer(version);
250 VersionInfo result = MAP_.get(key);
251 if (result == null) {
252 result = new VersionInfo(version);
253 VersionInfo tmpvi = MAP_.putIfAbsent(key, result);
262 * Returns an instance of VersionInfo with the argument version.
263 * Equivalent to getInstance(major, minor, milli, 0).
264 * @param major major version, non-negative number <= 255.
265 * @param minor minor version, non-negative number <= 255.
266 * @param milli milli version, non-negative number <= 255.
267 * @exception IllegalArgumentException when either arguments are
271 public static VersionInfo getInstance(int major, int minor, int milli)
273 return getInstance(major, minor, milli, 0);
277 * Returns an instance of VersionInfo with the argument version.
278 * Equivalent to getInstance(major, minor, 0, 0).
279 * @param major major version, non-negative number <= 255.
280 * @param minor minor version, non-negative number <= 255.
281 * @exception IllegalArgumentException when either arguments are
285 public static VersionInfo getInstance(int major, int minor)
287 return getInstance(major, minor, 0, 0);
291 * Returns an instance of VersionInfo with the argument version.
292 * Equivalent to getInstance(major, 0, 0, 0).
293 * @param major major version, non-negative number <= 255.
294 * @exception IllegalArgumentException when either arguments are
298 public static VersionInfo getInstance(int major)
300 return getInstance(major, 0, 0, 0);
303 private static VersionInfo javaVersion;
307 * @deprecated This API is ICU internal only.
309 public static VersionInfo javaVersion() {
310 if (javaVersion == null) {
311 String s = System.getProperty("java.version");
313 // preserve only digits, separated by single '.'
314 // ignore over 4 digit sequences
315 // does not test < 255, very odd...
317 char[] chars = s.toCharArray();
318 int r = 0, w = 0, count = 0;
319 boolean numeric = false; // ignore leading non-numerics
320 while (r < chars.length) {
322 if (c < '0' || c > '9') {
325 // only four digit strings allowed
337 while (w > 0 && chars[w-1] == '.') {
341 String vs = new String(chars, 0, w);
343 javaVersion = VersionInfo.getInstance(vs);
349 * Returns the String representative of VersionInfo in the format of
350 * "major.minor.milli.micro"
351 * @return String representative of VersionInfo
354 public String toString()
356 StringBuilder result = new StringBuilder(7);
357 result.append(getMajor());
359 result.append(getMinor());
361 result.append(getMilli());
363 result.append(getMicro());
364 return result.toString();
368 * Returns the major version number
369 * @return the major version number
372 public int getMajor()
374 return (m_version_ >> 24) & LAST_BYTE_MASK_ ;
378 * Returns the minor version number
379 * @return the minor version number
382 public int getMinor()
384 return (m_version_ >> 16) & LAST_BYTE_MASK_ ;
388 * Returns the milli version number
389 * @return the milli version number
392 public int getMilli()
394 return (m_version_ >> 8) & LAST_BYTE_MASK_ ;
398 * Returns the micro version number
399 * @return the micro version number
402 public int getMicro()
404 return m_version_ & LAST_BYTE_MASK_ ;
408 * Checks if this version information is equals to the argument version
409 * @param other object to be compared
410 * @return true if other is equals to this object's version information,
414 public boolean equals(Object other)
416 return other == this;
420 * Compares other with this VersionInfo.
421 * @param other VersionInfo to be compared
422 * @return 0 if the argument is a VersionInfo object that has version
423 * information equals to this object.
424 * Less than 0 if the argument is a VersionInfo object that has
425 * version information greater than this object.
426 * Greater than 0 if the argument is a VersionInfo object that
427 * has version information less than this object.
430 public int compareTo(VersionInfo other)
432 return m_version_ - other.m_version_;
435 // private data members ----------------------------------------------
438 * Unicode data version used by the current release
440 private static final VersionInfo UNICODE_VERSION;
443 * Version number stored as a byte for each of the major, minor, milli and
444 * micro numbers in the 32 bit int.
445 * Most significant for the major and the least significant contains the
448 private int m_version_;
452 private static final ConcurrentHashMap<Integer, VersionInfo> MAP_ = new ConcurrentHashMap<Integer, VersionInfo>();
456 private static final int LAST_BYTE_MASK_ = 0xFF;
458 * Error statement string
460 private static final String INVALID_VERSION_NUMBER_ =
461 "Invalid version number: Version number may be negative or greater than 255";
463 // static declaration ------------------------------------------------
466 * Initialize versions only after MAP_ has been created
469 UNICODE_1_0 = getInstance(1, 0, 0, 0);
470 UNICODE_1_0_1 = getInstance(1, 0, 1, 0);
471 UNICODE_1_1_0 = getInstance(1, 1, 0, 0);
472 UNICODE_1_1_5 = getInstance(1, 1, 5, 0);
473 UNICODE_2_0 = getInstance(2, 0, 0, 0);
474 UNICODE_2_1_2 = getInstance(2, 1, 2, 0);
475 UNICODE_2_1_5 = getInstance(2, 1, 5, 0);
476 UNICODE_2_1_8 = getInstance(2, 1, 8, 0);
477 UNICODE_2_1_9 = getInstance(2, 1, 9, 0);
478 UNICODE_3_0 = getInstance(3, 0, 0, 0);
479 UNICODE_3_0_1 = getInstance(3, 0, 1, 0);
480 UNICODE_3_1_0 = getInstance(3, 1, 0, 0);
481 UNICODE_3_1_1 = getInstance(3, 1, 1, 0);
482 UNICODE_3_2 = getInstance(3, 2, 0, 0);
483 UNICODE_4_0 = getInstance(4, 0, 0, 0);
484 UNICODE_4_0_1 = getInstance(4, 0, 1, 0);
485 UNICODE_4_1 = getInstance(4, 1, 0, 0);
486 UNICODE_5_0 = getInstance(5, 0, 0, 0);
487 UNICODE_5_1 = getInstance(5, 1, 0, 0);
488 UNICODE_5_2 = getInstance(5, 2, 0, 0);
489 UNICODE_6_0 = getInstance(6, 0, 0, 0);
491 ICU_VERSION = getInstance(4, 8, 1, 1);
492 ICU_DATA_VERSION = getInstance(4, 8, 1, 0);
493 UNICODE_VERSION = UNICODE_6_0;
495 UCOL_RUNTIME_VERSION = getInstance(7);
496 UCOL_BUILDER_VERSION = getInstance(8);
497 UCOL_TAILORINGS_VERSION = getInstance(1);
500 // private constructor -----------------------------------------------
503 * Constructor with int
504 * @param compactversion a 32 bit int with each byte representing a number
506 private VersionInfo(int compactversion)
508 m_version_ = compactversion;
512 * Gets the int from the version numbers
513 * @param major non-negative version number
514 * @param minor non-negativeversion number
515 * @param milli non-negativeversion number
516 * @param micro non-negativeversion number
518 private static int getInt(int major, int minor, int milli, int micro)
520 return (major << 24) | (minor << 16) | (milli << 8) | micro;
524 * Main method prints out ICU version information
525 * @param args arguments (currently not used)
527 * @provisional This API might change or be removed in a future release.
529 public static void main(String[] args) {
532 if (ICU_VERSION.getMinor() % 2 != 0) {
533 // Development mile stone
534 int major = ICU_VERSION.getMajor();
535 int minor = ICU_VERSION.getMinor() + 1;
540 icuApiVer = "" + major + "." + minor + "M" + ICU_VERSION.getMilli();
542 icuApiVer = ICU_VERSION.getVersionString(2, 2);
545 System.out.println("International Component for Unicode for Java " + icuApiVer);
547 System.out.println("");
548 System.out.println("Implementation Version: " + ICU_VERSION.getVersionString(2, 4));
549 System.out.println("Unicode Data Version: " + UNICODE_VERSION.getVersionString(2, 4));
550 System.out.println("CLDR Data Version: " + LocaleData.getCLDRVersion().getVersionString(2, 4));
551 System.out.println("Time Zone Data Version: " + TimeZone.getTZDataVersion());
555 * Generate version string separated by dots with
556 * the specified digit width. Version digit 0
557 * after <code>minDigits</code> will be trimmed off.
558 * @param minDigits Minimum number of version digits
559 * @param maxDigits Maximum number of version digits
560 * @return A tailored version string
562 private String getVersionString(int minDigits, int maxDigits) {
563 if (minDigits < 1 || maxDigits < 1
564 || minDigits > 4 || maxDigits > 4 || minDigits > maxDigits) {
565 throw new IllegalArgumentException("Invalid min/maxDigits range");
568 int[] digits = new int[4];
569 digits[0] = getMajor();
570 digits[1] = getMinor();
571 digits[2] = getMilli();
572 digits[3] = getMicro();
574 int numDigits = maxDigits;
575 while (numDigits > minDigits) {
576 if (digits[numDigits - 1] != 0) {
582 StringBuilder verStr = new StringBuilder(7);
583 verStr.append(digits[0]);
584 for (int i = 1; i < numDigits; i++) {
586 verStr.append(digits[i]);
589 return verStr.toString();