001    
002    package railo.runtime.i18n;
003    
004    import java.util.Arrays;
005    import java.util.Iterator;
006    import java.util.LinkedHashMap;
007    import java.util.Locale;
008    import java.util.Map;
009    import java.util.Map.Entry;
010    import java.util.regex.Matcher;
011    import java.util.regex.Pattern;
012    
013    import railo.runtime.exp.ExpressionException;
014    import railo.runtime.type.util.ListUtil;
015    
016    
017    /**
018     * Factory to create Locales by CFML rules
019     */
020    public final class LocaleFactory {
021            //private static Pattern localePattern = Pattern.compile("^\\s*([^\\s\\(]+)\\s*(\\(\\s*([^\\s\\)]+)\\s*\\))?\\s*$");
022            private static Pattern localePattern = Pattern.compile("^\\s*([^\\(]+)\\s*(\\(\\s*([^\\)]+)\\s*\\))?\\s*$");
023            private static Pattern localePattern2 = Pattern.compile("^([a-z]{2})_([a-z]{2,3})$");
024            private static Pattern localePattern3 = Pattern.compile("^([a-z]{2})_([a-z]{2,3})_([a-z]{2,})$");
025            
026            private static Map<String,Locale> locales=new LinkedHashMap<String,Locale>();
027            private static Map<String,Locale> localeAlias=new LinkedHashMap<String,Locale>();
028            
029            private static String list;
030            static {
031                    Locale[] ls = Locale.getAvailableLocales();
032                    
033                    
034                    String key;
035                    StringBuffer sb=new StringBuffer();
036                    for(int i=0;i<ls.length;i++) {
037                            key=ls[i].getDisplayName(Locale.US).toLowerCase();
038                            locales.put(key, ls[i]);
039                            if(key.indexOf(',')!=-1){
040                                    key=ls[i].toString();
041                                    //print.ln(key);
042                                    
043                            }
044                            if(i>0)sb.append(",");
045                            sb.append(key);
046                    }
047                    list=sb.toString();
048                    
049                    
050                    setLocalAlias("albanian (albania)", LocaleConstant.ALBANIAN_ALBANIA);
051    
052                    setLocalAlias("arabic (algeria)", LocaleConstant.ARABIC_ALGERIA);
053                    setLocalAlias("arabic (bahrain)", LocaleConstant.ARABIC_BAHRAIN);
054                    setLocalAlias("arabic (egypt)", LocaleConstant.ARABIC_EGYPT);
055                    setLocalAlias("arabic (iraq)", LocaleConstant.ARABIC_IRAQ);
056                    setLocalAlias("arabic (jordan)", LocaleConstant.ARABIC_JORDAN);
057                    setLocalAlias("arabic (kuwait)", LocaleConstant.ARABIC_KUWAIT);
058                    setLocalAlias("arabic (lebanon)", LocaleConstant.ARABIC_LEBANON);
059                    setLocalAlias("arabic (libya)", LocaleConstant.ARABIC_LIBYA);
060                    setLocalAlias("arabic (morocco)", LocaleConstant.ARABIC_MAROCCO);
061                    setLocalAlias("arabic (oman)", LocaleConstant.ARABIC_OMAN);
062                    setLocalAlias("arabic (qatar)", LocaleConstant.ARABIC_QATAR);
063                    setLocalAlias("arabic (saudi arabia)", LocaleConstant.ARABIC_SAUDI_ARABIA);
064                    setLocalAlias("arabic (sudan)", LocaleConstant.ARABIC_SUDAN);
065                    setLocalAlias("arabic (syria)", LocaleConstant.ARABIC_SYRIA);
066                    setLocalAlias("arabic (tunisia)", LocaleConstant.ARABIC_TUNISIA);
067                    setLocalAlias("arabic (united arab emirates)", LocaleConstant.ARABIC_UNITED_ARAB_EMIRATES);
068                    setLocalAlias("arabic (yemen)", LocaleConstant.ARABIC_YEMEN);
069                            
070                    setLocalAlias("chinese (china)", Locale.CHINA);
071                    setLocalAlias("chinese (hong kong)",LocaleConstant.CHINESE_HONG_KONG);
072                    setLocalAlias("chinese (singapore)",LocaleConstant.CHINESE_SINGAPORE);
073                setLocalAlias("chinese (taiwan)",LocaleConstant.CHINESE_TAIWAN);
074                setLocalAlias("dutch (belgian)",LocaleConstant.DUTCH_BELGIUM);
075                setLocalAlias("dutch (belgium)",LocaleConstant.DUTCH_BELGIUM);
076                setLocalAlias("dutch (standard)",LocaleConstant.DUTCH_NETHERLANDS);
077                setLocalAlias("english (australian)",LocaleConstant.ENGLISH_AUSTRALIA);
078                setLocalAlias("english (australia)",LocaleConstant.ENGLISH_AUSTRALIA);
079                setLocalAlias("english (canadian)",LocaleConstant.ENGLISH_CANADA);
080                setLocalAlias("english (canada)",LocaleConstant.ENGLISH_CANADA);
081                setLocalAlias("english (new zealand)",LocaleConstant.ENGLISH_NEW_ZEALAND);
082                setLocalAlias("english (uk)",LocaleConstant.ENGLISH_UNITED_KINDOM);
083                setLocalAlias("english (united kingdom)",LocaleConstant.ENGLISH_UNITED_KINDOM);
084                setLocalAlias("english (gb)",LocaleConstant.ENGLISH_UNITED_KINDOM);
085                setLocalAlias("english (great britan)",LocaleConstant.ENGLISH_UNITED_KINDOM);
086                setLocalAlias("english (us)",LocaleConstant.ENGLISH_UNITED_STATES);
087                setLocalAlias("english (united states)",LocaleConstant.ENGLISH_UNITED_STATES);
088                setLocalAlias("english (united states of america)",LocaleConstant.ENGLISH_UNITED_STATES);
089                setLocalAlias("english (usa)",LocaleConstant.ENGLISH_UNITED_STATES);
090                setLocalAlias("french (belgium)",new Locale("fr","BE"));
091                setLocalAlias("french (belgian)",new Locale("fr","BE"));
092                    setLocalAlias("french (canadian)",new Locale("fr","CA"));
093                    setLocalAlias("french (canadia)",new Locale("fr","CA"));
094                setLocalAlias("french (standard)",new Locale("fr","FRA"));
095                setLocalAlias("french (swiss)",new Locale("fr","CH"));
096                setLocalAlias("german (austrian)",new Locale("de","AT"));
097                setLocalAlias("german (austria)",new Locale("de","AT"));
098                setLocalAlias("german (standard)",new Locale("de","DE"));
099                setLocalAlias("german (swiss)",new Locale("de","CH"));
100                setLocalAlias("italian (standard)",new Locale("it","IT"));
101                setLocalAlias("italian (swiss)",new Locale("it","CH"));
102                setLocalAlias("japanese",new Locale("ja","JP"));  
103                setLocalAlias("korean",Locale.KOREAN);
104                setLocalAlias("norwegian (bokmal)",new Locale("no","NO"));
105                setLocalAlias("norwegian (nynorsk)",new Locale("no","NO"));
106                setLocalAlias("portuguese (brazilian)",LocaleConstant.PORTUGUESE_BRASIL);
107                setLocalAlias("portuguese (brazil)",LocaleConstant.PORTUGUESE_BRASIL);
108                    setLocalAlias("portuguese (standard)",LocaleConstant.PORTUGUESE_PORTUGAL);
109                setLocalAlias("rhaeto-romance (swiss)",new Locale("rm","CH"));
110                locales.put("rhaeto-romance (swiss)",new Locale("rm","CH"));
111                setLocalAlias("spanish (modern)",new Locale("es","ES"));
112                setLocalAlias("spanish (standard)",new Locale("es","ES"));
113                setLocalAlias("swedish",new Locale("sv","SE"));
114            }
115            
116            private LocaleFactory(){}
117            
118        private static void setLocalAlias(String name, Locale locale) {
119            if(!localeAlias.containsKey(name))localeAlias.put(name, locale);
120            }
121    
122            /**
123         * @param strLocale
124         * @param defaultValue 
125         * @return return locale match to String
126         */
127        public static Locale getLocale(String strLocale, Locale defaultValue) {
128            try {
129                return getLocale(strLocale);
130            } catch (ExpressionException e) {
131                return defaultValue;
132            }
133        }
134            
135            
136            /**
137             * @param strLocale
138             * @return return locale match to String
139             * @throws ExpressionException
140             */
141            public static Locale getLocale(String strLocale) throws ExpressionException {
142                    String strLocaleLC = strLocale.toLowerCase().trim();
143                    Locale l=locales.get(strLocaleLC);
144                    if(l!=null) return l;
145                    
146                    l=localeAlias.get(strLocaleLC);
147                    if(l!=null) return l;
148    
149                    Matcher matcher = localePattern2.matcher(strLocaleLC);
150                    if(matcher.find()) {
151                            int len=matcher.groupCount();
152                            if(len==2) {
153                                    String lang=matcher.group(1).trim();
154                                    String country=matcher.group(2).trim();
155                                    Locale locale=new Locale(lang,country);
156                                    
157                                    try {
158                                            locale.getISO3Language();
159                                            setLocalAlias(strLocaleLC, locale);
160                                            return locale;
161                                    }
162                                    catch(Exception e) {}
163                            }
164                    }
165                    
166                    matcher = localePattern3.matcher(strLocaleLC);
167                    if(matcher.find()) {
168                            int len=matcher.groupCount();
169                            if(len==3) {
170                                    String lang=matcher.group(1).trim();
171                                    String country=matcher.group(2).trim();
172                                    String variant=matcher.group(3).trim();
173                                    Locale locale=new Locale(lang,country,variant);
174                                    
175                                    try {
176                                            locale.getISO3Language();
177                                            setLocalAlias(strLocaleLC, locale);
178                                            return locale;
179                                    }
180                                    catch(Exception e) {}
181                            }
182                    }
183                            
184                    
185                    matcher=localePattern.matcher(strLocaleLC);
186                    if(matcher.find()) {
187                            int len=matcher.groupCount();
188    
189                            if(len==3) {
190                                    
191                                    String lang=matcher.group(1).trim();
192                                    String country=matcher.group(3);
193                                    if(country!=null)country=country.trim();
194                                     Object objLocale=null;
195                                     
196                                    if(country!=null) objLocale=locales.get(lang.toLowerCase()+" ("+(country.toLowerCase())+")");
197                                    else objLocale=locales.get(lang.toLowerCase());
198                                    if(objLocale!=null)return (Locale)objLocale;
199                                    
200                                    Locale locale;
201                                    if(country!=null)locale=new Locale(lang.toUpperCase(),country.toLowerCase());
202                                    else locale=new Locale(lang);
203                                    
204                                    try {
205                                            locale.getISO3Language();
206                                    }
207                                    catch(Exception e) {
208                                            if(strLocale.indexOf('-')!=-1) return getLocale(strLocale.replace('-', '_'));
209                                            throw new ExpressionException("unsupported Locale ["+strLocale+"]","supported Locales are:"+getSupportedLocalesAsString());
210                                    }
211                                    setLocalAlias(strLocaleLC, locale);
212                                    return locale;
213    
214                            }
215                    }
216                    
217    
218                    throw new ExpressionException("can't cast value ("+strLocale+") to a Locale","supported Locales are:"+getSupportedLocalesAsString());
219            }
220            
221    
222            private static String getSupportedLocalesAsString() {
223                    //StringBuffer sb=new StringBuffer();
224                // TODO chnge from ArryObject to string
225                    String[] arr = locales.keySet().toArray(new String[locales.size()]);
226                    Arrays.sort(arr);
227                    return ListUtil.arrayToList(arr,",");
228                    
229            }
230    
231            /**
232             * @param locale
233             * @return cast a Locale to a String 
234             */
235            public static String toString(Locale locale) {
236                    String lang=locale.getLanguage();
237                    String country=locale.getCountry();
238                    
239                    synchronized(localeAlias){
240                            Iterator<Entry<String, Locale>> it = localeAlias.entrySet().iterator();
241                            Map.Entry<String, Locale> entry;
242                            while(it.hasNext()) {
243                                    entry= it.next();
244                                    //Object qkey=it.next();
245                                    Locale curr=entry.getValue();
246                                    if(lang.equals(curr.getLanguage()) && country.equals(curr.getCountry())) {
247                                            return entry.getKey().toString();
248                                    }
249                            }
250                    }
251                    return locale.getDisplayName(Locale.ENGLISH);
252            }
253            
254        /**
255         * @return Returns the locales.
256         */
257        public static Map getLocales() {
258            return locales;
259        }
260        public static String getLocaleList() {
261            return list;
262        }
263    }