17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2008-2014, International Business Machines Corporation and * 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. * 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.impl; 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParseException; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collections; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TreeMap; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRanges; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.PluralType; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.StandardPluralCategories; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.UResourceBundle; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Loader for plural rules data. 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class PluralRulesLoader extends PluralRules.Factory { 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final Map<String, PluralRules> rulesIdToRules; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // lazy init, use getLocaleIdToRulesIdMap to access 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, String> localeIdToCardinalRulesId; 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, String> localeIdToOrdinalRulesId; 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, ULocale> rulesIdToEquivalentULocale; 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static Map<String, PluralRanges> localeIdToPluralRanges; 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Access through singleton. 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private PluralRulesLoader() { 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rulesIdToRules = new HashMap<String, PluralRules>(); 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the locales for which we have plurals data. Utility for testing. 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public ULocale[] getAvailableULocales() { 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<String> keys = getLocaleIdToRulesIdMap(PluralType.CARDINAL).keySet(); 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale[] locales = new ULocale[keys.size()]; 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int n = 0; 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (Iterator<String> iter = keys.iterator(); iter.hasNext();) { 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert locales[n++] = ULocale.createCanonical(iter.next()); 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return locales; 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the functionally equivalent locale. 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public ULocale getFunctionalEquivalent(ULocale locale, boolean[] isAvailable) { 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isAvailable != null && isAvailable.length > 0) { 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String localeId = ULocale.canonicalize(locale.getBaseName()); 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, String> idMap = getLocaleIdToRulesIdMap(PluralType.CARDINAL); 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isAvailable[0] = idMap.containsKey(localeId); 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String rulesId = getRulesIdForLocale(locale, PluralType.CARDINAL); 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rulesId == null || rulesId.trim().length() == 0) { 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ULocale.ROOT; // ultimate fallback 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale result = getRulesIdToEquivalentULocaleMap().get( 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rulesId); 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result == null) { 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ULocale.ROOT; // ultimate fallback 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the lazily-constructed map. 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, String> getLocaleIdToRulesIdMap(PluralType type) { 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert checkBuildRulesIdMaps(); 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (type == PluralType.CARDINAL) ? localeIdToCardinalRulesId : localeIdToOrdinalRulesId; 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the lazily-constructed map. 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, ULocale> getRulesIdToEquivalentULocaleMap() { 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert checkBuildRulesIdMaps(); 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return rulesIdToEquivalentULocale; 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Lazily constructs the localeIdToRulesId and rulesIdToEquivalentULocale 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maps if necessary. These exactly reflect the contents of the locales 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * resource in plurals.res. 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void checkBuildRulesIdMaps() { 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean haveMap; 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (this) { 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert haveMap = localeIdToCardinalRulesId != null; 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!haveMap) { 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, String> tempLocaleIdToCardinalRulesId; 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, String> tempLocaleIdToOrdinalRulesId; 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, ULocale> tempRulesIdToEquivalentULocale; 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle pluralb = getPluralBundle(); 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Read cardinal-number rules. 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle localeb = pluralb.get("locales"); 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // sort for convenience of getAvailableULocales 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToCardinalRulesId = new TreeMap<String, String>(); 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not visible 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempRulesIdToEquivalentULocale = new HashMap<String, ULocale>(); 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < localeb.getSize(); ++i) { 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle b = localeb.get(i); 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String id = b.getKey(); 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String value = b.getString().intern(); 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToCardinalRulesId.put(id, value); 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!tempRulesIdToEquivalentULocale.containsKey(value)) { 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempRulesIdToEquivalentULocale.put(value, new ULocale(id)); 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Read ordinal-number rules. 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeb = pluralb.get("locales_ordinals"); 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToOrdinalRulesId = new TreeMap<String, String>(); 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < localeb.getSize(); ++i) { 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle b = localeb.get(i); 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String id = b.getKey(); 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String value = b.getString().intern(); 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToOrdinalRulesId.put(id, value); 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (MissingResourceException e) { 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // dummy so we don't try again 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToCardinalRulesId = Collections.emptyMap(); 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToOrdinalRulesId = Collections.emptyMap(); 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempRulesIdToEquivalentULocale = Collections.emptyMap(); 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized(this) { 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (localeIdToCardinalRulesId == null) { 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeIdToCardinalRulesId = tempLocaleIdToCardinalRulesId; 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeIdToOrdinalRulesId = tempLocaleIdToOrdinalRulesId; 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rulesIdToEquivalentULocale = tempRulesIdToEquivalentULocale; 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the rulesId from the locale,with locale fallback. If there is no 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rulesId, return null. The rulesId might be the empty string if the rule 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is the default rule. 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getRulesIdForLocale(ULocale locale, PluralType type) { 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, String> idMap = getLocaleIdToRulesIdMap(type); 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String localeId = ULocale.canonicalize(locale.getBaseName()); 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String rulesId = null; 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (null == (rulesId = idMap.get(localeId))) { 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ix = localeId.lastIndexOf("_"); 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ix == -1) { 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeId = localeId.substring(0, ix); 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return rulesId; 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the rule from the rulesId. If there is no rule for this rulesId, 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return null. 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralRules getRulesForRulesId(String rulesId) { 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // synchronize on the map. release the lock temporarily while we build the rules. 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules rules = null; 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean hasRules; // Separate boolean because stored rules can be null. 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (rulesIdToRules) { 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert hasRules = rulesIdToRules.containsKey(rulesId); 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (hasRules) { 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules = rulesIdToRules.get(rulesId); // can be null 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!hasRules) { 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle pluralb = getPluralBundle(); 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle rulesb = pluralb.get("rules"); 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle setb = rulesb.get(rulesId); 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder sb = new StringBuilder(); 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < setb.getSize(); ++i) { 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle b = setb.get(i); 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i > 0) { 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sb.append("; "); 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sb.append(b.getKey()); 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sb.append(": "); 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sb.append(b.getString()); 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules = PluralRules.parseDescription(sb.toString()); 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (ParseException e) { 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (MissingResourceException e) { 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (rulesIdToRules) { 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rulesIdToRules.containsKey(rulesId)) { 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules = rulesIdToRules.get(rulesId); 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rulesIdToRules.put(rulesId, rules); // can be null 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return rules; 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return the plurals resource. Note MissingResourceException is unchecked, 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * listed here for clarity. Callers should handle this exception. 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public UResourceBundle getPluralBundle() throws MissingResourceException { 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ICUResourceBundle.getBundleInstance( 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle.ICU_BASE_NAME, "plurals", 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle.ICU_DATA_CLASS_LOADER, true); 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the plural rules for the the locale. If we don't have data, 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * com.ibm.icu.text.PluralRules.DEFAULT is returned. 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralRules forLocale(ULocale locale, PluralRules.PluralType type) { 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String rulesId = getRulesIdForLocale(locale, type); 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rulesId == null || rulesId.trim().length() == 0) { 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return PluralRules.DEFAULT; 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules rules = getRulesForRulesId(rulesId); 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (rules == null) { 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules = PluralRules.DEFAULT; 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return rules; 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The only instance of the loader. 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final PluralRulesLoader loader = new PluralRulesLoader(); 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* (non-Javadoc) 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.text.PluralRules.Factory#hasOverride(com.ibm.icu.util.ULocale) 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean hasOverride(ULocale locale) { 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final PluralRanges UNKNOWN_RANGE = new PluralRanges().freeze(); 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralRanges getPluralRanges(ULocale locale) { 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO markdavis Fix the bad fallback, here and elsewhere in this file. 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String localeId = ULocale.canonicalize(locale.getBaseName()); 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRanges result; 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (null == (result = localeIdToPluralRanges.get(localeId))) { 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ix = localeId.lastIndexOf("_"); 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ix == -1) { 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = UNKNOWN_RANGE; 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeId = localeId.substring(0, ix); 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isPluralRangesAvailable(ULocale locale) { 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getPluralRanges(locale) == UNKNOWN_RANGE; 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO markdavis FIX HARD-CODED HACK once we have data from CLDR in the bundles 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static { 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[][] pluralRangeData = { 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "id ja km ko lo ms my th vi zh"}, 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "am bn fr gu hi hy kn mr pa zu"}, 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "fa"}, 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "other"}, 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "ka"}, 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "one"}, 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "az de el gl hu it kk ky ml mn ne nl pt sq sw ta te tr ug uz"}, 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "af bg ca en es et eu fi nb sv ur"}, 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "da fil is"}, 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "si"}, 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "mk"}, 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "other"}, 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "lv"}, 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "zero", "other"}, 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "one", "one"}, 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "other", "other"}, 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "zero", "other"}, 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "zero", "other"}, 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "ro"}, 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "one", "few"}, 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "hr sr bs"}, 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "one", "one"}, 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "sl"}, 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "few"}, 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "two", "two"}, 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "one", "few"}, 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "two", "two"}, 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "few", "few"}, 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "other", "other"}, 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "one", "few"}, 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "two", "two"}, 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "few"}, 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "two", "two"}, 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "he"}, 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "two", "other"}, 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "many", "many"}, 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "many", "other"}, 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "other", "other"}, 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "many", "many"}, 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "other", "many"}, 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "two", "other"}, 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "many", "many"}, 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "cs pl sk"}, 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "many", "many"}, 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "many", "many"}, 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "one", "one"}, 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "few", "few"}, 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "many", "many"}, 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "other", "other"}, 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "many", "many"}, 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "lt ru uk"}, 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "one", "one"}, 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "many", "many"}, 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "one", "one"}, 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "many", "many"}, 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "one", "one"}, 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "few", "few"}, 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "many", "many"}, 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "other", "other"}, 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "many", "many"}, 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "cy"}, 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "one", "one"}, 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "two", "two"}, 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "few", "few"}, 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "many", "many"}, 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "other", "other"}, 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "two", "two"}, 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "many", "many"}, 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "few", "few"}, 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "many", "many"}, 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "other", "other"}, 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "many", "many"}, 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "other", "other"}, 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "one"}, 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "two", "two"}, 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "many", "many"}, 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"locales", "ar"}, 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "one", "zero"}, 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "two", "zero"}, 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "few", "few"}, 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "many", "many"}, 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"zero", "other", "other"}, 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "two", "other"}, 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "few", "few"}, 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "many", "many"}, 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"one", "other", "other"}, 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "few", "few"}, 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "many", "many"}, 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"two", "other", "other"}, 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "few", "few"}, 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "many", "many"}, 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"few", "other", "other"}, 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "few", "few"}, 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "many", "many"}, 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"many", "other", "other"}, 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "one", "other"}, 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "two", "other"}, 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "few", "few"}, 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "many", "many"}, 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert {"other", "other", "other"}, 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRanges pr = null; 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] locales = null; 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert HashMap<String, PluralRanges> tempLocaleIdToPluralRanges = new HashMap<String, PluralRanges>(); 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String[] row : pluralRangeData) { 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (row[0].equals("locales")) { 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pr != null) { 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pr.freeze(); 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String locale : locales) { 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToPluralRanges.put(locale, pr); 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert locales = row[1].split(" "); 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pr = new PluralRanges(); 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pr.add( 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StandardPluralCategories.valueOf(row[0]), 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StandardPluralCategories.valueOf(row[1]), 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StandardPluralCategories.valueOf(row[2])); 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do last one 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String locale : locales) { 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tempLocaleIdToPluralRanges.put(locale, pr); 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // now make whole thing immutable 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert localeIdToPluralRanges = Collections.unmodifiableMap(tempLocaleIdToPluralRanges); 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}