1 package com.ibm.icu.text; 2 3 import java.util.Arrays; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Locale; 7 import java.util.Map; 8 import java.util.Map.Entry; 9 10 import com.ibm.icu.util.ULocale; 11 12 /** 13 * Provide information about gender in locales based on data in CLDR. Currently just gender of lists. 14 * 15 * @author markdavis 16 */ 17 public class GenderInfo { 18 19 private final ListGenderStyle style; // set based on locale 20 21 /** 22 * Gender: OTHER means either the information is unavailable, or the person has declined to state MALE or FEMALE. 23 */ 24 public enum Gender { 25 MALE, FEMALE, OTHER 26 } 27 28 /** 29 * Create GenderInfo from a ULocale. 30 * 31 * @param uLocale 32 */ GenderInfo(ULocale uLocale)33 public GenderInfo(ULocale uLocale) { 34 ULocale language = new ULocale(uLocale.getLanguage()); // in the hard coded data, the language is sufficient. 35 // Will change with RB. 36 ListGenderStyle tempStyle = localeToListGender.get(language); 37 style = tempStyle == null ? ListGenderStyle.NEUTRAL : tempStyle; 38 } 39 40 /** 41 * Create GenderInfo from a Locale. 42 * 43 * @param uLocale 44 */ GenderInfo(Locale locale)45 public GenderInfo(Locale locale) { 46 this(ULocale.forLocale(locale)); 47 } 48 49 /** 50 * Enum only meant for use in CLDR and in testing. Indicates the category for the locale. 51 */ 52 public enum ListGenderStyle { 53 /** 54 * Always OTHER (if more than one) 55 */ 56 NEUTRAL, 57 /** 58 * gender(all male) = male, gender(all female) = female, otherwise gender(list) = other 59 */ 60 MIXED_NEUTRAL, 61 /** 62 * gender(all female) = female, otherwise gender(list) = male 63 */ 64 MALE_TAINTS 65 } 66 67 /** 68 * Reset the data used for mapping locales to styles. Only for use in CLDR and in testing. 69 * 70 * @param uLocale 71 */ setLocaleMapping(Map<ULocale, ListGenderStyle> newULocaleToListGender)72 public static void setLocaleMapping(Map<ULocale, ListGenderStyle> newULocaleToListGender) { 73 localeToListGender.clear(); 74 for (Entry<ULocale, ListGenderStyle> entry : newULocaleToListGender.entrySet()) { 75 localeToListGender.put(entry.getKey(), entry.getValue()); 76 } 77 } 78 79 /** 80 * Get the gender of a list, based on locale usage. 81 * 82 * @param genders 83 * a list of genders. 84 * @return the gender of the list. 85 */ getListGender(Gender... genders)86 public Gender getListGender(Gender... genders) { 87 return getListGender(Arrays.asList(genders)); 88 } 89 90 /** 91 * Get the gender of a list, based on locale usage. 92 * 93 * @param genders 94 * a list of genders. 95 * @return the gender of the list. 96 */ getListGender(List<Gender> genders)97 public Gender getListGender(List<Gender> genders) { 98 if (genders.size() == 0 || style == ListGenderStyle.NEUTRAL) { 99 return Gender.OTHER; // degenerate case 100 } 101 if (genders.size() == 1) { 102 return genders.get(0); // degenerate case 103 } 104 switch (style) { 105 case MIXED_NEUTRAL: // gender(all male) = male, gender(all female) = female, otherwise gender(list) = other 106 boolean hasFemale = false; 107 boolean hasMale = false; 108 for (Gender gender : genders) { 109 switch (gender) { 110 case FEMALE: 111 if (hasMale) { 112 return Gender.OTHER; 113 } 114 hasFemale = true; 115 break; 116 case MALE: 117 if (hasFemale) { 118 return Gender.OTHER; 119 } 120 hasMale = true; 121 break; 122 case OTHER: 123 return Gender.OTHER; 124 } 125 } 126 return hasMale ? Gender.MALE : hasFemale ? Gender.FEMALE : Gender.OTHER; 127 case MALE_TAINTS: // gender(all female) = female, otherwise gender(list) = male 128 for (Gender gender : genders) { 129 if (gender != Gender.FEMALE) { 130 return Gender.MALE; 131 } 132 } 133 return Gender.FEMALE; 134 default: 135 return Gender.OTHER; 136 } 137 } 138 139 // TODO Get this data from a resource bundle generated from CLDR. 140 // For now, hard coded. 141 142 private static Map<ULocale, ListGenderStyle> localeToListGender = new HashMap<ULocale, ListGenderStyle>(); 143 static { 144 for (String locale : Arrays.asList("ar", "ca", "cs", "hr", "es", "fr", "he", "hi", "it", "lt", "lv", "mr", 145 "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr", "uk", "ur", "zh")) { localeToListGender.put(new ULocale(locale), ListGenderStyle.MALE_TAINTS)146 localeToListGender.put(new ULocale(locale), ListGenderStyle.MALE_TAINTS); 147 } 148 for (String locale : Arrays.asList("el", "is")) { localeToListGender.put(new ULocale(locale), ListGenderStyle.MIXED_NEUTRAL)149 localeToListGender.put(new ULocale(locale), ListGenderStyle.MIXED_NEUTRAL); 150 } 151 } 152 } 153