blob: ad6ee7e2c8bf3d10393125e1299f06754e01d7de [file] [log] [blame]
package com.ibm.icu.text;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import com.ibm.icu.util.ULocale;
/**
* Provide information about gender in locales based on data in CLDR. Currently just gender of lists.
*
* @author markdavis
*/
public class GenderInfo {
private final ListGenderStyle style; // set based on locale
/**
* Gender: OTHER means either the information is unavailable, or the person has declined to state MALE or FEMALE.
*/
public enum Gender {
MALE, FEMALE, OTHER
}
/**
* Create GenderInfo from a ULocale.
*
* @param uLocale
*/
public GenderInfo(ULocale uLocale) {
ULocale language = new ULocale(uLocale.getLanguage()); // in the hard coded data, the language is sufficient.
// Will change with RB.
ListGenderStyle tempStyle = localeToListGender.get(language);
style = tempStyle == null ? ListGenderStyle.NEUTRAL : tempStyle;
}
/**
* Create GenderInfo from a Locale.
*
* @param uLocale
*/
public GenderInfo(Locale locale) {
this(ULocale.forLocale(locale));
}
/**
* Enum only meant for use in CLDR and in testing. Indicates the category for the locale.
*/
public enum ListGenderStyle {
/**
* Always OTHER (if more than one)
*/
NEUTRAL,
/**
* gender(all male) = male, gender(all female) = female, otherwise gender(list) = other
*/
MIXED_NEUTRAL,
/**
* gender(all female) = female, otherwise gender(list) = male
*/
MALE_TAINTS
}
/**
* Reset the data used for mapping locales to styles. Only for use in CLDR and in testing.
*
* @param uLocale
*/
public static void setLocaleMapping(Map<ULocale, ListGenderStyle> newULocaleToListGender) {
localeToListGender.clear();
for (Entry<ULocale, ListGenderStyle> entry : newULocaleToListGender.entrySet()) {
localeToListGender.put(entry.getKey(), entry.getValue());
}
}
/**
* Get the gender of a list, based on locale usage.
*
* @param genders
* a list of genders.
* @return the gender of the list.
*/
public Gender getListGender(Gender... genders) {
return getListGender(Arrays.asList(genders));
}
/**
* Get the gender of a list, based on locale usage.
*
* @param genders
* a list of genders.
* @return the gender of the list.
*/
public Gender getListGender(List<Gender> genders) {
if (genders.size() == 0 || style == ListGenderStyle.NEUTRAL) {
return Gender.OTHER; // degenerate case
}
if (genders.size() == 1) {
return genders.get(0); // degenerate case
}
switch (style) {
case MIXED_NEUTRAL: // gender(all male) = male, gender(all female) = female, otherwise gender(list) = other
boolean hasFemale = false;
boolean hasMale = false;
for (Gender gender : genders) {
switch (gender) {
case FEMALE:
if (hasMale) {
return Gender.OTHER;
}
hasFemale = true;
break;
case MALE:
if (hasFemale) {
return Gender.OTHER;
}
hasMale = true;
break;
case OTHER:
return Gender.OTHER;
}
}
return hasMale ? Gender.MALE : hasFemale ? Gender.FEMALE : Gender.OTHER;
case MALE_TAINTS: // gender(all female) = female, otherwise gender(list) = male
for (Gender gender : genders) {
if (gender != Gender.FEMALE) {
return Gender.MALE;
}
}
return Gender.FEMALE;
default:
return Gender.OTHER;
}
}
// TODO Get this data from a resource bundle generated from CLDR.
// For now, hard coded.
private static Map<ULocale, ListGenderStyle> localeToListGender = new HashMap<ULocale, ListGenderStyle>();
static {
for (String locale : Arrays.asList("ar", "ca", "cs", "hr", "es", "fr", "he", "hi", "it", "lt", "lv", "mr",
"nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr", "uk", "ur", "zh")) {
localeToListGender.put(new ULocale(locale), ListGenderStyle.MALE_TAINTS);
}
for (String locale : Arrays.asList("el", "is")) {
localeToListGender.put(new ULocale(locale), ListGenderStyle.MIXED_NEUTRAL);
}
}
}