17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ********************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2003-2014, Google, International Business Machines Corporation *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and others. All Rights Reserved.                                             *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ********************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.util;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUCache;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.SimpleCache;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Provide information about gender in locales based on data in CLDR. Currently supplies gender of lists.
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author markdavis
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only.
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert@Deprecated
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class GenderInfo {
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final ListGenderStyle style; // set based on locale
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Gender: OTHER means either the information is unavailable, or the person has declined to state MALE or FEMALE.
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public enum Gender {
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        MALE,
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        FEMALE,
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        OTHER
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Create GenderInfo from a ULocale.
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param uLocale desired locale
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static GenderInfo getInstance(ULocale uLocale) {
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return genderInfoCache.get(uLocale);
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Create GenderInfo from a Locale.
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param locale desired locale
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static GenderInfo getInstance(Locale locale) {
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return getInstance(ULocale.forLocale(locale));
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Enum only meant for use in CLDR and in testing. Indicates the category for the locale.
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This only affects gender for lists more than one. For lists of 1 item, the gender
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * of the list always equals the gender of that sole item.
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public enum ListGenderStyle {
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For an empty list, returns OTHER;
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For a single item, returns its gender;
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Otherwise always OTHER.
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        NEUTRAL,
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For an empty list, returns OTHER;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For a single item, returns its gender;
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Otherwise gender(all male) = male, gender(all female) = female, otherwise gender(list) = other.
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * So any 'other' value makes the overall gender be 'other'.
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        MIXED_NEUTRAL,
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For an empty list, returns OTHER;
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * For a single item, returns its gender;
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Otherwise, gender(all female) = female, otherwise gender(list) = male.
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * So for more than one item, any 'other' value makes the overall gender be 'male'.
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        MALE_TAINTS;
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static Map<String, ListGenderStyle> fromNameMap =
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new HashMap<String, ListGenderStyle>(3);
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static {
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromNameMap.put("neutral", NEUTRAL);
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromNameMap.put("maleTaints", MALE_TAINTS);
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromNameMap.put("mixedNeutral", MIXED_NEUTRAL);
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @internal
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @deprecated This API is ICU internal only.
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Deprecated
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public static ListGenderStyle fromName(String name) {
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ListGenderStyle result = fromNameMap.get(name);
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result == null) {
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IllegalArgumentException("Unknown gender style name: " + name);
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Get the gender of a list, based on locale usage.
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param genders a list of genders.
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the gender of the list.
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Gender getListGender(Gender... genders) {
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return getListGender(Arrays.asList(genders));
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Get the gender of a list, based on locale usage.
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param genders a list of genders.
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the gender of the list.
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Gender getListGender(List<Gender> genders) {
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (genders.size() == 0) {
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Gender.OTHER; // degenerate case
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (genders.size() == 1) {
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return genders.get(0); // degenerate case
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch(style) {
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case NEUTRAL:
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Gender.OTHER;
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case MIXED_NEUTRAL:
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean hasFemale = false;
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean hasMale = false;
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (Gender gender : genders) {
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (gender) {
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case FEMALE:
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (hasMale) {
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        return Gender.OTHER;
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    hasFemale = true;
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case MALE:
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (hasFemale) {
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        return Gender.OTHER;
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    hasMale = true;
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case OTHER:
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return Gender.OTHER;
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return hasMale ? Gender.MALE : Gender.FEMALE;
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Note: any OTHER would have caused a return in the loop, which always happens.
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case MALE_TAINTS:
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (Gender gender : genders) {
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (gender != Gender.FEMALE) {
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return Gender.MALE;
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Gender.FEMALE;
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default:
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Gender.OTHER;
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Only for testing and use with CLDR.
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param genderStyle gender style
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public GenderInfo(ListGenderStyle genderStyle) {
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        style = genderStyle;
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static GenderInfo neutral = new GenderInfo(ListGenderStyle.NEUTRAL);
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static class Cache {
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private final ICUCache<ULocale, GenderInfo> cache =
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new SimpleCache<ULocale, GenderInfo>();
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public GenderInfo get(ULocale locale) {
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            GenderInfo result = cache.get(locale);
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result == null) {
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = load(locale);
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (result == null) {
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ULocale fallback = locale.getFallback();
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // We call get() recursively so that we can leverage the cache
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // for all fallback locales too. If we get to the root locale,
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // and find no resource assume that list gender style is NEUTRAL.
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result = fallback == null ? neutral : get(fallback);
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cache.put(locale, result);
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static GenderInfo load(ULocale ulocale) {
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UResourceBundle rb = UResourceBundle.getBundleInstance(
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ICUResourceBundle.ICU_BASE_NAME,
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    "genderList",
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ICUResourceBundle.ICU_DATA_CLASS_LOADER, true);
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UResourceBundle genderList = rb.get("genderList");
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            try {
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return new GenderInfo(
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ListGenderStyle.fromName(genderList.getString(ulocale.toString())));
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } catch (MissingResourceException mre) {
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static Cache genderInfoCache = new Cache();
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
258