File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\value\CompareMode.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.value;
8
9 import java.text.Collator;
10 import java.util.Locale;
11 import org.h2.util.StringUtils;
12
13 /**
14 * Instances of this class can compare strings. Case sensitive and case
15 * insensitive comparison is supported, and comparison using a collator.
16 */
17 public class CompareMode {
18
19 /**
20 * This constant means there is no collator set, and the default string
21 * comparison is to be used.
22 */
23 public static final String OFF = "OFF";
24
25 /**
26 * This constant means the default collator should be used, even if ICU4J is
27 * in the classpath.
28 */
29 public static final String DEFAULT = "DEFAULT_";
30
31 /**
32 * This constant means ICU4J should be used (this will fail if it is not in
33 * the classpath).
34 */
35 public static final String ICU4J = "ICU4J_";
36
37 private static CompareMode lastUsed;
38
39 private static final boolean CAN_USE_ICU4J;
40
41 static {
42 boolean b = false;
43 try {
44 Class.forName("com.ibm.icu.text.Collator");
45 b = true;
46 } catch (Exception e) {
47 // ignore
48 }
49 CAN_USE_ICU4J = b;
50 }
51
52 private final String name;
53 private final int strength;
54
55 protected CompareMode(String name, int strength) {
56 this.name = name;
57 this.strength = strength;
58 }
59
60 /**
61 * Create a new compare mode with the given collator and strength. If
62 * required, a new CompareMode is created, or if possible the last one is
63 * returned. A cache is used to speed up comparison when using a collator;
64 * CollationKey objects are cached.
65 *
66 * @param name the collation name or null
67 * @param strength the collation strength
68 * @return the compare mode
69 */
70 public static synchronized CompareMode getInstance(String name, int strength) {
71 if (lastUsed != null) {
72 if (StringUtils.equals(lastUsed.name, name)) {
73 if (lastUsed.strength == strength) {
74 return lastUsed;
75 }
76 }
77 }
78 if (name == null || name.equals(OFF)) {
79 lastUsed = new CompareMode(name, strength);
80 } else {
81 boolean useICU4J;
82 if (name.startsWith(ICU4J)) {
83 useICU4J = true;
84 name = name.substring(ICU4J.length());
85 } else if (name.startsWith(DEFAULT)) {
86 useICU4J = false;
87 name = name.substring(DEFAULT.length());
88 } else {
89 useICU4J = CAN_USE_ICU4J;
90 }
91 if (useICU4J) {
92 lastUsed = new CompareModeIcu4J(name, strength);
93 } else {
94 lastUsed = new CompareModeDefault(name, strength);
95 }
96 }
97 return lastUsed;
98 }
99
100 /**
101 * Compare two characters in a string.
102 *
103 * @param a the first string
104 * @param ai the character index in the first string
105 * @param b the second string
106 * @param bi the character index in the second string
107 * @param ignoreCase true if a case-insensitive comparison should be made
108 * @return true if the characters are equals
109 */
110 public boolean equalsChars(String a, int ai, String b, int bi, boolean ignoreCase) {
111 char ca = a.charAt(ai);
112 char cb = b.charAt(bi);
113 if (ignoreCase) {
114 ca = Character.toUpperCase(ca);
115 cb = Character.toUpperCase(cb);
116 }
117 return ca == cb;
118 }
119
120 /**
121 * Compare two strings.
122 *
123 * @param a the first string
124 * @param b the second string
125 * @param ignoreCase true if a case-insensitive comparison should be made
126 * @return -1 if the first string is 'smaller', 1 if the second string is
127 * smaller, and 0 if they are equal
128 */
129 public int compareString(String a, String b, boolean ignoreCase) {
130 if (ignoreCase) {
131 return a.compareToIgnoreCase(b);
132 }
133 return a.compareTo(b);
134 }
135
136 /**
137 * Get the collation name.
138 *
139 * @param l the locale
140 * @return the name of the collation
141 */
142 public static String getName(Locale l) {
143 Locale english = Locale.ENGLISH;
144 String name = l.getDisplayLanguage(english) + ' ' + l.getDisplayCountry(english) + ' ' + l.getVariant();
145 name = StringUtils.toUpperEnglish(name.trim().replace(' ', '_'));
146 return name;
147 }
148
149 /**
150 * Compare name name of the locale with the given name. The case of the name
151 * is ignored.
152 *
153 * @param locale the locale
154 * @param name the name
155 * @return true if they match
156 */
157 static boolean compareLocaleNames(Locale locale, String name) {
158 return name.equalsIgnoreCase(locale.toString()) || name.equalsIgnoreCase(getName(locale));
159 }
160
161 /**
162 * Get the collator object for the given language name or language / country
163 * combination.
164 *
165 * @param name the language name
166 * @return the collator
167 */
168 public static Collator getCollator(String name) {
169 Collator result = null;
170 if (name.startsWith(ICU4J)) {
171 name = name.substring(ICU4J.length());
172 } else if (name.startsWith(DEFAULT)) {
173 name = name.substring(DEFAULT.length());
174 }
175 if (name.length() == 2) {
176 Locale locale = new Locale(StringUtils.toLowerEnglish(name), "");
177 if (compareLocaleNames(locale, name)) {
178 result = Collator.getInstance(locale);
179 }
180 } else if (name.length() == 5) {
181 // LL_CC (language_country)
182 int idx = name.indexOf('_');
183 if (idx >= 0) {
184 String language = StringUtils.toLowerEnglish(name.substring(0, idx));
185 String country = name.substring(idx + 1);
186 Locale locale = new Locale(language, country);
187 if (compareLocaleNames(locale, name)) {
188 result = Collator.getInstance(locale);
189 }
190 }
191 }
192 if (result == null) {
193 for (Locale locale : Collator.getAvailableLocales()) {
194 if (compareLocaleNames(locale, name)) {
195 result = Collator.getInstance(locale);
196 break;
197 }
198 }
199 }
200 return result;
201 }
202
203 public String getName() {
204 return name == null ? OFF : name;
205 }
206
207 public int getStrength() {
208 return strength;
209 }
210
211 }
212