1 package org.unicode.cldr.util; 2 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.HashSet; 6 import java.util.Set; 7 8 import com.ibm.icu.text.PluralRules; 9 10 public class PluralRulesUtil { 11 /** 12 * Status of the keyword for the rules, given a set of explicit values. 13 */ 14 public enum KeywordStatus { 15 /** 16 * The keyword is not valid for the rules. 17 */ 18 INVALID, 19 /** 20 * The keyword is valid, but unused (it is covered by the explicit values). 21 */ 22 SUPPRESSED, 23 /** 24 * The keyword is valid and used, but completely covered by the explicit values. 25 */ 26 UNIQUE, 27 /** 28 * The keyword is valid, used, not suppressed, and has a finite set of values. 29 */ 30 BOUNDED, 31 /** 32 * The keyword is valid but not bounded; there are indefinitely many matching values. 33 */ 34 UNBOUNDED 35 } 36 37 /** 38 * Find the status for the keyword, given a certain set of explicit values. 39 * 40 * @param rules 41 * the PluralRules 42 * @param keyword 43 * the particular keyword (call rules.getKeywords() to get the valid ones) 44 * @param offset 45 * the offset used, or 0.0d if not. Internally, the offset is subtracted from each explicit value before 46 * checking against the keyword values. 47 * @param explicits 48 * a set of Doubles that are used explicitly (eg [=0], "[=1]"). May be empty or null. 49 * @param integerOnly 50 * In circumstances where the values are known to be integers, this parameter can be set to true. 51 * Examples: "There are 3 people in..." (integerOnly=true) vs. "There are 1.2 people per household 52 * (integerOnly=false). 53 * This may produce different results in languages where fractions have the same format as integers for 54 * some keywords. 55 * @return the KeywordStatus 56 * <p> 57 * NOTE: For testing, this is a static with the first parameter being the rules. Those will disappear. 58 */ getKeywordStatus(PluralRules rules, String keyword, int offset, Set<Double> explicits, boolean integerOnly)59 public static KeywordStatus getKeywordStatus(PluralRules rules, String keyword, int offset, Set<Double> explicits, 60 boolean integerOnly) { 61 if (!rules.getKeywords().contains(keyword)) { 62 return KeywordStatus.INVALID; 63 } 64 Collection<Double> values = rules.getAllKeywordValues(keyword); 65 if (values == null) { 66 return KeywordStatus.UNBOUNDED; 67 } 68 int originalSize = values.size(); 69 70 // Quick check on whether there are multiple elements 71 72 if (explicits == null) { 73 explicits = Collections.emptySet(); 74 } 75 if (originalSize > explicits.size()) { 76 return originalSize == 1 ? KeywordStatus.UNIQUE : KeywordStatus.BOUNDED; 77 } 78 79 // Compute if the quick test is insufficient. 80 81 HashSet<Double> subtractedSet = new HashSet<>(values); 82 for (Double explicit : explicits) { 83 // int rounded = (int) Math.round(explicit*1000000); 84 subtractedSet.remove(explicit - offset); 85 } 86 if (subtractedSet.size() == 0) { 87 return KeywordStatus.SUPPRESSED; 88 } 89 90 return originalSize == 1 ? KeywordStatus.UNIQUE : KeywordStatus.BOUNDED; 91 } 92 93 // static final Map<String,Set<String>> locale2keywords = new HashMap<String,Set<String>>(); 94 // static final Map<String,PluralRules> locale2pluralRules = new HashMap<String,PluralRules>(); 95 // static final Set<Double> explicits = new HashSet<Double>(); 96 // static { 97 // explicits.add(0.0d); 98 // explicits.add(1.0d); 99 // } 100 // public static Set<String> getCanonicalKeywords(String locale) { 101 // synchronized (locale2keywords) { 102 // Set<String> result = locale2keywords.get(locale); 103 // if (result != null) { 104 // return result; 105 // } 106 // // special caching because locales don't differ 107 // int pos = locale.indexOf('_'); 108 // String lang = pos < 0 ? locale : locale.substring(0,pos); 109 // if (pos >= 0) { 110 // result = locale2keywords.get(locale); 111 // if (result != null) { 112 // locale2keywords.put(locale, result); 113 // return result; 114 // } 115 // } 116 // PluralInfo pluralInfo = SupplementalDataInfo.getInstance().getPlurals(SupplementalDataInfo.PluralType.cardinal, 117 // lang); 118 // PluralRules pluralRules = PluralRules.createRules(pluralInfo.getRules()); 119 // locale2pluralRules.put(lang, pluralRules); 120 // result = new HashSet(); 121 // for (String keyword : pluralRules.getKeywords()) { 122 // KeywordStatus status = getKeywordStatus(pluralRules, keyword, 0, explicits, true); 123 // if (status != KeywordStatus.SUPPRESSED) { 124 // result.add(keyword); 125 // } 126 // } 127 // result = Collections.unmodifiableSet(result); 128 // locale2keywords.put(locale, result); 129 // if (pos >= 0) { 130 // locale2keywords.put(lang, result); 131 // } 132 // return result; 133 // } 134 // 135 // } 136 } 137