]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/impl/PluralRulesLoader.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / core / src / com / ibm / icu / impl / PluralRulesLoader.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 2008-2010, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.impl;
8
9 import java.text.ParseException;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.Iterator;
13 import java.util.Map;
14 import java.util.MissingResourceException;
15 import java.util.Set;
16 import java.util.TreeMap;
17
18 import com.ibm.icu.text.PluralRules;
19 import com.ibm.icu.util.ULocale;
20 import com.ibm.icu.util.UResourceBundle;
21
22 /**
23  * Loader for plural rules data.
24  */
25 public class PluralRulesLoader {
26     private final Map<String, PluralRules> rulesIdToRules;
27     private Map<String, String> localeIdToRulesId; // lazy init, use
28                                                    // getLocaleIdToRulesIdMap to
29                                                    // access
30     private Map<String, ULocale> rulesIdToEquivalentULocale; // lazy init, use
31                                                              // getRulesIdToEquivalentULocaleMap
32                                                              // to access
33
34     /**
35      * Access through singleton.
36      */
37     private PluralRulesLoader() {
38         rulesIdToRules = new HashMap<String, PluralRules>();
39     }
40
41     /**
42      * Returns the locales for which we have plurals data. Utility for testing.
43      */
44     public ULocale[] getAvailableULocales() {
45         Set<String> keys = getLocaleIdToRulesIdMap().keySet();
46         ULocale[] locales = new ULocale[keys.size()];
47         int n = 0;
48         for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
49             locales[n++] = ULocale.createCanonical(iter.next());
50         }
51         return locales;
52     }
53
54     /**
55      * Returns the functionally equivalent locale.
56      */
57     public ULocale getFunctionalEquivalent(ULocale locale, boolean[] isAvailable) {
58         if (isAvailable != null && isAvailable.length > 0) {
59             String localeId = ULocale.canonicalize(locale.getBaseName());
60             Map<String, String> idMap = getLocaleIdToRulesIdMap();
61             isAvailable[0] = idMap.containsKey(localeId);
62         }
63
64         String rulesId = getRulesIdForLocale(locale);
65         if (rulesId == null || rulesId.trim().length() == 0) {
66             return ULocale.ROOT; // ultimate fallback
67         }
68
69         ULocale result = getRulesIdToEquivalentULocaleMap().get(
70                 rulesId);
71         if (result == null) {
72             return ULocale.ROOT; // ultimate fallback
73         }
74
75         return result;
76     }
77
78     /**
79      * Returns the lazily-constructed map.
80      */
81     private Map<String, String> getLocaleIdToRulesIdMap() {
82         checkBuildRulesIdMaps();
83         return localeIdToRulesId;
84     }
85
86     /**
87      * Returns the lazily-constructed map.
88      */
89     private Map<String, ULocale> getRulesIdToEquivalentULocaleMap() {
90         checkBuildRulesIdMaps();
91         return rulesIdToEquivalentULocale;
92     }
93
94     /**
95      * Lazily constructs the localeIdToRulesId and rulesIdToEquivalentULocale
96      * maps if necessary. These exactly reflect the contents of the locales
97      * resource in plurals.res.
98      */
99     private void checkBuildRulesIdMaps() {
100         if (localeIdToRulesId == null) {
101             try {
102                 UResourceBundle pluralb = getPluralBundle();
103                 UResourceBundle localeb = pluralb.get("locales");
104                 localeIdToRulesId = new TreeMap<String, String>(); // sort for
105                                                                    // convenience
106                                                                    // of
107                                                                    // getAvailableULocales
108                 rulesIdToEquivalentULocale = new HashMap<String, ULocale>(); // not
109                                                                              // visible
110                 for (int i = 0; i < localeb.getSize(); ++i) {
111                     UResourceBundle b = localeb.get(i);
112                     String id = b.getKey();
113                     String value = b.getString().intern();
114                     localeIdToRulesId.put(id, value);
115
116                     if (!rulesIdToEquivalentULocale.containsKey(value)) {
117                         rulesIdToEquivalentULocale.put(value, new ULocale(id));
118                     }
119                 }
120             } catch (MissingResourceException e) {
121                 localeIdToRulesId = Collections.emptyMap(); // dummy so we don't
122                                                             // try again, can
123                                                             // read
124                 rulesIdToEquivalentULocale = Collections.emptyMap();
125             }
126         }
127     }
128
129     /**
130      * Gets the rulesId from the locale,with locale fallback. If there is no
131      * rulesId, return null. The rulesId might be the empty string if the rule
132      * is the default rule.
133      */
134     public String getRulesIdForLocale(ULocale locale) {
135         Map<String, String> idMap = getLocaleIdToRulesIdMap();
136         String localeId = ULocale.canonicalize(locale.getBaseName());
137         String rulesId = null;
138         while (null == (rulesId = idMap.get(localeId))) {
139             int ix = localeId.lastIndexOf("_");
140             if (ix == -1) {
141                 break;
142             }
143             localeId = localeId.substring(0, ix);
144         }
145         return rulesId;
146     }
147
148     /**
149      * Gets the rule from the rulesId. If there is no rule for this rulesId,
150      * return null.
151      */
152     public PluralRules getRulesForRulesId(String rulesId) {
153         PluralRules rules = rulesIdToRules.get(rulesId);
154         if (rules == null) {
155             try {
156                 UResourceBundle pluralb = getPluralBundle();
157                 UResourceBundle rulesb = pluralb.get("rules");
158                 UResourceBundle setb = rulesb.get(rulesId);
159
160                 StringBuilder sb = new StringBuilder();
161                 for (int i = 0; i < setb.getSize(); ++i) {
162                     UResourceBundle b = setb.get(i);
163                     if (i > 0) {
164                         sb.append("; ");
165                     }
166                     sb.append(b.getKey());
167                     sb.append(": ");
168                     sb.append(b.getString());
169                 }
170                 rules = PluralRules.parseDescription(sb.toString());
171             } catch (ParseException e) {
172             } catch (MissingResourceException e) {
173             }
174             rulesIdToRules.put(rulesId, rules); // put even if null
175         }
176         return rules;
177     }
178
179     /**
180      * Return the plurals resource. Note MissingResourceException is unchecked,
181      * listed here for clarity. Callers should handle this exception.
182      */
183     public UResourceBundle getPluralBundle() throws MissingResourceException {
184         return ICUResourceBundle.getBundleInstance(
185                 ICUResourceBundle.ICU_BASE_NAME, "plurals",
186                 ICUResourceBundle.ICU_DATA_CLASS_LOADER, true);
187     }
188
189     /**
190      * Returns the plural rules for the the locale. If we don't have data,
191      * com.ibm.icu.text.PluralRules.DEFAULT is returned.
192      */
193     public PluralRules forLocale(ULocale locale) {
194         String rulesId = getRulesIdForLocale(locale);
195         if (rulesId == null || rulesId.trim().length() == 0) {
196             return PluralRules.DEFAULT;
197         }
198         PluralRules rules = getRulesForRulesId(rulesId);
199         if (rules == null) {
200             rules = PluralRules.DEFAULT;
201         }
202         return rules;
203     }
204
205     /**
206      * The only instance of the loader.
207      */
208     public static final PluralRulesLoader loader = new PluralRulesLoader();
209 }