ICU-7434 switch NumberingSystem from SimpleCache to SoftCache

X-SVN-Rev: 38743
This commit is contained in:
Markus Scherer 2016-05-16 16:36:31 +00:00
parent 677b1b1461
commit 3d7536e60b

View file

@ -11,10 +11,10 @@ import java.util.ArrayList;
import java.util.Locale;
import java.util.MissingResourceException;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.CacheBase;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SoftCache;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
@ -33,6 +33,7 @@ import com.ibm.icu.util.UResourceBundleIterator;
* @stable ICU 4.2
*/
public class NumberingSystem {
private static final String[] OTHER_NS_KEYWORDS = { "native", "traditional", "finance" };
/**
* Default constructor. Returns a numbering system that uses the Western decimal
@ -111,13 +112,8 @@ public class NumberingSystem {
* @stable ICU 4.2
*/
public static NumberingSystem getInstance(ULocale locale) {
final String[] OTHER_NS_KEYWORDS = { "native", "traditional", "finance" };
NumberingSystem ns;
Boolean nsResolved = true;
// Check for @numbers
boolean nsResolved = true;
String numbersKeyword = locale.getKeywordValue("numbers");
if (numbersKeyword != null ) {
for ( String keyword : OTHER_NS_KEYWORDS ) {
@ -132,54 +128,72 @@ public class NumberingSystem {
}
if (nsResolved) {
ns = getInstanceByName(numbersKeyword);
if ( ns != null ) {
NumberingSystem ns = getInstanceByName(numbersKeyword);
if (ns != null) {
return ns;
} else { // if @numbers keyword points to a bogus numbering system name, we return the default for the locale
numbersKeyword = "default";
nsResolved = false;
}
// If the @numbers keyword points to a bogus numbering system name,
// we return the default for the locale.
numbersKeyword = "default";
}
// Attempt to get the numbering system from the cache
String baseName = locale.getBaseName();
ns = cachedLocaleData.get(baseName+"@numbers="+numbersKeyword);
if (ns != null ) {
return ns;
}
// Cache miss, create new instance
// TODO: Caching by locale+numbersKeyword could yield a large cache.
// Try to load for each locale the mappings from OTHER_NS_KEYWORDS and default
// to real numbering system names; can we get those from supplemental data?
// Then look up those mappings for the locale and resolve the keyword.
String key = baseName+"@numbers="+numbersKeyword;
LocaleLookupData localeLookupData = new LocaleLookupData(locale, numbersKeyword);
return cachedLocaleData.getInstance(key, localeLookupData);
}
String originalNumbersKeyword = numbersKeyword;
private static class LocaleLookupData {
public final ULocale locale;
public final String numbersKeyword;
LocaleLookupData(ULocale locale, String numbersKeyword) {
this.locale = locale;
this.numbersKeyword = numbersKeyword;
}
}
static NumberingSystem lookupInstanceByLocale(LocaleLookupData localeLookupData) {
ULocale locale = localeLookupData.locale;
ICUResourceBundle rb;
try {
rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
rb = rb.getWithFallback("NumberElements");
} catch (MissingResourceException ex) {
return new NumberingSystem();
}
String numbersKeyword = localeLookupData.numbersKeyword;
String resolvedNumberingSystem = null;
while (!nsResolved) {
for (;;) {
try {
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,locale);
rb = rb.getWithFallback("NumberElements");
resolvedNumberingSystem = rb.getStringWithFallback(numbersKeyword);
nsResolved = true;
break;
} catch (MissingResourceException ex) { // Fall back behavior as defined in TR35
if (numbersKeyword.equals("native") || numbersKeyword.equals("finance")) {
numbersKeyword = "default";
} else if (numbersKeyword.equals("traditional")) {
numbersKeyword = "native";
} else {
nsResolved = true;
}
}
if (numbersKeyword.equals("native") || numbersKeyword.equals("finance")) {
numbersKeyword = "default";
} else if (numbersKeyword.equals("traditional")) {
numbersKeyword = "native";
} else {
break;
}
}
}
NumberingSystem ns = null;
if (resolvedNumberingSystem != null) {
ns = getInstanceByName(resolvedNumberingSystem);
}
if ( ns == null ) {
if (ns == null) {
ns = new NumberingSystem();
}
cachedLocaleData.put(baseName+"@numbers="+originalNumbersKeyword, ns);
return ns;
}
/**
@ -202,16 +216,14 @@ public class NumberingSystem {
* @stable ICU 4.2
*/
public static NumberingSystem getInstanceByName(String name) {
// Get the numbering system from the cache.
return cachedStringData.getInstance(name, null /* unused */);
}
private static NumberingSystem lookupInstanceByName(String name) {
int radix;
boolean isAlgorithmic;
String description;
// Get the numbering system from the cache
NumberingSystem ns = cachedStringData.get(name);
if (ns != null ) {
return ns;
}
try {
UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
@ -229,9 +241,7 @@ public class NumberingSystem {
return null;
}
ns = getInstance(name,radix,isAlgorithmic,description);
cachedStringData.put(name, ns);
return ns;
return getInstance(name, radix, isAlgorithmic, description);
}
/**
@ -330,11 +340,22 @@ public class NumberingSystem {
/**
* Cache to hold the NumberingSystems by Locale.
*/
private static ICUCache<String, NumberingSystem> cachedLocaleData = new SimpleCache<String, NumberingSystem>();
private static CacheBase<String, NumberingSystem, LocaleLookupData> cachedLocaleData =
new SoftCache<String, NumberingSystem, LocaleLookupData>() {
@Override
protected NumberingSystem createInstance(String key, LocaleLookupData localeLookupData) {
return lookupInstanceByLocale(localeLookupData);
}
};
/**
* Cache to hold the NumberingSystems by name.
*/
private static ICUCache<String, NumberingSystem> cachedStringData = new SimpleCache<String, NumberingSystem>();
private static CacheBase<String, NumberingSystem, Void> cachedStringData =
new SoftCache<String, NumberingSystem, Void>() {
@Override
protected NumberingSystem createInstance(String key, Void unused) {
return lookupInstanceByName(key);
}
};
}