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.List;
015    
016    
017    /**
018     * Factory to create Locales by Cold Fusion 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("chinese (china)", Locale.CHINA);
051                    setLocalAlias("chinese (china)", Locale.CHINA);
052                    setLocalAlias("chinese (hong kong)",new Locale("zh","HK"));
053            setLocalAlias("chinese (taiwan)",new Locale("zho","TWN"));
054            setLocalAlias("dutch (belgian)",new Locale("nl","BE"));
055            setLocalAlias("dutch (belgium)",new Locale("nl","BE"));
056            setLocalAlias("dutch (standard)",new Locale("nl","NL"));
057            setLocalAlias("english (australian)",new Locale("en","AU"));
058            setLocalAlias("english (australia)",new Locale("en","AU"));
059            setLocalAlias("english (canadian)",new Locale("en","CA"));
060            setLocalAlias("english (canadia)",new Locale("en","CA"));
061            setLocalAlias("english (new zealand)",new Locale("en","NZ"));
062            setLocalAlias("english (uk)",new Locale("en","GB"));
063            setLocalAlias("english (united kingdom)",new Locale("en","GB"));
064            setLocalAlias("english (us)",new Locale("en","US"));
065            setLocalAlias("french (belgium)",new Locale("fr","BE"));
066            setLocalAlias("french (belgian)",new Locale("fr","BE"));
067                    setLocalAlias("french (canadian)",new Locale("fr","CA"));
068                    setLocalAlias("french (canadia)",new Locale("fr","CA"));
069            setLocalAlias("french (standard)",new Locale("fr","FRA"));
070            setLocalAlias("french (swiss)",new Locale("fr","CH"));
071            setLocalAlias("german (austrian)",new Locale("de","AT"));
072            setLocalAlias("german (austria)",new Locale("de","AT"));
073            setLocalAlias("german (standard)",new Locale("de","DE"));
074            setLocalAlias("german (swiss)",new Locale("de","CH"));
075            setLocalAlias("italian (standard)",new Locale("it","IT"));
076            setLocalAlias("italian (swiss)",new Locale("it","CH"));
077            setLocalAlias("japanese",new Locale("ja","JP"));  
078            setLocalAlias("korean",Locale.KOREAN);
079            setLocalAlias("norwegian (bokmal)",new Locale("no","NO"));
080            setLocalAlias("norwegian (nynorsk)",new Locale("no","NO"));
081            setLocalAlias("portuguese (brazilian)",new Locale("pt","BR"));
082            setLocalAlias("portuguese (brazil)",new Locale("pt","BR"));
083                    setLocalAlias("portuguese (standard)",new Locale("pt"));
084            setLocalAlias("rhaeto-romance (swiss)",new Locale("rm","CH"));
085            locales.put("rhaeto-romance (swiss)",new Locale("rm","CH"));
086            setLocalAlias("spanish (modern)",new Locale("es","ES"));
087            setLocalAlias("spanish (standard)",new Locale("es","ES"));
088            setLocalAlias("swedish",new Locale("sv","SE"));
089            
090            }
091            
092            private LocaleFactory(){}
093            
094        private static void setLocalAlias(String name, Locale locale) {
095            if(!localeAlias.containsKey(name))localeAlias.put(name, locale);
096            }
097    
098            /**
099         * @param strLocale
100         * @param defaultValue 
101         * @return return locale match to String
102         */
103        public static Locale getLocale(String strLocale, Locale defaultValue) {
104            try {
105                return getLocale(strLocale);
106            } catch (ExpressionException e) {
107                return defaultValue;
108            }
109        }
110            
111            
112            /**
113             * @param strLocale
114             * @return return locale match to String
115             * @throws ExpressionException
116             */
117            public static Locale getLocale(String strLocale) throws ExpressionException {
118                    String strLocaleLC = strLocale.toLowerCase().trim();
119                    Locale l=(Locale) locales.get(strLocaleLC);
120                    if(l!=null) return l;
121                    
122                    l=(Locale) localeAlias.get(strLocaleLC);
123                    if(l!=null) return l;
124    
125                    Matcher matcher = localePattern2.matcher(strLocaleLC);
126                    if(matcher.find()) {
127                            int len=matcher.groupCount();
128                            if(len==2) {
129                                    String lang=matcher.group(1).trim();
130                                    String country=matcher.group(2).trim();
131                                    Locale locale=new Locale(lang,country);
132                                    
133                                    try {
134                                            locale.getISO3Language();
135                                            setLocalAlias(strLocaleLC, locale);
136                                            return locale;
137                                    }
138                                    catch(Exception e) {}
139                            }
140                    }
141                    
142                    matcher = localePattern3.matcher(strLocaleLC);
143                    if(matcher.find()) {
144                            int len=matcher.groupCount();
145                            if(len==3) {
146                                    String lang=matcher.group(1).trim();
147                                    String country=matcher.group(2).trim();
148                                    String variant=matcher.group(3).trim();
149                                    Locale locale=new Locale(lang,country,variant);
150                                    
151                                    try {
152                                            locale.getISO3Language();
153                                            setLocalAlias(strLocaleLC, locale);
154                                            return locale;
155                                    }
156                                    catch(Exception e) {}
157                            }
158                    }
159                            
160                    
161                    matcher=localePattern.matcher(strLocaleLC);
162                    if(matcher.find()) {
163                            int len=matcher.groupCount();
164    
165                            if(len==3) {
166                                    
167                                    String lang=matcher.group(1).trim();
168                                    String country=matcher.group(3);
169                                    if(country!=null)country=country.trim();
170                                     Object objLocale=null;
171                                     
172                                    if(country!=null) objLocale=locales.get(lang.toLowerCase()+" ("+(country.toLowerCase())+")");
173                                    else objLocale=locales.get(lang.toLowerCase());
174                                    if(objLocale!=null)return (Locale)objLocale;
175                                    
176                                    Locale locale;
177                                    if(country!=null)locale=new Locale(lang.toUpperCase(),country.toLowerCase());
178                                    else locale=new Locale(lang);
179                                    
180                                    try {
181                                            locale.getISO3Language();
182                                    }
183                                    catch(Exception e) {
184                                            if(strLocale.indexOf('-')!=-1) return getLocale(strLocale.replace('-', '_'));
185                                            throw new ExpressionException("unsupported Locale ["+strLocale+"]","supported Locales are:"+getSupportedLocalesAsString());
186                                    }
187                                    setLocalAlias(strLocaleLC, locale);
188                                    return locale;
189    
190                            }
191                    }
192                    
193    
194                    throw new ExpressionException("can't cast value ("+strLocale+") to a Locale","supported Locales are:"+getSupportedLocalesAsString());
195            }
196            
197    
198            private static String getSupportedLocalesAsString() {
199                    //StringBuffer sb=new StringBuffer();
200                // TODO chnge from ArryObject to string
201                    String[] arr = (String[])locales.keySet().toArray(new String[locales.size()]);
202                    Arrays.sort(arr);
203                    return List.arrayToList(arr,",");
204                    
205            }
206    
207            /**
208             * @param locale
209             * @return cast a Locale to a String 
210             */
211            public static String toString(Locale locale) {
212                    String lang=locale.getLanguage();
213                    String country=locale.getCountry();
214                    
215                    synchronized(localeAlias){
216                            Iterator<Entry<String, Locale>> it = localeAlias.entrySet().iterator();
217                            Map.Entry<String, Locale> entry;
218                            while(it.hasNext()) {
219                                    entry= it.next();
220                                    //Object qkey=it.next();
221                                    Locale curr=(Locale) entry.getValue();
222                                    if(lang.equals(curr.getLanguage()) && country.equals(curr.getCountry())) {
223                                            return entry.getKey().toString();
224                                    }
225                            }
226                    }
227                    return locale.getDisplayName(Locale.ENGLISH);
228            }
229            
230        /**
231         * @return Returns the locales.
232         */
233        public static Map getLocales() {
234            return locales;
235        }
236        public static String getLocaleList() {
237            return list;
238        }
239    }