2 *******************************************************************************
3 * Copyright (C) 1996-2013, 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 * Unicode 6.1 version
138 public static final VersionInfo UNICODE_6_1;
141 * Unicode 6.2 version
144 public static final VersionInfo UNICODE_6_2;
147 * Unicode 6.3 version
150 public static final VersionInfo UNICODE_6_3;
153 * ICU4J current release version
156 public static final VersionInfo ICU_VERSION;
159 * Data version string for ICU's internal data.
160 * Used for appending to data path (e.g. icudt43b)
162 * @deprecated This API is ICU internal only.
164 public static final String ICU_DATA_VERSION_PATH = "52b";
167 * Data version in ICU4J.
169 * @deprecated This API is ICU internal only.
171 public static final VersionInfo ICU_DATA_VERSION;
174 * Collation runtime version (sort key generator, string comparisons).
175 * If the version is different, sort keys for the same string could be different.
176 * This value may change in subsequent releases of ICU.
179 public static final VersionInfo UCOL_RUNTIME_VERSION;
182 * Collation builder code version.
183 * When this is different, the same tailoring might result
184 * in assigning different collation elements to code points.
185 * This value may change in subsequent releases of ICU.
188 public static final VersionInfo UCOL_BUILDER_VERSION;
191 * This is the version of collation tailorings.
192 * This value may change in subsequent releases of ICU.
195 public static final VersionInfo UCOL_TAILORINGS_VERSION;
198 // public methods ------------------------------------------------------
201 * Returns an instance of VersionInfo with the argument version.
202 * @param version version String in the format of "major.minor.milli.micro"
203 * or "major.minor.milli" or "major.minor" or "major",
204 * where major, minor, milli, micro are non-negative numbers
205 * <= 255. If the trailing version numbers are
206 * not specified they are taken as 0s. E.g. Version "3.1" is
207 * equivalent to "3.1.0.0".
208 * @return an instance of VersionInfo with the argument version.
209 * @exception IllegalArgumentException when the argument version
210 * is not in the right format
213 public static VersionInfo getInstance(String version)
215 int length = version.length();
216 int array[] = {0, 0, 0, 0};
220 while (count < 4 && index < length) {
221 char c = version.charAt(index);
227 if (c < 0 || c > 9) {
228 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
235 if (index != length) {
236 throw new IllegalArgumentException(
237 "Invalid version number: String '" + version + "' exceeds version format");
239 for (int i = 0; i < 4; i ++) {
240 if (array[i] < 0 || array[i] > 255) {
241 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
245 return getInstance(array[0], array[1], array[2], array[3]);
249 * Returns an instance of VersionInfo with the argument version.
250 * @param major major version, non-negative number <= 255.
251 * @param minor minor version, non-negative number <= 255.
252 * @param milli milli version, non-negative number <= 255.
253 * @param micro micro version, non-negative number <= 255.
254 * @exception IllegalArgumentException when either arguments are negative or > 255
257 public static VersionInfo getInstance(int major, int minor, int milli,
260 // checks if it is in the hashmap
262 if (major < 0 || major > 255 || minor < 0 || minor > 255 ||
263 milli < 0 || milli > 255 || micro < 0 || micro > 255) {
264 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
266 int version = getInt(major, minor, milli, micro);
267 Integer key = Integer.valueOf(version);
268 VersionInfo result = MAP_.get(key);
269 if (result == null) {
270 result = new VersionInfo(version);
271 VersionInfo tmpvi = MAP_.putIfAbsent(key, result);
280 * Returns an instance of VersionInfo with the argument version.
281 * Equivalent to getInstance(major, minor, milli, 0).
282 * @param major major version, non-negative number <= 255.
283 * @param minor minor version, non-negative number <= 255.
284 * @param milli milli version, non-negative number <= 255.
285 * @exception IllegalArgumentException when either arguments are
289 public static VersionInfo getInstance(int major, int minor, int milli)
291 return getInstance(major, minor, milli, 0);
295 * Returns an instance of VersionInfo with the argument version.
296 * Equivalent to getInstance(major, minor, 0, 0).
297 * @param major major version, non-negative number <= 255.
298 * @param minor minor version, non-negative number <= 255.
299 * @exception IllegalArgumentException when either arguments are
303 public static VersionInfo getInstance(int major, int minor)
305 return getInstance(major, minor, 0, 0);
309 * Returns an instance of VersionInfo with the argument version.
310 * Equivalent to getInstance(major, 0, 0, 0).
311 * @param major major version, non-negative number <= 255.
312 * @exception IllegalArgumentException when either arguments are
316 public static VersionInfo getInstance(int major)
318 return getInstance(major, 0, 0, 0);
321 private static volatile VersionInfo javaVersion;
325 * @deprecated This API is ICU internal only.
327 public static VersionInfo javaVersion() {
328 if (javaVersion == null) {
329 synchronized(VersionInfo.class) {
330 if (javaVersion == null) {
331 String s = System.getProperty("java.version");
333 // preserve only digits, separated by single '.'
334 // ignore over 4 digit sequences
335 // does not test < 255, very odd...
337 char[] chars = s.toCharArray();
338 int r = 0, w = 0, count = 0;
339 boolean numeric = false; // ignore leading non-numerics
340 while (r < chars.length) {
342 if (c < '0' || c > '9') {
345 // only four digit strings allowed
357 while (w > 0 && chars[w-1] == '.') {
361 String vs = new String(chars, 0, w);
363 javaVersion = VersionInfo.getInstance(vs);
371 * Returns the String representative of VersionInfo in the format of
372 * "major.minor.milli.micro"
373 * @return String representative of VersionInfo
376 public String toString()
378 StringBuilder result = new StringBuilder(7);
379 result.append(getMajor());
381 result.append(getMinor());
383 result.append(getMilli());
385 result.append(getMicro());
386 return result.toString();
390 * Returns the major version number
391 * @return the major version number
394 public int getMajor()
396 return (m_version_ >> 24) & LAST_BYTE_MASK_ ;
400 * Returns the minor version number
401 * @return the minor version number
404 public int getMinor()
406 return (m_version_ >> 16) & LAST_BYTE_MASK_ ;
410 * Returns the milli version number
411 * @return the milli version number
414 public int getMilli()
416 return (m_version_ >> 8) & LAST_BYTE_MASK_ ;
420 * Returns the micro version number
421 * @return the micro version number
424 public int getMicro()
426 return m_version_ & LAST_BYTE_MASK_ ;
430 * Checks if this version information is equals to the argument version
431 * @param other object to be compared
432 * @return true if other is equals to this object's version information,
436 public boolean equals(Object other)
438 return other == this;
442 * Compares other with this VersionInfo.
443 * @param other VersionInfo to be compared
444 * @return 0 if the argument is a VersionInfo object that has version
445 * information equals to this object.
446 * Less than 0 if the argument is a VersionInfo object that has
447 * version information greater than this object.
448 * Greater than 0 if the argument is a VersionInfo object that
449 * has version information less than this object.
452 public int compareTo(VersionInfo other)
454 return m_version_ - other.m_version_;
457 // private data members ----------------------------------------------
460 * Unicode data version used by the current release
462 private static final VersionInfo UNICODE_VERSION;
465 * Version number stored as a byte for each of the major, minor, milli and
466 * micro numbers in the 32 bit int.
467 * Most significant for the major and the least significant contains the
470 private int m_version_;
474 private static final ConcurrentHashMap<Integer, VersionInfo> MAP_ = new ConcurrentHashMap<Integer, VersionInfo>();
478 private static final int LAST_BYTE_MASK_ = 0xFF;
480 * Error statement string
482 private static final String INVALID_VERSION_NUMBER_ =
483 "Invalid version number: Version number may be negative or greater than 255";
485 // static declaration ------------------------------------------------
488 * Initialize versions only after MAP_ has been created
491 UNICODE_1_0 = getInstance(1, 0, 0, 0);
492 UNICODE_1_0_1 = getInstance(1, 0, 1, 0);
493 UNICODE_1_1_0 = getInstance(1, 1, 0, 0);
494 UNICODE_1_1_5 = getInstance(1, 1, 5, 0);
495 UNICODE_2_0 = getInstance(2, 0, 0, 0);
496 UNICODE_2_1_2 = getInstance(2, 1, 2, 0);
497 UNICODE_2_1_5 = getInstance(2, 1, 5, 0);
498 UNICODE_2_1_8 = getInstance(2, 1, 8, 0);
499 UNICODE_2_1_9 = getInstance(2, 1, 9, 0);
500 UNICODE_3_0 = getInstance(3, 0, 0, 0);
501 UNICODE_3_0_1 = getInstance(3, 0, 1, 0);
502 UNICODE_3_1_0 = getInstance(3, 1, 0, 0);
503 UNICODE_3_1_1 = getInstance(3, 1, 1, 0);
504 UNICODE_3_2 = getInstance(3, 2, 0, 0);
505 UNICODE_4_0 = getInstance(4, 0, 0, 0);
506 UNICODE_4_0_1 = getInstance(4, 0, 1, 0);
507 UNICODE_4_1 = getInstance(4, 1, 0, 0);
508 UNICODE_5_0 = getInstance(5, 0, 0, 0);
509 UNICODE_5_1 = getInstance(5, 1, 0, 0);
510 UNICODE_5_2 = getInstance(5, 2, 0, 0);
511 UNICODE_6_0 = getInstance(6, 0, 0, 0);
512 UNICODE_6_1 = getInstance(6, 1, 0, 0);
513 UNICODE_6_2 = getInstance(6, 2, 0, 0);
514 UNICODE_6_3 = getInstance(6, 3, 0, 0);
516 ICU_VERSION = getInstance(52, 1, 0, 0);
517 ICU_DATA_VERSION = getInstance(52, 1, 0, 0);
518 UNICODE_VERSION = UNICODE_6_3;
520 UCOL_RUNTIME_VERSION = getInstance(7);
521 UCOL_BUILDER_VERSION = getInstance(8);
522 UCOL_TAILORINGS_VERSION = getInstance(1);
525 // private constructor -----------------------------------------------
528 * Constructor with int
529 * @param compactversion a 32 bit int with each byte representing a number
531 private VersionInfo(int compactversion)
533 m_version_ = compactversion;
537 * Gets the int from the version numbers
538 * @param major non-negative version number
539 * @param minor non-negative version number
540 * @param milli non-negative version number
541 * @param micro non-negative version number
543 private static int getInt(int major, int minor, int milli, int micro)
545 return (major << 24) | (minor << 16) | (milli << 8) | micro;
549 * Main method prints out ICU version information
550 * @param args arguments (currently not used)
553 public static void main(String[] args) {
556 if (ICU_VERSION.getMajor() <= 4) {
557 if (ICU_VERSION.getMinor() % 2 != 0) {
558 // Development mile stone
559 int major = ICU_VERSION.getMajor();
560 int minor = ICU_VERSION.getMinor() + 1;
565 icuApiVer = "" + major + "." + minor + "M" + ICU_VERSION.getMilli();
567 icuApiVer = ICU_VERSION.getVersionString(2, 2);
570 if (ICU_VERSION.getMinor() == 0) {
571 // Development mile stone
572 icuApiVer = "" + ICU_VERSION.getMajor() + "M" + ICU_VERSION.getMilli();
574 icuApiVer = ICU_VERSION.getVersionString(2, 2);
579 System.out.println("International Components for Unicode for Java " + icuApiVer);
581 System.out.println("");
582 System.out.println("Implementation Version: " + ICU_VERSION.getVersionString(2, 4));
583 System.out.println("Unicode Data Version: " + UNICODE_VERSION.getVersionString(2, 4));
584 System.out.println("CLDR Data Version: " + LocaleData.getCLDRVersion().getVersionString(2, 4));
585 System.out.println("Time Zone Data Version: " + TimeZone.getTZDataVersion());
589 * Generate version string separated by dots with
590 * the specified digit width. Version digit 0
591 * after <code>minDigits</code> will be trimmed off.
592 * @param minDigits Minimum number of version digits
593 * @param maxDigits Maximum number of version digits
594 * @return A tailored version string
596 private String getVersionString(int minDigits, int maxDigits) {
597 if (minDigits < 1 || maxDigits < 1
598 || minDigits > 4 || maxDigits > 4 || minDigits > maxDigits) {
599 throw new IllegalArgumentException("Invalid min/maxDigits range");
602 int[] digits = new int[4];
603 digits[0] = getMajor();
604 digits[1] = getMinor();
605 digits[2] = getMilli();
606 digits[3] = getMicro();
608 int numDigits = maxDigits;
609 while (numDigits > minDigits) {
610 if (digits[numDigits - 1] != 0) {
616 StringBuilder verStr = new StringBuilder(7);
617 verStr.append(digits[0]);
618 for (int i = 1; i < numDigits; i++) {
620 verStr.append(digits[i]);
623 return verStr.toString();