com.ibm.icu.impl.LocaleDisplayNamesImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icu4j Show documentation
Show all versions of icu4j Show documentation
International Component for Unicode for Java (ICU4J) is a mature, widely used Java library
providing Unicode and Globalization support
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2009-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.Set;
import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo;
import com.ibm.icu.impl.locale.AsciiUtil;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.lang.UScript;
import com.ibm.icu.text.BreakIterator;
import com.ibm.icu.text.CaseMap;
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.DisplayContext.Type;
import com.ibm.icu.text.LocaleDisplayNames;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
private final ULocale locale;
private final DialectHandling dialectHandling;
private final DisplayContext capitalization;
private final DisplayContext nameLength;
private final DisplayContext substituteHandling;
private final DataTable langData;
private final DataTable regionData;
// Compiled SimpleFormatter patterns.
private final String separatorFormat;
private final String format;
private final String keyTypeFormat;
private final char formatOpenParen;
private final char formatReplaceOpenParen;
private final char formatCloseParen;
private final char formatReplaceCloseParen;
private final CurrencyDisplayInfo currencyDisplayInfo;
private static final Cache cache = new Cache();
/**
* Capitalization context usage types for locale display names
*/
private enum CapitalizationContextUsage {
LANGUAGE,
SCRIPT,
TERRITORY,
VARIANT,
KEY,
KEYVALUE
}
/**
* Capitalization transforms. For each usage type, indicates whether to titlecase for
* the context specified in capitalization (which we know at construction time).
*/
private boolean[] capitalizationUsage = null;
/**
* Map from resource key to CapitalizationContextUsage value
*/
private static final Map contextUsageTypeMap;
static {
contextUsageTypeMap=new HashMap();
contextUsageTypeMap.put("languages", CapitalizationContextUsage.LANGUAGE);
contextUsageTypeMap.put("script", CapitalizationContextUsage.SCRIPT);
contextUsageTypeMap.put("territory", CapitalizationContextUsage.TERRITORY);
contextUsageTypeMap.put("variant", CapitalizationContextUsage.VARIANT);
contextUsageTypeMap.put("key", CapitalizationContextUsage.KEY);
contextUsageTypeMap.put("keyValue", CapitalizationContextUsage.KEYVALUE);
}
/**
* BreakIterator to use for capitalization
*/
private transient BreakIterator capitalizationBrkIter = null;
private static final CaseMap.Title TO_TITLE_WHOLE_STRING_NO_LOWERCASE =
CaseMap.toTitle().wholeString().noLowercase();
private static String toTitleWholeStringNoLowercase(ULocale locale, String s) {
return TO_TITLE_WHOLE_STRING_NO_LOWERCASE.apply(locale.toLocale(), null, s);
}
public static LocaleDisplayNames getInstance(ULocale locale, DialectHandling dialectHandling) {
synchronized (cache) {
return cache.get(locale, dialectHandling);
}
}
public static LocaleDisplayNames getInstance(ULocale locale, DisplayContext... contexts) {
synchronized (cache) {
return cache.get(locale, contexts);
}
}
private final class CapitalizationContextSink extends UResource.Sink {
boolean hasCapitalizationUsage = false;
@Override
public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
UResource.Table contextsTable = value.getTable();
for (int i = 0; contextsTable.getKeyAndValue(i, key, value); ++i) {
CapitalizationContextUsage usage = contextUsageTypeMap.get(key.toString());
if (usage == null) { continue; };
int[] intVector = value.getIntVector();
if (intVector.length < 2) { continue; }
int titlecaseInt = (capitalization == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU)
? intVector[0] : intVector[1];
if (titlecaseInt == 0) { continue; }
capitalizationUsage[usage.ordinal()] = true;
hasCapitalizationUsage = true;
}
}
}
public LocaleDisplayNamesImpl(ULocale locale, DialectHandling dialectHandling) {
this(locale, (dialectHandling==DialectHandling.STANDARD_NAMES)? DisplayContext.STANDARD_NAMES: DisplayContext.DIALECT_NAMES,
DisplayContext.CAPITALIZATION_NONE);
}
public LocaleDisplayNamesImpl(ULocale locale, DisplayContext... contexts) {
DialectHandling dialectHandling = DialectHandling.STANDARD_NAMES;
DisplayContext capitalization = DisplayContext.CAPITALIZATION_NONE;
DisplayContext nameLength = DisplayContext.LENGTH_FULL;
DisplayContext substituteHandling = DisplayContext.SUBSTITUTE;
for (DisplayContext contextItem : contexts) {
switch (contextItem.type()) {
case DIALECT_HANDLING:
dialectHandling = (contextItem.value()==DisplayContext.STANDARD_NAMES.value())?
DialectHandling.STANDARD_NAMES: DialectHandling.DIALECT_NAMES;
break;
case CAPITALIZATION:
capitalization = contextItem;
break;
case DISPLAY_LENGTH:
nameLength = contextItem;
break;
case SUBSTITUTE_HANDLING:
substituteHandling = contextItem;
break;
default:
break;
}
}
this.dialectHandling = dialectHandling;
this.capitalization = capitalization;
this.nameLength = nameLength;
this.substituteHandling = substituteHandling;
this.langData = LangDataTables.impl.get(locale, substituteHandling == DisplayContext.NO_SUBSTITUTE);
this.regionData = RegionDataTables.impl.get(locale, substituteHandling == DisplayContext.NO_SUBSTITUTE);
this.locale = ULocale.ROOT.equals(langData.getLocale()) ? regionData.getLocale() :
langData.getLocale();
// Note, by going through DataTable, this uses table lookup rather than straight lookup.
// That should get us the same data, I think. This way we don't have to explicitly
// load the bundle again. Using direct lookup didn't seem to make an appreciable
// difference in performance.
String sep = langData.get("localeDisplayPattern", "separator");
if (sep == null || "separator".equals(sep)) {
sep = "{0}, {1}";
}
StringBuilder sb = new StringBuilder();
this.separatorFormat = SimpleFormatterImpl.compileToStringMinMaxArguments(sep, sb, 2, 2);
String pattern = langData.get("localeDisplayPattern", "pattern");
if (pattern == null || "pattern".equals(pattern)) {
pattern = "{0} ({1})";
}
this.format = SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, sb, 2, 2);
if (pattern.contains("(")) {
formatOpenParen = '(';
formatCloseParen = ')';
formatReplaceOpenParen = '[';
formatReplaceCloseParen = ']';
} else {
formatOpenParen = '(';
formatCloseParen = ')';
formatReplaceOpenParen = '[';
formatReplaceCloseParen = ']';
}
String keyTypePattern = langData.get("localeDisplayPattern", "keyTypePattern");
if (keyTypePattern == null || "keyTypePattern".equals(keyTypePattern)) {
keyTypePattern = "{0}={1}";
}
this.keyTypeFormat = SimpleFormatterImpl.compileToStringMinMaxArguments(
keyTypePattern, sb, 2, 2);
// Get values from the contextTransforms data if we need them
// Also check whether we will need a break iterator (depends on the data)
boolean needBrkIter = false;
if (capitalization == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU ||
capitalization == DisplayContext.CAPITALIZATION_FOR_STANDALONE) {
capitalizationUsage = new boolean[CapitalizationContextUsage.values().length]; // initialized to all false
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
CapitalizationContextSink sink = new CapitalizationContextSink();
try {
rb.getAllItemsWithFallback("contextTransforms", sink);
}
catch (MissingResourceException e) {
// Silently ignore. Not every locale has contextTransforms.
}
needBrkIter = sink.hasCapitalizationUsage;
}
// Get a sentence break iterator if we will need it
if (needBrkIter || capitalization == DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) {
capitalizationBrkIter = BreakIterator.getSentenceInstance(locale);
}
this.currencyDisplayInfo = CurrencyData.provider.getInstance(locale, false);
}
@Override
public ULocale getLocale() {
return locale;
}
@Override
public DialectHandling getDialectHandling() {
return dialectHandling;
}
@Override
public DisplayContext getContext(DisplayContext.Type type) {
DisplayContext result;
switch (type) {
case DIALECT_HANDLING:
result = (dialectHandling==DialectHandling.STANDARD_NAMES)? DisplayContext.STANDARD_NAMES: DisplayContext.DIALECT_NAMES;
break;
case CAPITALIZATION:
result = capitalization;
break;
case DISPLAY_LENGTH:
result = nameLength;
break;
case SUBSTITUTE_HANDLING:
result = substituteHandling;
break;
default:
result = DisplayContext.STANDARD_NAMES; // hmm, we should do something else here
break;
}
return result;
}
private String adjustForUsageAndContext(CapitalizationContextUsage usage, String name) {
if (name != null && name.length() > 0 && UCharacter.isLowerCase(name.codePointAt(0)) &&
(capitalization==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
(capitalizationUsage != null && capitalizationUsage[usage.ordinal()]) )) {
// Note, won't have capitalizationUsage != null && capitalizationUsage[usage.ordinal()]
// unless capitalization is CAPITALIZATION_FOR_UI_LIST_OR_MENU or CAPITALIZATION_FOR_STANDALONE
synchronized (this) {
if (capitalizationBrkIter == null) {
// should only happen when deserializing, etc.
capitalizationBrkIter = BreakIterator.getSentenceInstance(locale);
}
return UCharacter.toTitleCase(locale, name, capitalizationBrkIter,
UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
}
}
return name;
}
@Override
public String localeDisplayName(ULocale locale) {
return localeDisplayNameInternal(locale);
}
@Override
public String localeDisplayName(Locale locale) {
return localeDisplayNameInternal(ULocale.forLocale(locale));
}
@Override
public String localeDisplayName(String localeId) {
return localeDisplayNameInternal(new ULocale(localeId));
}
// TODO: implement use of capitalization
private String localeDisplayNameInternal(ULocale locale) {
// lang
// lang (script, country, variant, keyword=value, ...)
// script, country, variant, keyword=value, ...
String resultName = null;
String lang = locale.getLanguage();
// Empty basename indicates root locale (keywords are ignored for this).
// For the display name, we treat this as unknown language (ICU-20273).
if (lang.isEmpty()) {
lang = "und";
}
String script = locale.getScript();
String country = locale.getCountry();
String variant = locale.getVariant();
boolean hasScript = script.length() > 0;
boolean hasCountry = country.length() > 0;
boolean hasVariant = variant.length() > 0;
// always have a value for lang
if (dialectHandling == DialectHandling.DIALECT_NAMES) {
do { // loop construct is so we can break early out of search
if (hasScript && hasCountry) {
String langScriptCountry = lang + '_' + script + '_' + country;
String result = localeIdName(langScriptCountry);
if (result != null && !result.equals(langScriptCountry)) {
resultName = result;
hasScript = false;
hasCountry = false;
break;
}
}
if (hasScript) {
String langScript = lang + '_' + script;
String result = localeIdName(langScript);
if (result != null && !result.equals(langScript)) {
resultName = result;
hasScript = false;
break;
}
}
if (hasCountry) {
String langCountry = lang + '_' + country;
String result = localeIdName(langCountry);
if (result != null && !result.equals(langCountry)) {
resultName = result;
hasCountry = false;
break;
}
}
} while (false);
}
if (resultName == null) {
String result = localeIdName(lang);
if (result == null) { return null; }
resultName = result
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen);
}
StringBuilder buf = new StringBuilder();
if (hasScript) {
// first element, don't need appendWithSep
String result = scriptDisplayNameInContext(script, true);
if (result == null) { return null; }
buf.append(result
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen));
}
if (hasCountry) {
String result = regionDisplayName(country, true);
if (result == null) { return null; }
appendWithSep(result
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen), buf);
}
if (hasVariant) {
String result = variantDisplayName(variant, true);
if (result == null) { return null; }
appendWithSep(result
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen), buf);
}
Iterator keys = locale.getKeywords();
if (keys != null) {
while (keys.hasNext()) {
String key = keys.next();
String value = locale.getKeywordValue(key);
String keyDisplayName = keyDisplayName(key, true);
if (keyDisplayName == null) { return null; }
keyDisplayName = keyDisplayName
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen);
String valueDisplayName = keyValueDisplayName(key, value, true);
if (valueDisplayName == null) { return null; }
valueDisplayName = valueDisplayName
.replace(formatOpenParen, formatReplaceOpenParen)
.replace(formatCloseParen, formatReplaceCloseParen);
if (!valueDisplayName.equals(value)) {
appendWithSep(valueDisplayName, buf);
} else if (!key.equals(keyDisplayName)) {
String keyValue = SimpleFormatterImpl.formatCompiledPattern(
keyTypeFormat, keyDisplayName, valueDisplayName);
appendWithSep(keyValue, buf);
} else {
appendWithSep(keyDisplayName, buf)
.append("=")
.append(valueDisplayName);
}
}
}
String resultRemainder = null;
if (buf.length() > 0) {
resultRemainder = buf.toString();
}
if (resultRemainder != null) {
resultName = SimpleFormatterImpl.formatCompiledPattern(
format, resultName, resultRemainder);
}
return adjustForUsageAndContext(CapitalizationContextUsage.LANGUAGE, resultName);
}
private String localeIdName(String localeId) {
String locIdName;
if (nameLength == DisplayContext.LENGTH_SHORT) {
locIdName = langData.get("Languages%short", localeId);
if (locIdName != null && !locIdName.equals(localeId)) {
return locIdName;
}
}
locIdName = langData.get("Languages", localeId);
if ((locIdName == null || locIdName.equals(localeId)) && localeId.indexOf('_') < 0) {
// Canonicalize lang and try again, ICU-20870
// (only for language codes without script or region)
ULocale canonLocale = ULocale.createCanonical(localeId);
String canonLocId = canonLocale.getName();
if (nameLength == DisplayContext.LENGTH_SHORT) {
locIdName = langData.get("Languages%short", canonLocId);
if (locIdName != null && !locIdName.equals(canonLocId)) {
return locIdName;
}
}
locIdName = langData.get("Languages", canonLocId);
}
return locIdName;
}
@Override
public String languageDisplayName(String lang) {
// Special case to eliminate non-languages, which pollute our data.
if (lang.equals("root") || lang.indexOf('_') != -1) {
return substituteHandling == DisplayContext.SUBSTITUTE ? lang : null;
}
String langName;
if (nameLength == DisplayContext.LENGTH_SHORT) {
langName = langData.get("Languages%short", lang);
if (langName != null && !langName.equals(lang)) {
return adjustForUsageAndContext(CapitalizationContextUsage.LANGUAGE, langName);
}
}
langName = langData.get("Languages", lang);
if (langName == null || langName.equals(lang)) {
// Canonicalize lang and try again, ICU-20870
ULocale canonLocale = ULocale.createCanonical(lang);
String canonLocId = canonLocale.getName();
if (nameLength == DisplayContext.LENGTH_SHORT) {
langName = langData.get("Languages%short", canonLocId);
if (langName != null && !langName.equals(canonLocId)) {
return adjustForUsageAndContext(CapitalizationContextUsage.LANGUAGE, langName);
}
}
langName = langData.get("Languages", canonLocId);
}
return adjustForUsageAndContext(CapitalizationContextUsage.LANGUAGE, langName);
}
@Override
public String scriptDisplayName(String script) {
String str = langData.get("Scripts%stand-alone", script);
if (str == null || str.equals(script)) {
if (nameLength == DisplayContext.LENGTH_SHORT) {
str = langData.get("Scripts%short", script);
if (str != null && !str.equals(script)) {
return adjustForUsageAndContext(CapitalizationContextUsage.SCRIPT, str);
}
}
str = langData.get("Scripts", script);
}
return adjustForUsageAndContext(CapitalizationContextUsage.SCRIPT, str);
}
private String scriptDisplayNameInContext(String script, boolean skipAdjust) {
if (nameLength == DisplayContext.LENGTH_SHORT) {
String scriptName = langData.get("Scripts%short", script);
if (scriptName != null && !scriptName.equals(script)) {
return skipAdjust? scriptName: adjustForUsageAndContext(CapitalizationContextUsage.SCRIPT, scriptName);
}
}
String scriptName = langData.get("Scripts", script);
return skipAdjust? scriptName: adjustForUsageAndContext(CapitalizationContextUsage.SCRIPT, scriptName);
}
@Override
public String scriptDisplayNameInContext(String script) {
return scriptDisplayNameInContext(script, false);
}
@Override
public String scriptDisplayName(int scriptCode) {
return scriptDisplayName(UScript.getShortName(scriptCode));
}
private String regionDisplayName(String region, boolean skipAdjust) {
if (nameLength == DisplayContext.LENGTH_SHORT) {
String regionName = regionData.get("Countries%short", region);
if (regionName != null && !regionName.equals(region)) {
return skipAdjust? regionName: adjustForUsageAndContext(CapitalizationContextUsage.TERRITORY, regionName);
}
}
String regionName = regionData.get("Countries", region);
return skipAdjust? regionName: adjustForUsageAndContext(CapitalizationContextUsage.TERRITORY, regionName);
}
@Override
public String regionDisplayName(String region) {
return regionDisplayName(region, false);
}
private String variantDisplayName(String variant, boolean skipAdjust) {
// don't have a resource for short variant names
String variantName = langData.get("Variants", variant);
return skipAdjust? variantName: adjustForUsageAndContext(CapitalizationContextUsage.VARIANT, variantName);
}
@Override
public String variantDisplayName(String variant) {
return variantDisplayName(variant, false);
}
private String keyDisplayName(String key, boolean skipAdjust) {
// don't have a resource for short key names
String keyName = langData.get("Keys", key);
return skipAdjust? keyName: adjustForUsageAndContext(CapitalizationContextUsage.KEY, keyName);
}
@Override
public String keyDisplayName(String key) {
return keyDisplayName(key, false);
}
private String keyValueDisplayName(String key, String value, boolean skipAdjust) {
String keyValueName = null;
if (key.equals("currency")) {
keyValueName = currencyDisplayInfo.getName(AsciiUtil.toUpperString(value));
if (keyValueName == null) {
keyValueName = value;
}
} else {
if (nameLength == DisplayContext.LENGTH_SHORT) {
String tmp = langData.get("Types%short", key, value);
if (tmp != null && !tmp.equals(value)) {
keyValueName = tmp;
}
}
if (keyValueName == null) {
keyValueName = langData.get("Types", key, value);
}
}
return skipAdjust? keyValueName: adjustForUsageAndContext(CapitalizationContextUsage.KEYVALUE, keyValueName);
}
@Override
public String keyValueDisplayName(String key, String value) {
return keyValueDisplayName(key, value, false);
}
@Override
public List getUiListCompareWholeItems(Set localeSet, Comparator comparator) {
DisplayContext capContext = getContext(Type.CAPITALIZATION);
List result = new ArrayList();
Map> baseToLocales = new HashMap>();
ULocale.Builder builder = new ULocale.Builder();
for (ULocale locOriginal : localeSet) {
builder.setLocale(locOriginal); // verify well-formed. We do this here so that we consistently throw exception
ULocale loc = ULocale.addLikelySubtags(locOriginal);
ULocale base = new ULocale(loc.getLanguage());
Set locales = baseToLocales.get(base);
if (locales == null) {
baseToLocales.put(base, locales = new HashSet());
}
locales.add(loc);
}
for (Entry> entry : baseToLocales.entrySet()) {
ULocale base = entry.getKey();
Set values = entry.getValue();
if (values.size() == 1) {
ULocale locale = values.iterator().next();
result.add(newRow(ULocale.minimizeSubtags(locale, ULocale.Minimize.FAVOR_SCRIPT), capContext));
} else {
Set scripts = new HashSet();
Set regions = new HashSet();
// need the follow two steps to make sure that unusual scripts or regions are displayed
ULocale maxBase = ULocale.addLikelySubtags(base);
scripts.add(maxBase.getScript());
regions.add(maxBase.getCountry());
for (ULocale locale : values) {
scripts.add(locale.getScript());
regions.add(locale.getCountry());
}
boolean hasScripts = scripts.size() > 1;
boolean hasRegions = regions.size() > 1;
for (ULocale locale : values) {
ULocale.Builder modified = builder.setLocale(locale);
if (!hasScripts) {
modified.setScript("");
}
if (!hasRegions) {
modified.setRegion("");
}
result.add(newRow(modified.build(), capContext));
}
}
}
Collections.sort(result, comparator);
return result;
}
private UiListItem newRow(ULocale modified, DisplayContext capContext) {
ULocale minimized = ULocale.minimizeSubtags(modified, ULocale.Minimize.FAVOR_SCRIPT);
String tempName = modified.getDisplayName(locale);
boolean titlecase = capContext == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU;
String nameInDisplayLocale =
titlecase ? toTitleWholeStringNoLowercase(locale, tempName) : tempName;
tempName = modified.getDisplayName(modified);
String nameInSelf = capContext ==
DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU ?
toTitleWholeStringNoLowercase(modified, tempName) : tempName;
return new UiListItem(minimized, modified, nameInDisplayLocale, nameInSelf);
}
public static class DataTable {
final boolean nullIfNotFound;
DataTable(boolean nullIfNotFound) {
this.nullIfNotFound = nullIfNotFound;
}
ULocale getLocale() {
return ULocale.ROOT;
}
String get(String tableName, String code) {
return get(tableName, null, code);
}
String get(String tableName, String subTableName, String code) {
return nullIfNotFound ? null : code;
}
}
static class ICUDataTable extends DataTable {
private final ICUResourceBundle bundle;
public ICUDataTable(String path, ULocale locale, boolean nullIfNotFound) {
super(nullIfNotFound);
this.bundle = (ICUResourceBundle) UResourceBundle.getBundleInstance(
path, locale.getBaseName());
}
@Override
public ULocale getLocale() {
return bundle.getULocale();
}
@Override
public String get(String tableName, String subTableName, String code) {
return ICUResourceTableAccess.getTableString(bundle, tableName, subTableName,
code, nullIfNotFound ? null : code);
}
}
static abstract class DataTables {
public abstract DataTable get(ULocale locale, boolean nullIfNotFound);
public static DataTables load(String className) {
try {
return (DataTables) Class.forName(className).newInstance();
} catch (Throwable t) {
return new DataTables() {
@Override
public DataTable get(ULocale locale, boolean nullIfNotFound) {
return new DataTable(nullIfNotFound);
}
};
}
}
}
static abstract class ICUDataTables extends DataTables {
private final String path;
protected ICUDataTables(String path) {
this.path = path;
}
@Override
public DataTable get(ULocale locale, boolean nullIfNotFound) {
return new ICUDataTable(path, locale, nullIfNotFound);
}
}
static class LangDataTables {
static final DataTables impl = DataTables.load("com.ibm.icu.impl.ICULangDataTables");
}
static class RegionDataTables {
static final DataTables impl = DataTables.load("com.ibm.icu.impl.ICURegionDataTables");
}
public static enum DataTableType {
LANG, REGION;
}
public static boolean haveData(DataTableType type) {
switch (type) {
case LANG: return LangDataTables.impl instanceof ICUDataTables;
case REGION: return RegionDataTables.impl instanceof ICUDataTables;
default:
throw new IllegalArgumentException("unknown type: " + type);
}
}
private StringBuilder appendWithSep(String s, StringBuilder b) {
if (b.length() == 0) {
b.append(s);
} else {
SimpleFormatterImpl.formatAndReplace(separatorFormat, b, null, b, s);
}
return b;
}
private static class Cache {
private ULocale locale;
private DialectHandling dialectHandling;
private DisplayContext capitalization;
private DisplayContext nameLength;
private DisplayContext substituteHandling;
private LocaleDisplayNames cache;
public LocaleDisplayNames get(ULocale locale, DialectHandling dialectHandling) {
if (!(dialectHandling == this.dialectHandling && DisplayContext.CAPITALIZATION_NONE == this.capitalization &&
DisplayContext.LENGTH_FULL == this.nameLength && DisplayContext.SUBSTITUTE == this.substituteHandling &&
locale.equals(this.locale))) {
this.locale = locale;
this.dialectHandling = dialectHandling;
this.capitalization = DisplayContext.CAPITALIZATION_NONE;
this.nameLength = DisplayContext.LENGTH_FULL;
this.substituteHandling = DisplayContext.SUBSTITUTE;
this.cache = new LocaleDisplayNamesImpl(locale, dialectHandling);
}
return cache;
}
public LocaleDisplayNames get(ULocale locale, DisplayContext... contexts) {
DialectHandling dialectHandlingIn = DialectHandling.STANDARD_NAMES;
DisplayContext capitalizationIn = DisplayContext.CAPITALIZATION_NONE;
DisplayContext nameLengthIn = DisplayContext.LENGTH_FULL;
DisplayContext substituteHandling = DisplayContext.SUBSTITUTE;
for (DisplayContext contextItem : contexts) {
switch (contextItem.type()) {
case DIALECT_HANDLING:
dialectHandlingIn = (contextItem.value()==DisplayContext.STANDARD_NAMES.value())?
DialectHandling.STANDARD_NAMES: DialectHandling.DIALECT_NAMES;
break;
case CAPITALIZATION:
capitalizationIn = contextItem;
break;
case DISPLAY_LENGTH:
nameLengthIn = contextItem;
break;
case SUBSTITUTE_HANDLING:
substituteHandling = contextItem;
break;
default:
break;
}
}
if (!(dialectHandlingIn == this.dialectHandling && capitalizationIn == this.capitalization &&
nameLengthIn == this.nameLength && substituteHandling == this.substituteHandling &&
locale.equals(this.locale))) {
this.locale = locale;
this.dialectHandling = dialectHandlingIn;
this.capitalization = capitalizationIn;
this.nameLength = nameLengthIn;
this.substituteHandling = substituteHandling;
this.cache = new LocaleDisplayNamesImpl(locale, contexts);
}
return cache;
}
}
}