• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html#License
3 /*
4  ********************************************************************************
5  * Copyright (C) 2003-2016, Google, International Business Machines Corporation
6  * and others. All Rights Reserved.
7  ********************************************************************************
8 */
9 package com.ibm.icu.util;
10 
11 import java.util.Arrays;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Locale;
15 import java.util.Map;
16 import java.util.MissingResourceException;
17 
18 import com.ibm.icu.impl.ICUCache;
19 import com.ibm.icu.impl.ICUData;
20 import com.ibm.icu.impl.ICUResourceBundle;
21 import com.ibm.icu.impl.SimpleCache;
22 
23 /**
24  * Provide information about gender in locales based on data in CLDR. Currently supplies gender of lists.
25  * @author markdavis
26  * @internal
27  * @deprecated This API is ICU internal only.
28  */
29 @Deprecated
30 public class GenderInfo {
31 
32     private final ListGenderStyle style; // set based on locale
33 
34     /**
35      * Gender: OTHER means either the information is unavailable, or the person has declined to state MALE or FEMALE.
36      * @internal
37      * @deprecated This API is ICU internal only.
38      */
39     @Deprecated
40     public enum Gender {
41         /**
42          * @internal
43          * @deprecated This API is ICU internal only.
44          */
45         @Deprecated
46         MALE,
47         /**
48          * @internal
49          * @deprecated This API is ICU internal only.
50          */
51         @Deprecated
52         FEMALE,
53         /**
54          * @internal
55          * @deprecated This API is ICU internal only.
56          */
57         @Deprecated
58         OTHER
59     }
60 
61     /**
62      * Create GenderInfo from a ULocale.
63      * @param uLocale desired locale
64      * @internal
65      * @deprecated This API is ICU internal only.
66      */
67     @Deprecated
getInstance(ULocale uLocale)68     public static GenderInfo getInstance(ULocale uLocale) {
69         return genderInfoCache.get(uLocale);
70     }
71 
72     /**
73      * Create GenderInfo from a Locale.
74      * @param locale desired locale
75      * @internal
76      * @deprecated This API is ICU internal only.
77      */
78     @Deprecated
getInstance(Locale locale)79     public static GenderInfo getInstance(Locale locale) {
80         return getInstance(ULocale.forLocale(locale));
81     }
82 
83     /**
84      * Enum only meant for use in CLDR and in testing. Indicates the category for the locale.
85      * This only affects gender for lists more than one. For lists of 1 item, the gender
86      * of the list always equals the gender of that sole item.
87      * @internal
88      * @deprecated This API is ICU internal only.
89      */
90     @Deprecated
91     public enum ListGenderStyle {
92         /**
93          * For an empty list, returns OTHER;
94          * For a single item, returns its gender;
95          * Otherwise always OTHER.
96          * @internal
97          * @deprecated This API is ICU internal only.
98          */
99         @Deprecated
100         NEUTRAL,
101         /**
102          * For an empty list, returns OTHER;
103          * For a single item, returns its gender;
104          * Otherwise gender(all male) = male, gender(all female) = female, otherwise gender(list) = other.
105          * So any 'other' value makes the overall gender be 'other'.
106          * @internal
107          * @deprecated This API is ICU internal only.
108          */
109         @Deprecated
110         MIXED_NEUTRAL,
111         /**
112          * For an empty list, returns OTHER;
113          * For a single item, returns its gender;
114          * Otherwise, gender(all female) = female, otherwise gender(list) = male.
115          * So for more than one item, any 'other' value makes the overall gender be 'male'.
116          * @internal
117          * @deprecated This API is ICU internal only.
118          */
119         @Deprecated
120         MALE_TAINTS;
121 
122         private static Map<String, ListGenderStyle> fromNameMap =
123             new HashMap<String, ListGenderStyle>(3);
124 
125         static {
126             fromNameMap.put("neutral", NEUTRAL);
127             fromNameMap.put("maleTaints", MALE_TAINTS);
128             fromNameMap.put("mixedNeutral", MIXED_NEUTRAL);
129         }
130 
131         /**
132          * @internal
133          * @deprecated This API is ICU internal only.
134          */
135         @Deprecated
fromName(String name)136         public static ListGenderStyle fromName(String name) {
137             ListGenderStyle result = fromNameMap.get(name);
138             if (result == null) {
139                 throw new IllegalArgumentException("Unknown gender style name: " + name);
140             }
141             return result;
142         }
143     }
144 
145     /**
146      * Get the gender of a list, based on locale usage.
147      * @param genders a list of genders.
148      * @return the gender of the list.
149      * @internal
150      * @deprecated This API is ICU internal only.
151      */
152     @Deprecated
getListGender(Gender... genders)153     public Gender getListGender(Gender... genders) {
154         return getListGender(Arrays.asList(genders));
155     }
156 
157     /**
158      * Get the gender of a list, based on locale usage.
159      * @param genders a list of genders.
160      * @return the gender of the list.
161      * @internal
162      * @deprecated This API is ICU internal only.
163      */
164     @Deprecated
getListGender(List<Gender> genders)165     public Gender getListGender(List<Gender> genders) {
166         if (genders.size() == 0) {
167             return Gender.OTHER; // degenerate case
168         }
169         if (genders.size() == 1) {
170             return genders.get(0); // degenerate case
171         }
172         switch(style) {
173         case NEUTRAL:
174             return Gender.OTHER;
175         case MIXED_NEUTRAL:
176             boolean hasFemale = false;
177             boolean hasMale = false;
178             for (Gender gender : genders) {
179                 switch (gender) {
180                 case FEMALE:
181                     if (hasMale) {
182                         return Gender.OTHER;
183                     }
184                     hasFemale = true;
185                     break;
186                 case MALE:
187                     if (hasFemale) {
188                         return Gender.OTHER;
189                     }
190                     hasMale = true;
191                     break;
192                 case OTHER:
193                     return Gender.OTHER;
194                 }
195             }
196             return hasMale ? Gender.MALE : Gender.FEMALE;
197             // Note: any OTHER would have caused a return in the loop, which always happens.
198         case MALE_TAINTS:
199             for (Gender gender : genders) {
200                 if (gender != Gender.FEMALE) {
201                     return Gender.MALE;
202                 }
203             }
204             return Gender.FEMALE;
205         default:
206             return Gender.OTHER;
207         }
208     }
209 
210     /**
211      * Only for testing and use with CLDR.
212      * @param genderStyle gender style
213      * @internal
214      * @deprecated This API is ICU internal only.
215      */
216     @Deprecated
GenderInfo(ListGenderStyle genderStyle)217     public GenderInfo(ListGenderStyle genderStyle) {
218         style = genderStyle;
219     }
220 
221     private static GenderInfo neutral = new GenderInfo(ListGenderStyle.NEUTRAL);
222 
223     private static class Cache {
224         private final ICUCache<ULocale, GenderInfo> cache =
225             new SimpleCache<ULocale, GenderInfo>();
226 
get(ULocale locale)227         public GenderInfo get(ULocale locale) {
228             GenderInfo result = cache.get(locale);
229             if (result == null) {
230                 result = load(locale);
231                 if (result == null) {
232                     ULocale fallback = locale.getFallback();
233 
234                     // We call get() recursively so that we can leverage the cache
235                     // for all fallback locales too. If we get to the root locale,
236                     // and find no resource assume that list gender style is NEUTRAL.
237                     result = fallback == null ? neutral : get(fallback);
238                 }
239                 cache.put(locale, result);
240             }
241             return result;
242         }
243 
load(ULocale ulocale)244         private static GenderInfo load(ULocale ulocale) {
245             UResourceBundle rb = UResourceBundle.getBundleInstance(
246                     ICUData.ICU_BASE_NAME,
247                     "genderList",
248                     ICUResourceBundle.ICU_DATA_CLASS_LOADER, true);
249             UResourceBundle genderList = rb.get("genderList");
250             try {
251                 return new GenderInfo(
252                         ListGenderStyle.fromName(genderList.getString(ulocale.toString())));
253             } catch (MissingResourceException mre) {
254                 return null;
255             }
256         }
257     }
258 
259     private static Cache genderInfoCache = new Cache();
260 }
261