17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2008-2014, Google, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.EnumSet;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.StandardPluralCategories;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Freezable;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Output;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Utility class for returning the plural category for a range of numbers, such as 1–5, so that appropriate messages can
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be chosen. The rules for determining this value vary widely across locales.
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author markdavis
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only.
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert@Deprecated
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic final class PluralRanges implements Freezable<PluralRanges>, Comparable<PluralRanges> {
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private volatile boolean isFrozen;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Matrix matrix = new Matrix();
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean[] explicit = new boolean[StandardPluralCategories.COUNT];
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Constructor
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public PluralRanges() {
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Internal class for mapping from two StandardPluralCategories values to another.
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class Matrix implements Comparable<Matrix>, Cloneable {
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private byte[] data = new byte[StandardPluralCategories.COUNT * StandardPluralCategories.COUNT];
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < data.length; ++i) {
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                data[i] = -1;
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Matrix() {
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Internal method for setting.
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("unused")
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        void set(StandardPluralCategories start, StandardPluralCategories end, StandardPluralCategories result) {
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()] = result == null ? (byte) -1
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    : (byte) result.ordinal();
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Internal method for setting; throws exception if already set.
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        void setIfNew(StandardPluralCategories start, StandardPluralCategories end,
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                StandardPluralCategories result) {
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte old = data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()];
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (old >= 0) {
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IllegalArgumentException("Previously set value for <" + start + ", " + end + ", "
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        + StandardPluralCategories.VALUES.get(old) + ">");
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()] = result == null ? (byte) -1
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    : (byte) result.ordinal();
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Internal method for getting.
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StandardPluralCategories get(StandardPluralCategories start, StandardPluralCategories end) {
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte result = data[start.ordinal() * StandardPluralCategories.COUNT + end.ordinal()];
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result < 0 ? null : StandardPluralCategories.VALUES.get(result);
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Internal method to see if <*,end> values are all the same.
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("unused")
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StandardPluralCategories endSame(StandardPluralCategories end) {
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StandardPluralCategories first = null;
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (StandardPluralCategories start : StandardPluralCategories.VALUES) {
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                StandardPluralCategories item = get(start, end);
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (item == null) {
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    continue;
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (first == null) {
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    first = item;
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    continue;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (first != item) {
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return first;
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Internal method to see if <start,*> values are all the same.
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("unused")
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StandardPluralCategories startSame(StandardPluralCategories start,
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                EnumSet<StandardPluralCategories> endDone, Output<Boolean> emit) {
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            emit.value = false;
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StandardPluralCategories first = null;
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (StandardPluralCategories end : StandardPluralCategories.VALUES) {
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                StandardPluralCategories item = get(start, end);
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (item == null) {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    continue;
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (first == null) {
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    first = item;
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    continue;
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (first != item) {
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // only emit if we didn't cover with the 'end' values
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!endDone.contains(end)) {
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    emit.value = true;
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return first;
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int hashCode() {
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int result = 0;
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < data.length; ++i) {
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = result * 37 + data[i];
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean equals(Object other) {
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!(other instanceof Matrix)) {
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return false;
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 0 == compareTo((Matrix) other);
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int compareTo(Matrix o) {
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < data.length; ++i) {
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int diff = data[i] - o.data[i];
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (diff != 0) {
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return diff;
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 0;
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Matrix clone() {
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Matrix result = new Matrix();
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.data = data.clone();
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String toString() {
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StringBuilder result = new StringBuilder();
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (StandardPluralCategories i : StandardPluralCategories.values()) {
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (StandardPluralCategories j : StandardPluralCategories.values()) {
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    StandardPluralCategories x = get(i, j);
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (x != null) {
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        result.append(i + " & " + j + " → " + x + ";\n");
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result.toString();
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Internal method for building. If the start or end are null, it means everything of that type.
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param rangeStart
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the start of the range
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param rangeEnd
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the end of the range
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param result
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            the resulting plural category
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void add(StandardPluralCategories rangeStart, StandardPluralCategories rangeEnd,
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StandardPluralCategories result) {
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isFrozen) {
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new UnsupportedOperationException();
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        explicit[result.ordinal()] = true;
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (rangeStart == null) {
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (StandardPluralCategories rs : StandardPluralCategories.values()) {
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (rangeEnd == null) {
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (StandardPluralCategories re : StandardPluralCategories.values()) {
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        matrix.setIfNew(rs, re, result);
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    explicit[rangeEnd.ordinal()] = true;
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    matrix.setIfNew(rs, rangeEnd, result);
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (rangeEnd == null) {
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            explicit[rangeStart.ordinal()] = true;
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (StandardPluralCategories re : StandardPluralCategories.values()) {
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                matrix.setIfNew(rangeStart, re, result);
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            explicit[rangeStart.ordinal()] = true;
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            explicit[rangeEnd.ordinal()] = true;
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            matrix.setIfNew(rangeStart, rangeEnd, result);
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the appropriate plural category for a range from start to end. If there is no available data, then
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 'end' is returned as an implicit value. (Such an implicit value can be tested for with {@link #isExplicit}.)
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param start
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the start of the range
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param end
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the end of the range
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the resulting plural category, or 'end' if there is no data.
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StandardPluralCategories get(StandardPluralCategories start, StandardPluralCategories end) {
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StandardPluralCategories result = matrix.get(start, end);
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result == null ? end : result;
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns whether the appropriate plural category for a range from start to end
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is explicitly in the data (vs given an implicit value). See also {@link #get}.
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param start
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the start of the range
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param end
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category for the end of the range
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return whether the value for (start,end) is explicit or not.
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isExplicit(StandardPluralCategories start, StandardPluralCategories end) {
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return matrix.get(start, end) != null;
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Internal method to determines whether the StandardPluralCategories was explicitly used in any add statement.
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param count
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            plural category to test
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if set
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isExplicitlySet(StandardPluralCategories count) {
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return explicit[count.ordinal()];
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean equals(Object other) {
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (this == other) {
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!(other instanceof PluralRanges)) {
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        PluralRanges otherPR = (PluralRanges)other;
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return matrix.equals(otherPR.matrix) && Arrays.equals(explicit, otherPR.explicit);
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int hashCode() {
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return matrix.hashCode();
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int compareTo(PluralRanges that) {
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return matrix.compareTo(that.matrix);
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isFrozen() {
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return isFrozen;
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public PluralRanges freeze() {
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isFrozen = true;
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return this;
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public PluralRanges cloneAsThawed() {
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        PluralRanges result = new PluralRanges();
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.explicit = explicit.clone();
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.matrix = matrix.clone();
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String toString() {
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return matrix.toString();
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}