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