• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5 *******************************************************************************
6 *
7 *   Copyright (C) 1996-2016, International Business Machines
8 *   Corporation and others.  All Rights Reserved.
9 *
10 *******************************************************************************
11 *
12 * CollationLoader.java, ported from ucol_res.cpp
13 *
14 * created by: Markus W. Scherer
15 */
16 
17 package ohos.global.icu.impl.coll;
18 
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.util.MissingResourceException;
22 
23 import ohos.global.icu.impl.ICUData;
24 import ohos.global.icu.impl.ICUResourceBundle;
25 import ohos.global.icu.util.ICUUncheckedIOException;
26 import ohos.global.icu.util.Output;
27 import ohos.global.icu.util.ULocale;
28 import ohos.global.icu.util.UResourceBundle;
29 
30 /**
31  * Convenience string denoting the Collation data tree
32  * @hide exposed on OHOS
33  */
34 public final class CollationLoader {
35 
36     // not implemented, all methods are static
CollationLoader()37     private CollationLoader() {
38     }
39 
40     private static volatile String rootRules = null;
41 
loadRootRules()42     private static void loadRootRules() {
43         if (rootRules != null) {
44             return;
45         }
46         synchronized(CollationLoader.class) {
47             if (rootRules == null) {
48                 UResourceBundle rootBundle = UResourceBundle.getBundleInstance(
49                         ICUData.ICU_COLLATION_BASE_NAME, ULocale.ROOT);
50                 rootRules = rootBundle.getString("UCARules");
51             }
52         }
53     }
54 
55     // C++: static void appendRootRules(UnicodeString &s)
getRootRules()56     public static String getRootRules() {
57         loadRootRules();
58         return rootRules;
59     }
60 
61     /**
62      * Simpler/faster methods for ASCII than ones based on Unicode data.
63      * TODO: There should be code like this somewhere already??
64      */
65     private static final class ASCII {
toLowerCase(String s)66         static String toLowerCase(String s) {
67             for (int i = 0; i < s.length(); ++i) {
68                 char c = s.charAt(i);
69                 if ('A' <= c && c <= 'Z') {
70                     StringBuilder sb = new StringBuilder(s.length());
71                     sb.append(s, 0, i).append((char)(c + 0x20));
72                     while (++i < s.length()) {
73                         c = s.charAt(i);
74                         if ('A' <= c && c <= 'Z') { c = (char)(c + 0x20); }
75                         sb.append(c);
76                     }
77                     return sb.toString();
78                 }
79             }
80             return s;
81         }
82     }
83 
loadRules(ULocale locale, String collationType)84     static String loadRules(ULocale locale, String collationType) {
85         UResourceBundle bundle = UResourceBundle.getBundleInstance(
86                 ICUData.ICU_COLLATION_BASE_NAME, locale);
87         UResourceBundle data = ((ICUResourceBundle)bundle).getWithFallback(
88                 "collations/" + ASCII.toLowerCase(collationType));
89         String rules = data.getString("Sequence");
90         return rules;
91     }
92 
findWithFallback(UResourceBundle table, String entryName)93     private static final UResourceBundle findWithFallback(UResourceBundle table, String entryName) {
94         return ((ICUResourceBundle)table).findWithFallback(entryName);
95     }
96 
loadTailoring(ULocale locale, Output<ULocale> outValidLocale)97     public static CollationTailoring loadTailoring(ULocale locale, Output<ULocale> outValidLocale) {
98 
99         // Java porting note: ICU4J getWithFallback/getStringWithFallback currently does not
100         // work well when alias table is involved in a resource path, unless full path is specified.
101         // For now, collation resources does not contain such data, so the code below should work fine.
102 
103         CollationTailoring root = CollationRoot.getRoot();
104         String localeName = locale.getName();
105         if (localeName.length() == 0 || localeName.equals("root")) {
106             outValidLocale.value = ULocale.ROOT;
107             return root;
108         }
109 
110         UResourceBundle bundle = null;
111         try {
112             bundle = ICUResourceBundle.getBundleInstance(
113                     ICUData.ICU_COLLATION_BASE_NAME, locale,
114                     ICUResourceBundle.OpenType.LOCALE_ROOT);
115         } catch (MissingResourceException e) {
116             outValidLocale.value = ULocale.ROOT;
117             return root;
118         }
119 
120         ULocale validLocale = bundle.getULocale();
121         // Normalize the root locale. See
122         // http://bugs.icu-project.org/trac/ticket/10715
123         String validLocaleName = validLocale.getName();
124         if (validLocaleName.length() == 0 || validLocaleName.equals("root")) {
125             validLocale = ULocale.ROOT;
126         }
127         outValidLocale.value = validLocale;
128 
129         // There are zero or more tailorings in the collations table.
130         UResourceBundle collations;
131         try {
132             collations = bundle.get("collations");
133             if (collations == null) {
134                 return root;
135             }
136         } catch(MissingResourceException ignored) {
137             return root;
138         }
139 
140         // Fetch the collation type from the locale ID and the default type from the data.
141         String type = locale.getKeywordValue("collation");
142         String defaultType = "standard";
143 
144         String defT = ((ICUResourceBundle)collations).findStringWithFallback("default");
145         if (defT != null) {
146             defaultType = defT;
147         }
148 
149         if (type == null || type.equals("default")) {
150             type = defaultType;
151         } else {
152             type = ASCII.toLowerCase(type);
153         }
154 
155         // Load the collations/type tailoring, with type fallback.
156 
157         // Java porting note: typeFallback is used for setting U_USING_DEFAULT_WARNING in
158         // ICU4C, but not used by ICU4J
159 
160         // boolean typeFallback = false;
161         UResourceBundle data = findWithFallback(collations, type);
162         if (data == null &&
163                 type.length() > 6 && type.startsWith("search")) {
164             // fall back from something like "searchjl" to "search"
165             // typeFallback = true;
166             type = "search";
167             data = findWithFallback(collations, type);
168         }
169 
170         if (data == null && !type.equals(defaultType)) {
171             // fall back to the default type
172             // typeFallback = true;
173             type = defaultType;
174             data = findWithFallback(collations, type);
175         }
176 
177         if (data == null && !type.equals("standard")) {
178             // fall back to the "standard" type
179             // typeFallback = true;
180             type = "standard";
181             data = findWithFallback(collations, type);
182         }
183 
184         if (data == null) {
185             return root;
186         }
187 
188         // Is this the same as the root collator? If so, then use that instead.
189         ULocale actualLocale = data.getULocale();
190         // http://bugs.icu-project.org/trac/ticket/10715 ICUResourceBundle(root).getULocale() != ULocale.ROOT
191         // Therefore not just if (actualLocale.equals(ULocale.ROOT) && type.equals("standard")) {
192         String actualLocaleName = actualLocale.getName();
193         if (actualLocaleName.length() == 0 || actualLocaleName.equals("root")) {
194             actualLocale = ULocale.ROOT;
195             if (type.equals("standard")) {
196                 return root;
197             }
198         }
199 
200         CollationTailoring t = new CollationTailoring(root.settings);
201         t.actualLocale = actualLocale;
202 
203         // deserialize
204         UResourceBundle binary = data.get("%%CollationBin");
205         ByteBuffer inBytes = binary.getBinary();
206         try {
207             CollationDataReader.read(root, inBytes, t);
208         } catch (IOException e) {
209             throw new ICUUncheckedIOException("Failed to load collation tailoring data for locale:"
210                     + actualLocale + " type:" + type, e);
211         }
212 
213         // Try to fetch the optional rules string.
214         try {
215             t.setRulesResource(data.get("Sequence"));
216         } catch(MissingResourceException ignored) {
217         }
218 
219         // Set the collation types on the informational locales,
220         // except when they match the default types (for brevity and backwards compatibility).
221         // For the valid locale, suppress the default type.
222         if (!type.equals(defaultType)) {
223             outValidLocale.value = validLocale.setKeywordValue("collation", type);
224         }
225 
226         // For the actual locale, suppress the default type *according to the actual locale*.
227         // For example, zh has default=pinyin and contains all of the Chinese tailorings.
228         // zh_Hant has default=stroke but has no other data.
229         // For the valid locale "zh_Hant" we need to suppress stroke.
230         // For the actual locale "zh" we need to suppress pinyin instead.
231         if (!actualLocale.equals(validLocale)) {
232             // Opening a bundle for the actual locale should always succeed.
233             UResourceBundle actualBundle = UResourceBundle.getBundleInstance(
234                     ICUData.ICU_COLLATION_BASE_NAME, actualLocale);
235             defT = ((ICUResourceBundle)actualBundle).findStringWithFallback("collations/default");
236             if (defT != null) {
237                 defaultType = defT;
238             }
239         }
240 
241         if (!type.equals(defaultType)) {
242             t.actualLocale = t.actualLocale.setKeywordValue("collation", type);
243         }
244 
245         // if (typeFallback) {
246         //     ICU4C implementation sets U_USING_DEFAULT_WARNING here
247         // }
248 
249         return t;
250     }
251 }
252