aboutsummaryrefslogtreecommitdiff
path: root/src/com/ibm/icu/simple/PluralRulesLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/ibm/icu/simple/PluralRulesLoader.java')
-rw-r--r--src/com/ibm/icu/simple/PluralRulesLoader.java180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/com/ibm/icu/simple/PluralRulesLoader.java b/src/com/ibm/icu/simple/PluralRulesLoader.java
new file mode 100644
index 0000000..23383ea
--- /dev/null
+++ b/src/com/ibm/icu/simple/PluralRulesLoader.java
@@ -0,0 +1,180 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2008-2013, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.simple;
+
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TreeMap;
+
+import com.ibm.icu.simple.PluralRules.PluralType;
+
+/**
+ * Loader for plural rules data.
+ */
+public class PluralRulesLoader extends PluralRules.Factory {
+ // Data created from ICU4C with the command
+ // ~/svn.icu/trunk/bld$ LD_LIBRARY_PATH=lib bin/genrb --write-java UTF-8 --java-package com.ibm.icu.simple -s ../src/source/data/misc/ plurals.txt -d /tmp/icu
+ private static final ResourceBundle DATA_RB = new LocaleElements_plurals();
+
+ private final Map<String, PluralRules> rulesIdToRules;
+ // lazy init, use getLocaleIdToRulesIdMap to access
+ private Map<String, String> localeIdToCardinalRulesId;
+ private Map<String, String> localeIdToOrdinalRulesId;
+
+ /**
+ * Access through singleton.
+ */
+ private PluralRulesLoader() {
+ rulesIdToRules = new HashMap<String, PluralRules>();
+ }
+
+ /**
+ * Returns the lazily-constructed map.
+ */
+ private Map<String, String> getLocaleIdToRulesIdMap(PluralType type) {
+ checkBuildRulesIdMaps();
+ return (type == PluralType.CARDINAL) ? localeIdToCardinalRulesId : localeIdToOrdinalRulesId;
+ }
+
+ /**
+ * Lazily constructs the localeIdToRulesId and rulesIdToEquivalentULocale
+ * maps if necessary. These exactly reflect the contents of the locales
+ * resource in plurals.res.
+ */
+ private void checkBuildRulesIdMaps() {
+ boolean haveMap;
+ synchronized (this) {
+ haveMap = localeIdToCardinalRulesId != null;
+ }
+ if (!haveMap) {
+ Map<String, String> tempLocaleIdToCardinalRulesId;
+ Map<String, String> tempLocaleIdToOrdinalRulesId;
+ try {
+ ResourceBundle pluralb = DATA_RB;
+ // Read cardinal-number rules.
+ Object[][] localeb = (Object[][]) pluralb.getObject("locales");
+
+ // sort for convenience of getAvailableULocales
+ tempLocaleIdToCardinalRulesId = new TreeMap<String, String>();
+
+ for (Object[] langAndId : localeb) {
+ String id = (String) langAndId[0];
+ String value = (String) langAndId[1];
+ tempLocaleIdToCardinalRulesId.put(id, value);
+ }
+
+ // Read ordinal-number rules.
+ localeb = (Object[][]) pluralb.getObject("locales_ordinals");
+ tempLocaleIdToOrdinalRulesId = new TreeMap<String, String>();
+ for (Object[] langAndId : localeb) {
+ String id = (String) langAndId[0];
+ String value = (String) langAndId[1];
+ tempLocaleIdToOrdinalRulesId.put(id, value);
+ }
+ } catch (MissingResourceException e) {
+ // dummy so we don't try again
+ tempLocaleIdToCardinalRulesId = Collections.emptyMap();
+ tempLocaleIdToOrdinalRulesId = Collections.emptyMap();
+ }
+
+ synchronized(this) {
+ if (localeIdToCardinalRulesId == null) {
+ localeIdToCardinalRulesId = tempLocaleIdToCardinalRulesId;
+ localeIdToOrdinalRulesId = tempLocaleIdToOrdinalRulesId;
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the rulesId from the locale,with locale fallback. If there is no
+ * rulesId, return null. The rulesId might be the empty string if the rule
+ * is the default rule.
+ */
+ public String getRulesIdForLocale(Locale locale, PluralType type) {
+ Map<String, String> idMap = getLocaleIdToRulesIdMap(type);
+ String lang = locale.getLanguage();
+ String rulesId = idMap.get(lang);
+ return rulesId;
+ }
+
+ /**
+ * Gets the rule from the rulesId. If there is no rule for this rulesId,
+ * return null.
+ */
+ public PluralRules getRulesForRulesId(String rulesId) {
+ // synchronize on the map. release the lock temporarily while we build the rules.
+ PluralRules rules = null;
+ boolean hasRules; // Separate boolean because stored rules can be null.
+ synchronized (rulesIdToRules) {
+ hasRules = rulesIdToRules.containsKey(rulesId);
+ if (hasRules) {
+ rules = rulesIdToRules.get(rulesId); // can be null
+ }
+ }
+ if (!hasRules) {
+ try {
+ ResourceBundle pluralb = DATA_RB;
+ Object[][] rulesb = (Object[][]) pluralb.getObject("rules");
+ Object[][] setb = null;
+ for (Object[] idAndRule : rulesb) { // Unbounded loop: We must find the rulesId.
+ if (rulesId.equals(idAndRule[0])) {
+ setb = (Object[][]) idAndRule[1];
+ break;
+ }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (Object[] keywordAndRule : setb) {
+ if (sb.length() > 0) {
+ sb.append("; ");
+ }
+ sb.append((String) keywordAndRule[0]);
+ sb.append(": ");
+ sb.append((String) keywordAndRule[1]);
+ }
+ rules = PluralRules.parseDescription(sb.toString());
+ } catch (ParseException e) {
+ } catch (MissingResourceException e) {
+ }
+ synchronized (rulesIdToRules) {
+ if (rulesIdToRules.containsKey(rulesId)) {
+ rules = rulesIdToRules.get(rulesId);
+ } else {
+ rulesIdToRules.put(rulesId, rules); // can be null
+ }
+ }
+ }
+ return rules;
+ }
+
+ /**
+ * Returns the plural rules for the the locale. If we don't have data,
+ * com.ibm.icu.text.PluralRules.DEFAULT is returned.
+ */
+ public PluralRules forLocale(Locale locale, PluralRules.PluralType type) {
+ String rulesId = getRulesIdForLocale(locale, type);
+ if (rulesId == null || rulesId.trim().length() == 0) {
+ return PluralRules.DEFAULT;
+ }
+ PluralRules rules = getRulesForRulesId(rulesId);
+ if (rules == null) {
+ rules = PluralRules.DEFAULT;
+ }
+ return rules;
+ }
+
+ /**
+ * The only instance of the loader.
+ */
+ public static final PluralRulesLoader loader = new PluralRulesLoader();
+}