1 /*
   2  * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  *******************************************************************************
  27  * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         *
  28  *                                                                             *
  29  * The original version of this source code and documentation is copyrighted   *
  30  * and owned by IBM, These materials are provided under terms of a License     *
  31  * Agreement between IBM and Sun. This technology is protected by multiple     *
  32  * US and International patents. This notice and attribution to IBM may not    *
  33  * to removed.                                                                 *
  34  *******************************************************************************
  35  */
  36 
  37 package sun.text.normalizer;
  38 
  39 import java.util.HashMap;
  40 
  41 /**
  42  * Class to store version numbers of the form major.minor.milli.micro.
  43  * @author synwee
  44  * @stable ICU 2.6
  45  */
  46 public final class VersionInfo
  47 {
  48 
  49     // public methods ------------------------------------------------------
  50 
  51     /**
  52      * Returns an instance of VersionInfo with the argument version.
  53      * @param version version String in the format of "major.minor.milli.micro"
  54      *                or "major.minor.milli" or "major.minor" or "major",
  55      *                where major, minor, milli, micro are non-negative numbers
  56      *                {@literal <=} 255. If the trailing version numbers are
  57      *                not specified they are taken as 0s. E.g. Version "3.1" is
  58      *                equivalent to "3.1.0.0".
  59      * @return an instance of VersionInfo with the argument version.
  60      * @exception throws an IllegalArgumentException when the argument version
  61      *                is not in the right format
  62      * @stable ICU 2.6
  63      */
  64     public static VersionInfo getInstance(String version)
  65     {
  66         int length  = version.length();
  67         int array[] = {0, 0, 0, 0};
  68         int count   = 0;
  69         int index   = 0;
  70 
  71         while (count < 4 && index < length) {
  72             char c = version.charAt(index);
  73             if (c == '.') {
  74                 count ++;
  75             }
  76             else {
  77                 c -= '0';
  78                 if (c < 0 || c > 9) {
  79                     throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
  80                 }
  81                 array[count] *= 10;
  82                 array[count] += c;
  83             }
  84             index ++;
  85         }
  86         if (index != length) {
  87             throw new IllegalArgumentException(
  88                                                "Invalid version number: String '" + version + "' exceeds version format");
  89         }
  90         for (int i = 0; i < 4; i ++) {
  91             if (array[i] < 0 || array[i] > 255) {
  92                 throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
  93             }
  94         }
  95 
  96         return getInstance(array[0], array[1], array[2], array[3]);
  97     }
  98 
  99     /**
 100      * Returns an instance of VersionInfo with the argument version.
 101      * @param major major version, non-negative number {@literal <=} 255.
 102      * @param minor minor version, non-negative number {@literal <=} 255.
 103      * @param milli milli version, non-negative number {@literal <=} 255.
 104      * @param micro micro version, non-negative number {@literal <=} 255.
 105      * @exception throws an IllegalArgumentException when either arguments are
 106      *                                     negative or {@literal >} 255
 107      * @stable ICU 2.6
 108      */
 109     public static VersionInfo getInstance(int major, int minor, int milli,
 110                                           int micro)
 111     {
 112         // checks if it is in the hashmap
 113         // else
 114         if (major < 0 || major > 255 || minor < 0 || minor > 255 ||
 115             milli < 0 || milli > 255 || micro < 0 || micro > 255) {
 116             throw new IllegalArgumentException(INVALID_VERSION_NUMBER_);
 117         }
 118         int     version = getInt(major, minor, milli, micro);
 119         Integer key     = Integer.valueOf(version);
 120         Object  result  = MAP_.get(key);
 121         if (result == null) {
 122             result = new VersionInfo(version);
 123             MAP_.put(key, result);
 124         }
 125         return (VersionInfo)result;
 126     }
 127 
 128     /**
 129      * Compares other with this VersionInfo.
 130      * @param other VersionInfo to be compared
 131      * @return 0 if the argument is a VersionInfo object that has version
 132      *           information equals to this object.
 133      *           Less than 0 if the argument is a VersionInfo object that has
 134      *           version information greater than this object.
 135      *           Greater than 0 if the argument is a VersionInfo object that
 136      *           has version information less than this object.
 137      * @stable ICU 2.6
 138      */
 139     public int compareTo(VersionInfo other)
 140     {
 141         return m_version_ - other.m_version_;
 142     }
 143 
 144     // private data members ----------------------------------------------
 145 
 146     /**
 147      * Version number stored as a byte for each of the major, minor, milli and
 148      * micro numbers in the 32 bit int.
 149      * Most significant for the major and the least significant contains the
 150      * micro numbers.
 151      */
 152     private int m_version_;
 153     /**
 154      * Map of singletons
 155      */
 156     private static final HashMap<Integer, Object> MAP_ = new HashMap<>();
 157     /**
 158      * Error statement string
 159      */
 160     private static final String INVALID_VERSION_NUMBER_ =
 161         "Invalid version number: Version number may be negative or greater than 255";
 162 
 163     // private constructor -----------------------------------------------
 164 
 165     /**
 166      * Constructor with int
 167      * @param compactversion a 32 bit int with each byte representing a number
 168      */
 169     private VersionInfo(int compactversion)
 170     {
 171         m_version_ = compactversion;
 172     }
 173 
 174     /**
 175      * Gets the int from the version numbers
 176      * @param major non-negative version number
 177      * @param minor non-negativeversion number
 178      * @param milli non-negativeversion number
 179      * @param micro non-negativeversion number
 180      */
 181     private static int getInt(int major, int minor, int milli, int micro)
 182     {
 183         return (major << 24) | (minor << 16) | (milli << 8) | micro;
 184     }
 185 }