. For more information on the Apache
Software Foundation, please see .
*/
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
/**
* Map using Locale objects as keys.
*
* This class is based on code from Apache Cocoon.
*
* This map should be filled once using calls to {@link #put}, before any calls
* are made to {@link #get}.
*
*/
public class LocaleMap {
/** Contains the original values the have been put in the map. */
protected ConcurrentHashMap map = new ConcurrentHashMap();
/** Contains 'resolved' locales for quick lookup. */
protected ConcurrentHashMap searchMap = new ConcurrentHashMap();
private static final String NO_RESULT = "(no result: you should never see this)";
/**
* Gets an object based on the given locale. An automatic fallback mechanism is used:
* if nothing is found for language-COUNTRY-variant, then language-COUNTRY is searched,
* the language, and finally "" (empty string). If nothing is found null is returned.
*/
public Object get(Locale locale) {
if (map.size() == 0)
return null;
String full = getFullKey(locale);
if (!searchMap.containsKey(full)) {
if (map.containsKey(full)) {
Object object = map.get(full);
searchMap.put(full, object);
return object;
}
String altKey = locale.getLanguage() + '-' + locale.getCountry();
Object object = map.get(altKey);
if (object != null) {
searchMap.put(full, object);
return object;
}
altKey = locale.getLanguage();
object = map.get(altKey);
if (object != null) {
searchMap.put(full, object);
return object;
}
object = map.get("");
if (object != null) {
searchMap.put(full, object);
return object;
}
searchMap.put(full, NO_RESULT);
}
Object result = searchMap.get(full);
return result == NO_RESULT ? null : result;
}
public Object getExact(Locale locale) {
return map.get(getString(locale));
}
public void clear() {
map.clear();
searchMap.clear();
}
public void remove(Locale locale) {
put(locale, null);
}
public Locale[] getLocales() {
String[] localeNames = map.keySet().toArray(new String[0]);
Locale[] locales = new Locale[localeNames.length];
for (int i = 0; i < locales.length; i++)
locales[i] = parseLocale(localeNames[i]);
return locales;
}
public Set entrySet() {
return map.entrySet();
}
private String getFullKey(Locale locale) {
return locale.getLanguage() + '-' + locale.getCountry() + '-' + locale.getVariant();
}
public void put(Locale locale, Object object) {
if (object == null)
map.remove(getString(locale));
else
map.put(getString(locale), object);
searchMap.clear();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean equals(Object obj) {
if (!(obj instanceof LocaleMap))
return false;
LocaleMap other = (LocaleMap)obj;
// map can do equals
return map.equals(other.map);
}
public static Locale parseLocale(String localeString) {
StringTokenizer localeParser = new StringTokenizer(localeString, "-_");
String lang = null, country = null, variant = null;
if (localeParser.hasMoreTokens())
lang = localeParser.nextToken();
if (localeParser.hasMoreTokens())
country = localeParser.nextToken();
if (localeParser.hasMoreTokens())
variant = localeParser.nextToken();
if (lang != null && country != null && variant != null)
return new Locale(lang, country, variant);
else if (lang != null && country != null)
return new Locale(lang, country);
else if (lang != null)
return new Locale(lang);
else
return new Locale("");
}
public static String getString(Locale locale) {
boolean hasLanguage = !locale.getLanguage().equals("");
boolean hasCountry = !locale.getCountry().equals("");
boolean hasVariant = !locale.getVariant().equals("");
if (hasLanguage && hasCountry && hasVariant)
return locale.getLanguage() + '-' + locale.getCountry() + '-' + locale.getVariant();
else if (hasLanguage && hasCountry)
return locale.getLanguage() + '-' + locale.getCountry();
else if (hasLanguage)
return locale.getLanguage();
else
return "";
}
}