1/**
2*******************************************************************************
3* Copyright (C) 1996-2005, International Business Machines Corporation and    *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*
7*
8*******************************************************************************
9*/
10
11package com.ibm.icu4jni.text;
12
13/**
14* Collation key wrapper, containing the byte array sort key.
15* @author syn wee quek
16* @stable ICU 2.4
17*/
18
19public final class CollationKey implements Comparable
20{
21  // public methods -----------------------------------------------
22
23  /**
24  * Bitwise comparison for the collation keys
25  * @param target CollationKey to be compared
26  * @return comparison result from Collator, RESULT_LESS, RESULT_EQUAL,
27  *         RESULT_GREATER
28  * @stable ICU 2.4
29  */
30  public int compareTo(CollationKey target)
31  {
32    byte tgtbytes[] = target.m_bytes_;
33
34    if (m_bytes_ == null || m_bytes_.length == 0) {
35      if (tgtbytes == null || tgtbytes.length == 0) {
36        return Collator.RESULT_EQUAL;
37      }
38      return Collator.RESULT_LESS;
39    }
40    else {
41      if (tgtbytes == null || tgtbytes.length == 0) {
42        return Collator.RESULT_GREATER;
43      }
44    }
45
46    int count = m_bytes_.length;
47    if (tgtbytes.length < count) {
48      count = tgtbytes.length;
49    }
50
51    int s,
52        t;
53    for (int i = 0; i < count; i ++)
54    {
55      // unable to use Arrays.equals
56      s = m_bytes_[i] & UNSIGNED_BYTE_MASK_;
57      t = tgtbytes[i] & UNSIGNED_BYTE_MASK_;
58      if (s < t) {
59        return Collator.RESULT_LESS;
60      }
61      if (s > t) {
62        return Collator.RESULT_GREATER;
63      }
64    }
65
66    if (m_bytes_.length < target.m_bytes_.length) {
67      return Collator.RESULT_LESS;
68    }
69
70    if (m_bytes_.length > target.m_bytes_.length) {
71      return Collator.RESULT_GREATER;
72    }
73
74    return Collator.RESULT_EQUAL;
75  }
76
77  /**
78  * Bitwise comparison for the collation keys.
79  * Argument is casted to CollationKey
80  * @param target CollationKey to be compared
81  * @return comparison result from Collator, RESULT_LESS, RESULT_EQUAL,
82  * RESULT_GREATER
83  * @stable ICU 2.4
84  */
85  public int compareTo(Object target)
86  {
87    return compareTo((CollationKey)target);
88  }
89
90  /**
91  * Checks if target object is equal to this object.
92  * Target is first casted to CollationKey and bitwise compared.
93  * @param target comparison object
94  * @return true if both objects are equal, false otherwise
95  * @stable ICU 2.4
96  */
97  public boolean equals(Object target)
98  {
99    if (this == target) {
100      return true;
101    }
102
103    // checks getClass here since CollationKey is final not subclassable
104    if (target == null || target.getClass() != getClass()) {
105      return false;
106    }
107
108    return compareTo((CollationKey)target) == Collator.RESULT_EQUAL;
109  }
110
111  /**
112  * Creates a hash code for this CollationKey.
113  * Compute the hash by iterating sparsely over about 32 (up to 63) bytes
114  * spaced evenly through the string.  For each byte, multiply the previous
115  * hash value by a prime number and add the new byte in, like a linear
116  * congruential random number generator, producing a pseudorandom
117  * deterministic value well distributed over the output range.
118  * @return hash value of collation key. Hash value is never 0.
119  * @stable ICU 2.4
120  */
121  public int hashCode()
122  {
123    if (m_hash_ == 0)
124    {
125      if (m_bytes_ != null && m_bytes_.length != 0)
126      {
127        int len = m_bytes_.length;
128        int inc = ((len - 32) / 32) + 1;
129        for (int i = 0; i < len;)
130        {
131          m_hash_ = (m_hash_ * 37) + m_bytes_[i];
132          i += inc;
133        }
134      }
135      if (m_hash_ == 0)
136        m_hash_ = 1;
137    }
138    return m_hash_;
139  }
140
141  /**
142  * Create the value of the Collation key in term of bytes
143  * @return value of Collation key in bytes
144  * @stable ICU 2.4
145  */
146  public byte[] toByteArray()
147  {
148    if (m_bytes_ == null || m_bytes_.length == 0)
149      return null;
150
151    return (byte[])m_bytes_.clone();
152  }
153
154  // package constructors ----------------------------------------------
155
156  /**
157  * Default constructor, for use by the Collator and its subclasses.
158  */
159  CollationKey()
160  {
161    m_hash_ = 0;
162  }
163
164  /**
165  * Constructor, for use only by the Collator and its subclasses.
166  */
167  CollationKey(byte[] bytes)
168  {
169    m_bytes_ = bytes;
170    m_hash_ = 0;
171  }
172
173  // private data members -----------------------------------------------
174
175  private byte m_bytes_[];
176
177  /**
178  * Mask value to retrieve a single unsigned byte
179  */
180  private static final int UNSIGNED_BYTE_MASK_ = 0x00FF;
181
182  /**
183  * Cached hash value
184  */
185  private int m_hash_;
186}
187