package railo.runtime.i18n;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import railo.runtime.exp.ExpressionException;
import railo.runtime.type.util.ListUtil;
/**
* Factory to create Locales by CFML rules
*/
public final class LocaleFactory {
//private static Pattern localePattern = Pattern.compile("^\\s*([^\\s\\(]+)\\s*(\\(\\s*([^\\s\\)]+)\\s*\\))?\\s*$");
private static Pattern localePattern = Pattern.compile("^\\s*([^\\(]+)\\s*(\\(\\s*([^\\)]+)\\s*\\))?\\s*$");
private static Pattern localePattern2 = Pattern.compile("^([a-z]{2})_([a-z]{2,3})$");
private static Pattern localePattern3 = Pattern.compile("^([a-z]{2})_([a-z]{2,3})_([a-z]{2,})$");
private static Map<String,Locale> locales=new LinkedHashMap<String,Locale>();
private static Map<String,Locale> localeAlias=new LinkedHashMap<String,Locale>();
private static String list;
static {
Locale[] ls = Locale.getAvailableLocales();
String key;
StringBuffer sb=new StringBuffer();
for(int i=0;i<ls.length;i++) {
key=ls[i].getDisplayName(Locale.US).toLowerCase();
locales.put(key, ls[i]);
if(key.indexOf(',')!=-1){
key=ls[i].toString();
//print.ln(key);
}
if(i>0)sb.append(",");
sb.append(key);
}
list=sb.toString();
setLocalAlias("albanian (albania)", LocaleConstant.ALBANIAN_ALBANIA);
setLocalAlias("arabic (algeria)", LocaleConstant.ARABIC_ALGERIA);
setLocalAlias("arabic (bahrain)", LocaleConstant.ARABIC_BAHRAIN);
setLocalAlias("arabic (egypt)", LocaleConstant.ARABIC_EGYPT);
setLocalAlias("arabic (iraq)", LocaleConstant.ARABIC_IRAQ);
setLocalAlias("arabic (jordan)", LocaleConstant.ARABIC_JORDAN);
setLocalAlias("arabic (kuwait)", LocaleConstant.ARABIC_KUWAIT);
setLocalAlias("arabic (lebanon)", LocaleConstant.ARABIC_LEBANON);
setLocalAlias("arabic (libya)", LocaleConstant.ARABIC_LIBYA);
setLocalAlias("arabic (morocco)", LocaleConstant.ARABIC_MAROCCO);
setLocalAlias("arabic (oman)", LocaleConstant.ARABIC_OMAN);
setLocalAlias("arabic (qatar)", LocaleConstant.ARABIC_QATAR);
setLocalAlias("arabic (saudi arabia)", LocaleConstant.ARABIC_SAUDI_ARABIA);
setLocalAlias("arabic (sudan)", LocaleConstant.ARABIC_SUDAN);
setLocalAlias("arabic (syria)", LocaleConstant.ARABIC_SYRIA);
setLocalAlias("arabic (tunisia)", LocaleConstant.ARABIC_TUNISIA);
setLocalAlias("arabic (united arab emirates)", LocaleConstant.ARABIC_UNITED_ARAB_EMIRATES);
setLocalAlias("arabic (yemen)", LocaleConstant.ARABIC_YEMEN);
setLocalAlias("chinese (china)", Locale.CHINA);
setLocalAlias("chinese (hong kong)",LocaleConstant.CHINESE_HONG_KONG);
setLocalAlias("chinese (singapore)",LocaleConstant.CHINESE_SINGAPORE);
setLocalAlias("chinese (taiwan)",LocaleConstant.CHINESE_TAIWAN);
setLocalAlias("dutch (belgian)",LocaleConstant.DUTCH_BELGIUM);
setLocalAlias("dutch (belgium)",LocaleConstant.DUTCH_BELGIUM);
setLocalAlias("dutch (standard)",LocaleConstant.DUTCH_NETHERLANDS);
setLocalAlias("english (australian)",LocaleConstant.ENGLISH_AUSTRALIA);
setLocalAlias("english (australia)",LocaleConstant.ENGLISH_AUSTRALIA);
setLocalAlias("english (canadian)",LocaleConstant.ENGLISH_CANADA);
setLocalAlias("english (canada)",LocaleConstant.ENGLISH_CANADA);
setLocalAlias("english (new zealand)",LocaleConstant.ENGLISH_NEW_ZEALAND);
setLocalAlias("english (uk)",LocaleConstant.ENGLISH_UNITED_KINDOM);
setLocalAlias("english (united kingdom)",LocaleConstant.ENGLISH_UNITED_KINDOM);
setLocalAlias("english (gb)",LocaleConstant.ENGLISH_UNITED_KINDOM);
setLocalAlias("english (great britan)",LocaleConstant.ENGLISH_UNITED_KINDOM);
setLocalAlias("english (us)",LocaleConstant.ENGLISH_UNITED_STATES);
setLocalAlias("english (united states)",LocaleConstant.ENGLISH_UNITED_STATES);
setLocalAlias("english (united states of america)",LocaleConstant.ENGLISH_UNITED_STATES);
setLocalAlias("english (usa)",LocaleConstant.ENGLISH_UNITED_STATES);
setLocalAlias("french (belgium)",new Locale("fr","BE"));
setLocalAlias("french (belgian)",new Locale("fr","BE"));
setLocalAlias("french (canadian)",new Locale("fr","CA"));
setLocalAlias("french (canadia)",new Locale("fr","CA"));
setLocalAlias("french (standard)",new Locale("fr","FRA"));
setLocalAlias("french (swiss)",new Locale("fr","CH"));
setLocalAlias("german (austrian)",new Locale("de","AT"));
setLocalAlias("german (austria)",new Locale("de","AT"));
setLocalAlias("german (standard)",new Locale("de","DE"));
setLocalAlias("german (swiss)",new Locale("de","CH"));
setLocalAlias("italian (standard)",new Locale("it","IT"));
setLocalAlias("italian (swiss)",new Locale("it","CH"));
setLocalAlias("japanese",new Locale("ja","JP"));
setLocalAlias("korean",Locale.KOREAN);
setLocalAlias("norwegian (bokmal)",new Locale("no","NO"));
setLocalAlias("norwegian (nynorsk)",new Locale("no","NO"));
setLocalAlias("portuguese (brazilian)",LocaleConstant.PORTUGUESE_BRASIL);
setLocalAlias("portuguese (brazil)",LocaleConstant.PORTUGUESE_BRASIL);
setLocalAlias("portuguese (standard)",LocaleConstant.PORTUGUESE_PORTUGAL);
setLocalAlias("rhaeto-romance (swiss)",new Locale("rm","CH"));
locales.put("rhaeto-romance (swiss)",new Locale("rm","CH"));
setLocalAlias("spanish (modern)",new Locale("es","ES"));
setLocalAlias("spanish (standard)",new Locale("es","ES"));
setLocalAlias("swedish",new Locale("sv","SE"));
}
private LocaleFactory(){}
private static void setLocalAlias(String name, Locale locale) {
if(!localeAlias.containsKey(name))localeAlias.put(name, locale);
}
/**
* @param strLocale
* @param defaultValue
* @return return locale match to String
*/
public static Locale getLocale(String strLocale, Locale defaultValue) {
try {
return getLocale(strLocale);
} catch (ExpressionException e) {
return defaultValue;
}
}
/**
* @param strLocale
* @return return locale match to String
* @throws ExpressionException
*/
public static Locale getLocale(String strLocale) throws ExpressionException {
String strLocaleLC = strLocale.toLowerCase().trim();
Locale l=locales.get(strLocaleLC);
if(l!=null) return l;
l=localeAlias.get(strLocaleLC);
if(l!=null) return l;
Matcher matcher = localePattern2.matcher(strLocaleLC);
if(matcher.find()) {
int len=matcher.groupCount();
if(len==2) {
String lang=matcher.group(1).trim();
String country=matcher.group(2).trim();
Locale locale=new Locale(lang,country);
try {
locale.getISO3Language();
setLocalAlias(strLocaleLC, locale);
return locale;
}
catch(Exception e) {}
}
}
matcher = localePattern3.matcher(strLocaleLC);
if(matcher.find()) {
int len=matcher.groupCount();
if(len==3) {
String lang=matcher.group(1).trim();
String country=matcher.group(2).trim();
String variant=matcher.group(3).trim();
Locale locale=new Locale(lang,country,variant);
try {
locale.getISO3Language();
setLocalAlias(strLocaleLC, locale);
return locale;
}
catch(Exception e) {}
}
}
matcher=localePattern.matcher(strLocaleLC);
if(matcher.find()) {
int len=matcher.groupCount();
if(len==3) {
String lang=matcher.group(1).trim();
String country=matcher.group(3);
if(country!=null)country=country.trim();
Object objLocale=null;
if(country!=null) objLocale=locales.get(lang.toLowerCase()+" ("+(country.toLowerCase())+")");
else objLocale=locales.get(lang.toLowerCase());
if(objLocale!=null)return (Locale)objLocale;
Locale locale;
if(country!=null)locale=new Locale(lang.toUpperCase(),country.toLowerCase());
else locale=new Locale(lang);
try {
locale.getISO3Language();
}
catch(Exception e) {
if(strLocale.indexOf('-')!=-1) return getLocale(strLocale.replace('-', '_'));
throw new ExpressionException("unsupported Locale ["+strLocale+"]","supported Locales are:"+getSupportedLocalesAsString());
}
setLocalAlias(strLocaleLC, locale);
return locale;
}
}
throw new ExpressionException("can't cast value ("+strLocale+") to a Locale","supported Locales are:"+getSupportedLocalesAsString());
}
private static String getSupportedLocalesAsString() {
//StringBuffer sb=new StringBuffer();
// TODO chnge from ArryObject to string
String[] arr = locales.keySet().toArray(new String[locales.size()]);
Arrays.sort(arr);
return ListUtil.arrayToList(arr,",");
}
/**
* @param locale
* @return cast a Locale to a String
*/
public static String toString(Locale locale) {
String lang=locale.getLanguage();
String country=locale.getCountry();
synchronized(localeAlias){
Iterator<Entry<String, Locale>> it = localeAlias.entrySet().iterator();
Map.Entry<String, Locale> entry;
while(it.hasNext()) {
entry= it.next();
//Object qkey=it.next();
Locale curr=entry.getValue();
if(lang.equals(curr.getLanguage()) && country.equals(curr.getCountry())) {
return entry.getKey().toString();
}
}
}
return locale.getDisplayName(Locale.ENGLISH);
}
/**
* @return Returns the locales.
*/
public static Map getLocales() {
return locales;
}
public static String getLocaleList() {
return list;
}
}