001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.text;
019:
020: import java.security.AccessController;
021: import java.util.Comparator;
022: import java.util.Locale;
023: import java.util.Vector;
024:
025: import org.apache.harmony.luni.util.PriviAction;
026:
027: /**
028: * Collator is an abstract class which is the root of classes which provide
029: * Locale specific String comparison to determine their ordering with respect to
030: * each other.
031: */
032: public abstract class Collator implements Comparator<Object>, Cloneable {
033:
034: static final int EQUAL = 0;
035:
036: static final int GREATER = 1;
037:
038: static final int LESS = -1;
039:
040: /**
041: * Constant used to specify the decomposition rule.
042: */
043: public static final int NO_DECOMPOSITION = 0;
044:
045: /**
046: * Constant used to specify the decomposition rule.
047: */
048: public static final int CANONICAL_DECOMPOSITION = 1;
049:
050: /**
051: * Constant used to specify the decomposition rule.
052: */
053: public static final int FULL_DECOMPOSITION = 2;
054:
055: /**
056: * Constant used to specify the collation strength.
057: */
058: public static final int PRIMARY = 0;
059:
060: /**
061: * Constant used to specify the collation strength.
062: */
063: public static final int SECONDARY = 1;
064:
065: /**
066: * Constant used to specify the collation strength.
067: */
068: public static final int TERTIARY = 2;
069:
070: /**
071: * Constant used to specify the collation strength.
072: */
073: public static final int IDENTICAL = 3;
074:
075: private static int CACHE_SIZE;
076:
077: static {
078: // CACHE_SIZE includes key and value, so needs to be double
079: String cacheSize = AccessController
080: .doPrivileged(new PriviAction<String>("collator.cache")); //$NON-NLS-1$
081: if (cacheSize != null) {
082: try {
083: CACHE_SIZE = Integer.parseInt(cacheSize);
084: } catch (NumberFormatException e) {
085: CACHE_SIZE = 6;
086: }
087: } else {
088: CACHE_SIZE = 6;
089: }
090: }
091:
092: private static Vector<Collator> cache = new Vector<Collator>(
093: CACHE_SIZE);
094:
095: // Wrapper class of ICU4J Collator
096: com.ibm.icu.text.Collator icuColl;
097:
098: Collator(com.ibm.icu.text.Collator wrapper) {
099: this .icuColl = wrapper;
100: }
101:
102: /**
103: * Constructs a new instance of this Collator.
104: */
105: protected Collator() {
106: super ();
107: }
108:
109: /**
110: * Answers a new Collator with the same decomposition rule and strength
111: * value as this Collator.
112: *
113: * @return a shallow copy of this Collator
114: * @see java.lang.Cloneable
115: */
116: @Override
117: public Object clone() {
118: try {
119: Collator clone = (Collator) super .clone();
120: clone.icuColl = (com.ibm.icu.text.Collator) this .icuColl
121: .clone();
122: return clone;
123: } catch (CloneNotSupportedException e) {
124: return null;
125: }
126: }
127:
128: /**
129: * Compares the two objects to determine their relative ordering. The
130: * objects must be Strings.
131: *
132: * @param object1
133: * the first String to compare
134: * @param object2
135: * the second String to compare
136: * @return an int < 0 if object1 is less than object2, 0 if they are equal,
137: * and > 0 if object1 is greater than object2
138: *
139: * @exception ClassCastException
140: * when the objects are not Strings
141: */
142: public int compare(Object object1, Object object2) {
143: return compare((String) object1, (String) object2);
144: }
145:
146: /**
147: * Compares the two Strings to determine their relative ordering.
148: *
149: * @param string1
150: * the first String to compare
151: * @param string2
152: * the second String to compare
153: * @return an int < 0 if string1 is less than string2, 0 if they are equal,
154: * and > 0 if string1 is greater than string2
155: */
156: public abstract int compare(String string1, String string2);
157:
158: /**
159: * Compares the specified object to this Collator and answer if they are
160: * equal. The object must be an instance of Collator and have the same
161: * strength and decomposition values.
162: *
163: * @param object
164: * the object to compare with this object
165: * @return true if the specified object is equal to this Collator, false
166: * otherwise
167: *
168: * @see #hashCode
169: */
170: @Override
171: public boolean equals(Object object) {
172: if (!(object instanceof Collator)) {
173: return false;
174: }
175: Collator collator = (Collator) object;
176: return this .icuColl == null ? collator.icuColl == null
177: : this .icuColl.equals(collator.icuColl);
178: }
179:
180: /**
181: * Compares the two Strings using the collation rules to determine if they
182: * are equal.
183: *
184: * @param string1
185: * the first String to compare
186: * @param string2
187: * the second String to compare
188: * @return true if the strings are equal using the collation rules, false
189: * otherwise
190: */
191: public boolean equals(String string1, String string2) {
192: return compare(string1, string2) == 0;
193: }
194:
195: /**
196: * Gets the list of installed Locales which support Collator.
197: *
198: * @return an array of Locale
199: */
200: public static Locale[] getAvailableLocales() {
201: return com.ibm.icu.text.Collator.getAvailableLocales();
202: }
203:
204: /**
205: * Answers a CollationKey for the specified String for this Collator with
206: * the current decomposition rule and strength value.
207: *
208: * @param string
209: * the collation key.
210: * @return a CollationKey
211: */
212: public abstract CollationKey getCollationKey(String string);
213:
214: /**
215: * Answers the decomposition rule for this Collator.
216: *
217: * @return the decomposition rule, either NO_DECOMPOSITION,
218: * CANONICAL_DECOMPOSITION or FULL_DECOMPOSITION
219: */
220: public int getDecomposition() {
221: return decompositionMode_ICU_Java(this .icuColl
222: .getDecomposition());
223: }
224:
225: /**
226: * Answers a Collator instance which is appropriate for the default Locale.
227: *
228: * @return a Collator
229: */
230: public static Collator getInstance() {
231: return getInstance(Locale.getDefault());
232: }
233:
234: /**
235: * Answers a Collator instance which is appropriate for the specified
236: * Locale.
237: *
238: * @param locale
239: * the Locale
240: * @return a Collator
241: */
242: public static Collator getInstance(Locale locale) {
243: String key = locale.toString();
244: for (int i = cache.size() - 1; i >= 0; i -= 2) {
245: if (cache.elementAt(i).equals(key)) {
246: return (Collator) (cache.elementAt(i - 1)).clone();
247: }
248: }
249:
250: return new RuleBasedCollator(com.ibm.icu.text.Collator
251: .getInstance(locale));
252: }
253:
254: /**
255: * Answers the strength value for this Collator.
256: *
257: * @return the strength value, either PRIMARY, SECONDARY, TERTIARY, or
258: * IDENTICAL
259: */
260: public int getStrength() {
261: return strength_ICU_Java(this .icuColl.getStrength());
262: }
263:
264: /**
265: * Answers an integer hash code for the receiver. Objects which are equal
266: * answer the same value for this method.
267: *
268: * @return the receiver's hash
269: *
270: * @see #equals(Object)
271: * @see #equals(String, String)
272: */
273: @Override
274: public abstract int hashCode();
275:
276: /**
277: * Sets the decomposition rule for this Collator.
278: *
279: * @param value
280: * the decomposition rule, either NO_DECOMPOSITION,
281: * CANONICAL_DECOMPOSITION or FULL_DECOMPOSITION
282: *
283: * @exception IllegalArgumentException
284: * when the decomposition rule is not valid
285: */
286: public void setDecomposition(int value) {
287: this .icuColl
288: .setDecomposition(decompositionMode_Java_ICU(value));
289: }
290:
291: /**
292: * Sets the strength value for this Collator.
293: *
294: * @param value
295: * the strength value, either PRIMARY, SECONDARY, TERTIARY, or
296: * IDENTICAL
297: *
298: * @exception IllegalArgumentException
299: * when the strength value is not valid
300: */
301: public void setStrength(int value) {
302: this .icuColl.setStrength(strength_Java_ICU(value));
303: }
304:
305: private int decompositionMode_Java_ICU(int mode) {
306: int icuDecomp = mode;
307: switch (mode) {
308: case Collator.CANONICAL_DECOMPOSITION:
309: icuDecomp = com.ibm.icu.text.Collator.CANONICAL_DECOMPOSITION;
310: break;
311: case Collator.NO_DECOMPOSITION:
312: icuDecomp = com.ibm.icu.text.Collator.NO_DECOMPOSITION;
313: break;
314: }
315: return icuDecomp;
316: }
317:
318: private int decompositionMode_ICU_Java(int mode) {
319: int javaMode = mode;
320: switch (mode) {
321: case com.ibm.icu.text.Collator.NO_DECOMPOSITION:
322: javaMode = Collator.NO_DECOMPOSITION;
323: break;
324: case com.ibm.icu.text.Collator.CANONICAL_DECOMPOSITION:
325: javaMode = Collator.CANONICAL_DECOMPOSITION;
326: break;
327: }
328: return javaMode;
329: }
330:
331: private int strength_Java_ICU(int value) {
332: int icuValue = value;
333: switch (value) {
334: case Collator.PRIMARY:
335: icuValue = com.ibm.icu.text.Collator.PRIMARY;
336: break;
337: case Collator.SECONDARY:
338: icuValue = com.ibm.icu.text.Collator.SECONDARY;
339: break;
340: case Collator.TERTIARY:
341: icuValue = com.ibm.icu.text.Collator.TERTIARY;
342: break;
343: case Collator.IDENTICAL:
344: icuValue = com.ibm.icu.text.Collator.IDENTICAL;
345: break;
346: }
347: return icuValue;
348:
349: }
350:
351: private int strength_ICU_Java(int value) {
352: int javaValue = value;
353: switch (value) {
354: case com.ibm.icu.text.Collator.PRIMARY:
355: javaValue = Collator.PRIMARY;
356: break;
357: case com.ibm.icu.text.Collator.SECONDARY:
358: javaValue = Collator.SECONDARY;
359: break;
360: case com.ibm.icu.text.Collator.TERTIARY:
361: javaValue = Collator.TERTIARY;
362: break;
363: case com.ibm.icu.text.Collator.IDENTICAL:
364: javaValue = Collator.IDENTICAL;
365: break;
366: }
367: return javaValue;
368: }
369: }
|