diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/PluralRulesLoader.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/PluralRulesLoader.java index 8ed630d0589..f2097fcd29b 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/PluralRulesLoader.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/PluralRulesLoader.java @@ -1,7 +1,7 @@ /* ******************************************************************************* - * Copyright (C) 2008-2014, International Business Machines Corporation and * - * others. All Rights Reserved. * + * Copyright (C) 2008-2015, International Business Machines Corporation and + * others. All Rights Reserved. ******************************************************************************* */ package com.ibm.icu.impl; @@ -18,7 +18,6 @@ import java.util.TreeMap; import com.ibm.icu.text.PluralRanges; import com.ibm.icu.text.PluralRules; import com.ibm.icu.text.PluralRules.PluralType; -import com.ibm.icu.text.PluralRules.StandardPluralCategories; import com.ibm.icu.util.ULocale; import com.ibm.icu.util.UResourceBundle; @@ -486,9 +485,9 @@ public class PluralRulesLoader extends PluralRules.Factory { pr = new PluralRanges(); } else { pr.add( - StandardPluralCategories.valueOf(row[0]), - StandardPluralCategories.valueOf(row[1]), - StandardPluralCategories.valueOf(row[2])); + StandardPlural.fromString(row[0]), + StandardPlural.fromString(row[1]), + StandardPlural.fromString(row[2])); } } // do last one diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java new file mode 100644 index 00000000000..a6d606f709b --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java @@ -0,0 +1,142 @@ +/* + ******************************************************************************* + * Copyright (C) 2015, International Business Machines Corporation and + * others. All Rights Reserved. + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Standard CLDR plural form/category constants. + * See http://www.unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules + */ +public enum StandardPlural { + ZERO("zero"), + ONE("one"), + TWO("two"), + FEW("few"), + MANY("many"), + OTHER("other"); + + /** + * Numeric index of OTHER, same as OTHER.ordinal(). + */ + public static final int OTHER_INDEX = OTHER.ordinal(); + + /** + * Unmodifiable List of all standard plural form constants. + * List version of {@link #values()}. + */ + public static final List VALUES = + Collections.unmodifiableList(Arrays.asList(values())); + + /** + * Number of standard plural forms/categories. + */ + public static final int COUNT = VALUES.size(); + + private final String keyword; + + private StandardPlural(String kw) { + keyword = kw; + } + + /** + * @return the lowercase CLDR keyword string for the plural form + */ + public final String getKeyword() { + return keyword; + } + + /** + * @param keyword for example "few" or "other" + * @return the plural form corresponding to the keyword, or null + */ + public static final StandardPlural orNullFromString(CharSequence keyword) { + switch (keyword.length()) { + case 3: + if ("one".contentEquals(keyword)) { + return ONE; + } else if ("two".contentEquals(keyword)) { + return TWO; + } else if ("few".contentEquals(keyword)) { + return FEW; + } + break; + case 4: + if ("many".contentEquals(keyword)) { + return MANY; + } else if ("zero".contentEquals(keyword)) { + return ZERO; + } + break; + case 5: + if ("other".contentEquals(keyword)) { + return OTHER; + } + break; + default: + break; + } + return null; + } + + /** + * @param keyword for example "few" or "other" + * @return the plural form corresponding to the keyword, or OTHER + */ + public static final StandardPlural orOtherFromString(CharSequence keyword) { + StandardPlural p = orNullFromString(keyword); + return p != null ? p : OTHER; + } + + /** + * @param keyword for example "few" or "other" + * @return the plural form corresponding to the keyword + * @throws IllegalArgumentException if the keyword is not a plural form + */ + public static final StandardPlural fromString(CharSequence keyword) { + StandardPlural p = orNullFromString(keyword); + if (p != null) { + return p; + } else { + throw new IllegalArgumentException(keyword.toString()); + } + } + + /** + * @param keyword for example "few" or "other" + * @return the index of the plural form corresponding to the keyword, or a negative value + */ + public static final int indexOrNegativeFromString(CharSequence keyword) { + StandardPlural p = orNullFromString(keyword); + return p != null ? p.ordinal() : -1; + } + + /** + * @param keyword for example "few" or "other" + * @return the index of the plural form corresponding to the keyword, or OTHER_INDEX + */ + public static final int indexOrOtherIndexFromString(CharSequence keyword) { + StandardPlural p = orNullFromString(keyword); + return p != null ? p.ordinal() : OTHER.ordinal(); + } + + /** + * @param keyword for example "few" or "other" + * @return the index of the plural form corresponding to the keyword + * @throws IllegalArgumentException if the keyword is not a plural form + */ + public static final int indexFromString(CharSequence keyword) { + StandardPlural p = orNullFromString(keyword); + if (p != null) { + return p.ordinal(); + } else { + throw new IllegalArgumentException(keyword.toString()); + } + } +} \ No newline at end of file diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java index cf0dc24e1c2..482f564af10 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java @@ -33,10 +33,10 @@ import com.ibm.icu.impl.ICUData; import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.SimpleCache; import com.ibm.icu.impl.SimplePatternFormatter; +import com.ibm.icu.impl.StandardPlural; import com.ibm.icu.impl.UResource; import com.ibm.icu.math.BigDecimal; import com.ibm.icu.text.PluralRules.Factory; -import com.ibm.icu.text.PluralRules.StandardPluralCategories; import com.ibm.icu.util.Currency; import com.ibm.icu.util.CurrencyAmount; import com.ibm.icu.util.ICUException; @@ -422,8 +422,9 @@ public class MeasureFormat extends UFormat { highFpos.getCountVisibleFractionDigits(), highFpos.getFractionDigits())); final PluralRanges pluralRanges = Factory.getDefaultFactory().getPluralRanges(getLocale()); - StandardPluralCategories resolvedCategory = pluralRanges.get( - StandardPluralCategories.valueOf(keywordLow), StandardPluralCategories.valueOf(keywordHigh)); + StandardPlural resolvedPlural = pluralRanges.get( + StandardPlural.fromString(keywordLow), + StandardPlural.fromString(keywordHigh)); SimplePatternFormatter rangeFormatter = getRangeFormat(getLocale(), formatWidth); String formattedNumber = rangeFormatter.format(lowFormatted, highFormatted); @@ -434,9 +435,9 @@ public class MeasureFormat extends UFormat { Currency currencyUnit = (Currency) unit; StringBuilder result = new StringBuilder(); - appendReplacingCurrency(currencyFormat.getPrefix(lowDouble >= 0), currencyUnit, resolvedCategory, result); + appendReplacingCurrency(currencyFormat.getPrefix(lowDouble >= 0), currencyUnit, resolvedPlural, result); result.append(formattedNumber); - appendReplacingCurrency(currencyFormat.getSuffix(highDouble >= 0), currencyUnit, resolvedCategory, result); + appendReplacingCurrency(currencyFormat.getSuffix(highDouble >= 0), currencyUnit, resolvedPlural, result); return result.toString(); // StringBuffer buffer = new StringBuffer(); // CurrencyAmount currencyLow = (CurrencyAmount) lowValue; @@ -449,12 +450,12 @@ public class MeasureFormat extends UFormat { // currencyFormat.format(currencyHigh, buffer2, pos2); } else { SimplePatternFormatter formatter = - getPluralFormatter(lowValue.getUnit(), formatWidth, resolvedCategory.ordinal()); + getPluralFormatter(lowValue.getUnit(), formatWidth, resolvedPlural.ordinal()); return formatter.format(formattedNumber); } } - private void appendReplacingCurrency(String affix, Currency unit, StandardPluralCategories resolvedCategory, StringBuilder result) { + private void appendReplacingCurrency(String affix, Currency unit, StandardPlural resolvedPlural, StringBuilder result) { String replacement = "¤"; int pos = affix.indexOf(replacement); if (pos < 0) { @@ -473,7 +474,7 @@ public class MeasureFormat extends UFormat { } else { result.append(unit.getName(currencyFormat.nf.getLocale(ULocale.ACTUAL_LOCALE), currentStyle == NumberFormat.CURRENCYSTYLE ? Currency.SYMBOL_NAME : Currency.PLURAL_LONG_NAME, - resolvedCategory.toString(), null)); + resolvedPlural.getKeyword(), null)); } result.append(affix.substring(pos+replacement.length())); } @@ -783,7 +784,7 @@ public class MeasureFormat extends UFormat { // The key must be one of the plural form strings. For example: // one{"{0} hr"} // other{"{0} hrs"} - setFormatterIfAbsent(StandardPluralCategories.getIndex(key), value, 0); + setFormatterIfAbsent(StandardPlural.indexFromString(key), value, 0); } } } @@ -963,13 +964,13 @@ public class MeasureFormat extends UFormat { } private SimplePatternFormatter getPluralFormatter(MeasureUnit unit, FormatWidth width, int index) { - if (index != StandardPluralCategories.OTHER_INDEX) { + if (index != StandardPlural.OTHER_INDEX) { SimplePatternFormatter pattern = getFormatterOrNull(unit, width, index); if (pattern != null) { return pattern; } } - return getFormatter(unit, width, StandardPluralCategories.OTHER_INDEX); + return getFormatter(unit, width, StandardPlural.OTHER_INDEX); } private SimplePatternFormatter getPerFormatter(FormatWidth width) { @@ -999,7 +1000,7 @@ public class MeasureFormat extends UFormat { } SimplePatternFormatter perPattern = getPerFormatter(formatWidth); SimplePatternFormatter pattern = - getPluralFormatter(perUnit, formatWidth, StandardPluralCategories.one.ordinal()); + getPluralFormatter(perUnit, formatWidth, StandardPlural.ONE.ordinal()); String perUnitString = pattern.getPatternWithNoPlaceholders().trim(); perPattern.formatAndAppend(appendTo, offsets, formatted, perUnitString); return offsets[0]; @@ -1030,7 +1031,7 @@ public class MeasureFormat extends UFormat { StringBuffer formattedNumber = nf.format(n, new StringBuffer(), fpos); String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits())); - int pluralForm = StandardPluralCategories.getIndexOrOtherIndex(keyword); + int pluralForm = StandardPlural.indexOrOtherIndexFromString(keyword); SimplePatternFormatter formatter = getPluralFormatter(unit, formatWidth, pluralForm); int[] offsets = new int[1]; formatter.formatAndAppend(appendTo, offsets, formattedNumber); @@ -1056,7 +1057,7 @@ public class MeasureFormat extends UFormat { * TODO: Maybe store more sparsely in general, with pointers rather than potentially-empty objects. */ private static final class MeasureFormatData { - static final int PER_UNIT_INDEX = StandardPluralCategories.COUNT; + static final int PER_UNIT_INDEX = StandardPlural.COUNT; static final int PATTERN_COUNT = PER_UNIT_INDEX + 1; boolean hasPerFormatter(FormatWidth width) { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRanges.java b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRanges.java index 2d2b72c7902..7aab6d2ce3b 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRanges.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRanges.java @@ -1,7 +1,7 @@ /* ******************************************************************************* - * Copyright (C) 2008-2014, Google, International Business Machines Corporation and * - * others. All Rights Reserved. * + * Copyright (C) 2008-2015, Google, International Business Machines Corporation and + * others. All Rights Reserved. ******************************************************************************* */ package com.ibm.icu.text; @@ -9,7 +9,7 @@ package com.ibm.icu.text; import java.util.Arrays; import java.util.EnumSet; -import com.ibm.icu.text.PluralRules.StandardPluralCategories; +import com.ibm.icu.impl.StandardPlural; import com.ibm.icu.util.Freezable; import com.ibm.icu.util.Output; @@ -26,7 +26,7 @@ public final class PluralRanges implements Freezable, Comparable

, Comparable

, Cloneable { - private byte[] data = new byte[StandardPluralCategories.COUNT * StandardPluralCategories.COUNT]; + private byte[] data = new byte[StandardPlural.COUNT * StandardPlural.COUNT]; { for (int i = 0; i < data.length; ++i) { data[i] = -1; @@ -56,41 +56,41 @@ public final class PluralRanges implements Freezable, Comparable

= 0) { throw new IllegalArgumentException("Previously set value for <" + start + ", " + end + ", " - + StandardPluralCategories.VALUES.get(old) + ">"); + + StandardPlural.VALUES.get(old) + ">"); } - data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()] = result == null ? (byte) -1 + data[start.ordinal() * StandardPlural.COUNT + end.ordinal()] = result == null ? (byte) -1 : (byte) result.ordinal(); } /** * Internal method for getting. */ - StandardPluralCategories get(StandardPluralCategories start, StandardPluralCategories end) { - byte result = data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()]; - return result < 0 ? null : StandardPluralCategories.VALUES.get(result); + StandardPlural get(StandardPlural start, StandardPlural end) { + byte result = data[start.ordinal() * StandardPlural.COUNT + end.ordinal()]; + return result < 0 ? null : StandardPlural.VALUES.get(result); } /** * Internal method to see if <*,end> values are all the same. */ @SuppressWarnings("unused") - StandardPluralCategories endSame(StandardPluralCategories end) { - StandardPluralCategories first = null; - for (StandardPluralCategories start : StandardPluralCategories.VALUES) { - StandardPluralCategories item = get(start, end); + StandardPlural endSame(StandardPlural end) { + StandardPlural first = null; + for (StandardPlural start : StandardPlural.VALUES) { + StandardPlural item = get(start, end); if (item == null) { continue; } @@ -109,12 +109,12 @@ public final class PluralRanges implements Freezable, Comparable

values are all the same. */ @SuppressWarnings("unused") - StandardPluralCategories startSame(StandardPluralCategories start, - EnumSet endDone, Output emit) { + StandardPlural startSame(StandardPlural start, + EnumSet endDone, Output emit) { emit.value = false; - StandardPluralCategories first = null; - for (StandardPluralCategories end : StandardPluralCategories.VALUES) { - StandardPluralCategories item = get(start, end); + StandardPlural first = null; + for (StandardPlural end : StandardPlural.VALUES) { + StandardPlural item = get(start, end); if (item == null) { continue; } @@ -170,9 +170,9 @@ public final class PluralRanges implements Freezable, Comparable

, Comparable

, Comparable

, Comparable

, Comparable

, Comparable

VALUES = - Collections.unmodifiableList(Arrays.asList(values())); - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final int COUNT = VALUES.size(); - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final StandardPluralCategories getCategoryOrNull(CharSequence keyword) { - switch (keyword.length()) { - case 3: - if ("one".contentEquals(keyword)) { - return one; - } else if ("two".contentEquals(keyword)) { - return two; - } else if ("few".contentEquals(keyword)) { - return few; - } - break; - case 4: - if ("many".contentEquals(keyword)) { - return many; - } else if ("zero".contentEquals(keyword)) { - return zero; - } - break; - case 5: - if ("other".contentEquals(keyword)) { - return other; - } - break; - default: - break; - } - return null; - } - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final StandardPluralCategories getCategoryOrOther(CharSequence keyword) { - StandardPluralCategories cat = getCategoryOrNull(keyword); - return cat != null ? cat : other; - } - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final StandardPluralCategories getCategory(CharSequence keyword) { - StandardPluralCategories cat = getCategoryOrNull(keyword); - if (cat != null) { - return cat; - } else { - throw new IllegalArgumentException(keyword.toString()); - } - } - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final int getIndexOrNegative(CharSequence keyword) { - StandardPluralCategories cat = getCategoryOrNull(keyword); - return cat != null ? cat.ordinal() : -1; - } - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final int getIndexOrOtherIndex(CharSequence keyword) { - StandardPluralCategories cat = getCategoryOrNull(keyword); - return cat != null ? cat.ordinal() : other.ordinal(); - } - - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public static final int getIndex(CharSequence keyword) { - StandardPluralCategories cat = getCategoryOrNull(keyword); - if (cat != null) { - return cat.ordinal(); - } else { - throw new IllegalArgumentException(keyword.toString()); - } - } - } - @SuppressWarnings("unused") private boolean addConditional(Set toAddTo, Set others, double trial) { boolean added; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java b/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java index baf34f7d197..cd5ae87fb9d 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java @@ -7,7 +7,7 @@ package com.ibm.icu.text; import com.ibm.icu.impl.SimplePatternFormatter; -import com.ibm.icu.text.PluralRules.StandardPluralCategories; +import com.ibm.icu.impl.StandardPlural; /** * QuantityFormatter represents an unknown quantity of something and formats a known quantity @@ -19,7 +19,7 @@ import com.ibm.icu.text.PluralRules.StandardPluralCategories; */ class QuantityFormatter { private final SimplePatternFormatter[] templates = - new SimplePatternFormatter[StandardPluralCategories.COUNT]; + new SimplePatternFormatter[StandardPlural.COUNT]; public QuantityFormatter() {} @@ -34,7 +34,7 @@ class QuantityFormatter { * if template has more than just the {0} placeholder. */ public void addIfAbsent(CharSequence variant, String template) { - int idx = StandardPluralCategories.getIndex(variant); + int idx = StandardPlural.indexFromString(variant); if (templates[idx] != null) { return; } @@ -45,7 +45,7 @@ class QuantityFormatter { * @return true if this object has at least the "other" variant */ public boolean isValid() { - return templates[StandardPluralCategories.OTHER_INDEX] != null; + return templates[StandardPlural.OTHER_INDEX] != null; } /** @@ -69,9 +69,9 @@ class QuantityFormatter { */ public SimplePatternFormatter getByVariant(CharSequence variant) { assert isValid(); - int idx = StandardPluralCategories.getIndexOrOtherIndex(variant); + int idx = StandardPlural.indexOrOtherIndexFromString(variant); SimplePatternFormatter template = templates[idx]; - return (template == null && idx != StandardPluralCategories.OTHER_INDEX) ? - templates[StandardPluralCategories.OTHER_INDEX] : template; + return (template == null && idx != StandardPlural.OTHER_INDEX) ? + templates[StandardPlural.OTHER_INDEX] : template; } } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRangesTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRangesTest.java index c58335928ac..641e6450a3d 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRangesTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRangesTest.java @@ -1,7 +1,7 @@ /* ******************************************************************************* - * Copyright (C) 2008-2014, International Business Machines Corporation and * - * others. All Rights Reserved. * + * Copyright (C) 2008-2015, International Business Machines Corporation and + * others. All Rights Reserved. ******************************************************************************* */ package com.ibm.icu.dev.test.format; @@ -9,11 +9,11 @@ package com.ibm.icu.dev.test.format; import java.util.Arrays; import com.ibm.icu.dev.test.TestFmwk; +import com.ibm.icu.impl.StandardPlural; import com.ibm.icu.text.MeasureFormat; import com.ibm.icu.text.MeasureFormat.FormatWidth; import com.ibm.icu.text.PluralRanges; import com.ibm.icu.text.PluralRules.Factory; -import com.ibm.icu.text.PluralRules.StandardPluralCategories; import com.ibm.icu.util.Currency; import com.ibm.icu.util.Measure; import com.ibm.icu.util.MeasureUnit; @@ -41,12 +41,12 @@ public class PluralRangesTest extends TestFmwk { }; for (String[] test : tests) { final ULocale locale = new ULocale(test[0]); - final StandardPluralCategories start = StandardPluralCategories.valueOf(test[1]); - final StandardPluralCategories end = StandardPluralCategories.valueOf(test[2]); - final StandardPluralCategories expected = StandardPluralCategories.valueOf(test[3]); + final StandardPlural start = StandardPlural.fromString(test[1]); + final StandardPlural end = StandardPlural.fromString(test[2]); + final StandardPlural expected = StandardPlural.fromString(test[3]); final PluralRanges pluralRanges = Factory.getDefaultFactory().getPluralRanges(locale); - StandardPluralCategories actual = pluralRanges.get(start, end); + StandardPlural actual = pluralRanges.get(start, end); assertEquals("Deriving range category", expected, actual); } } @@ -110,12 +110,12 @@ public class PluralRangesTest extends TestFmwk { public void TestBasic() { PluralRanges a = new PluralRanges(); - a.add(StandardPluralCategories.one, StandardPluralCategories.other, StandardPluralCategories.one); - StandardPluralCategories actual = a.get(StandardPluralCategories.one, StandardPluralCategories.other); - assertEquals("range", StandardPluralCategories.one, actual); + a.add(StandardPlural.ONE, StandardPlural.OTHER, StandardPlural.ONE); + StandardPlural actual = a.get(StandardPlural.ONE, StandardPlural.OTHER); + assertEquals("range", StandardPlural.ONE, actual); a.freeze(); try { - a.add(StandardPluralCategories.one, StandardPluralCategories.one, StandardPluralCategories.one); + a.add(StandardPlural.ONE, StandardPlural.ONE, StandardPlural.ONE); errln("Failed to cause exception on frozen instance"); } catch (UnsupportedOperationException e) { }