001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    
020    import java.util.HashMap;
021    import java.util.Locale;
022    import java.util.Map;
023    import java.util.TreeMap;
024    
025    /**
026     * @author Brian Wing Shun Chan
027     */
028    public class LocaleUtil {
029    
030            public static Locale fromLanguageId(String languageId) {
031                    return _instance._fromLanguageId(languageId);
032            }
033    
034            public static Locale[] fromLanguageIds(String[] languageIds) {
035                    return _instance._fromLanguageIds(languageIds);
036            }
037    
038            public static Locale getDefault() {
039                    return _instance._getDefault();
040            }
041    
042            public static LocaleUtil getInstance() {
043                    return _instance;
044            }
045    
046            public static Map<String, String> getISOLanguages(Locale locale) {
047                    return _instance._getISOLanguages(locale);
048            }
049    
050            public static void setDefault(
051                    String userLanguage, String userCountry, String userVariant) {
052    
053                    _instance._setDefault(userLanguage, userCountry, userVariant);
054            }
055    
056            public static String toLanguageId(Locale locale) {
057                    return _instance._toLanguageId(locale);
058            }
059    
060            public static String[] toLanguageIds(Locale[] locales) {
061                    return _instance._toLanguageIds(locales);
062            }
063    
064            public static String toW3cLanguageId(Locale locale) {
065                    return _instance._toW3cLanguageId(locale);
066            }
067    
068            public static String toW3cLanguageId(String languageId) {
069                    return _instance._toW3cLanguageId(languageId);
070            }
071    
072            public static String[] toW3cLanguageIds(Locale[] locales) {
073                    return _instance._toW3cLanguageIds(locales);
074            }
075    
076            public static String[] toW3cLanguageIds(String[] languageIds) {
077                    return _instance._toW3cLanguageIds(languageIds);
078            }
079    
080            private LocaleUtil() {
081                    _locale = new Locale("en", "US");
082            }
083    
084            private Locale _fromLanguageId(String languageId) {
085                    if (languageId == null) {
086                            return _locale;
087                    }
088    
089                    Locale locale = _locales.get(languageId);
090    
091                    if (locale != null) {
092                            return locale;
093                    }
094    
095                    try {
096                            int pos = languageId.indexOf(CharPool.UNDERLINE);
097    
098                            if (pos == -1) {
099                                    locale = new Locale(languageId);
100                            }
101                            else {
102                                    String[] languageIdParts = StringUtil.split(
103                                            languageId, CharPool.UNDERLINE);
104    
105                                    String languageCode = languageIdParts[0];
106                                    String countryCode = languageIdParts[1];
107    
108                                    String variant = null;
109    
110                                    if (languageIdParts.length > 2) {
111                                            variant = languageIdParts[2];
112                                    }
113    
114                                    if (Validator.isNotNull(variant)) {
115                                            locale = new Locale(languageCode, countryCode, variant);
116                                    }
117                                    else {
118                                            locale = new Locale(languageCode, countryCode);
119                                    }
120                            }
121    
122                            if (_locales.size() < _MAX_LOCALES) {
123                                    _locales.put(languageId, locale);
124                            }
125                            else {
126                                    if (_log.isWarnEnabled()) {
127                                            _log.warn("There are too many entries in the locales map");
128                                    }
129                            }
130                    }
131                    catch (Exception e) {
132                            if (_log.isWarnEnabled()) {
133                                    _log.warn(languageId + " is not a valid language id");
134                            }
135                    }
136    
137                    if (locale == null) {
138                            locale = _locale;
139                    }
140    
141                    return locale;
142            }
143    
144            private Locale[] _fromLanguageIds(String[] languageIds) {
145                    Locale[] locales = new Locale[languageIds.length];
146    
147                    for (int i = 0; i < languageIds.length; i++) {
148                            locales[i] = _fromLanguageId(languageIds[i]);
149                    }
150    
151                    return locales;
152            }
153    
154            private Locale _getDefault() {
155                    Locale locale = LocaleThreadLocal.getDefaultLocale();
156    
157                    if (locale != null) {
158                            return locale;
159                    }
160    
161                    return _locale;
162            }
163    
164            private Map<String, String> _getISOLanguages(Locale locale) {
165                    Map<String, String> isoLanguages = new TreeMap<String, String>(
166                            String.CASE_INSENSITIVE_ORDER);
167    
168                    for (String isoLanguageId : Locale.getISOLanguages()) {
169                            Locale isoLocale = _fromLanguageId(isoLanguageId);
170    
171                            isoLanguages.put(
172                                    isoLocale.getDisplayLanguage(locale), isoLanguageId);
173                    }
174    
175                    return isoLanguages;
176            }
177    
178            private void _setDefault(
179                    String userLanguage, String userCountry, String userVariant) {
180    
181                    if (Validator.isNotNull(userLanguage) &&
182                            Validator.isNull(userCountry) && Validator.isNull(userVariant)) {
183    
184                            _locale = new Locale(userLanguage);
185                    }
186                    else if (Validator.isNotNull(userLanguage) &&
187                                     Validator.isNotNull(userCountry) &&
188                                     Validator.isNull(userVariant)) {
189    
190                            _locale = new Locale(userLanguage, userCountry);
191                    }
192                    else if (Validator.isNotNull(userLanguage) &&
193                                     Validator.isNotNull(userCountry) &&
194                                     Validator.isNotNull(userVariant)) {
195    
196                            _locale = new Locale(userLanguage, userCountry, userVariant);
197                    }
198            }
199    
200            private String _toLanguageId(Locale locale) {
201                    if (locale == null) {
202                            locale = _locale;
203                    }
204    
205                    String country = locale.getCountry();
206    
207                    boolean hasCountry = false;
208    
209                    if (country.length() != 0) {
210                            hasCountry = true;
211                    }
212    
213                    String variant = locale.getVariant();
214    
215                    boolean hasVariant = false;
216    
217                    if (variant.length() != 0) {
218                            hasVariant = true;
219                    }
220    
221                    if (!hasCountry && !hasVariant) {
222                            return locale.getLanguage();
223                    }
224    
225                    int length = 3;
226    
227                    if (hasCountry && hasVariant) {
228                            length = 5;
229                    }
230    
231                    StringBundler sb = new StringBundler(length);
232    
233                    sb.append(locale.getLanguage());
234    
235                    if (hasCountry) {
236                            sb.append(StringPool.UNDERLINE);
237                            sb.append(country);
238                    }
239    
240                    if (hasVariant) {
241                            sb.append(StringPool.UNDERLINE);
242                            sb.append(variant);
243                    }
244    
245                    return sb.toString();
246            }
247    
248            private String[] _toLanguageIds(Locale[] locales) {
249                    String[] languageIds = new String[locales.length];
250    
251                    for (int i = 0; i < locales.length; i++) {
252                            languageIds[i] = _toLanguageId(locales[i]);
253                    }
254    
255                    return languageIds;
256            }
257    
258            private String _toW3cLanguageId(Locale locale) {
259                    return _toW3cLanguageId(_toLanguageId(locale));
260            }
261    
262            private String _toW3cLanguageId(String languageId) {
263                    return StringUtil.replace(
264                            languageId, CharPool.UNDERLINE, CharPool.MINUS);
265            }
266    
267            private String[] _toW3cLanguageIds(Locale[] locales) {
268                    return _toW3cLanguageIds(_toLanguageIds(locales));
269            }
270    
271            private String[] _toW3cLanguageIds(String[] languageIds) {
272                    String[] w3cLanguageIds = new String[languageIds.length];
273    
274                    for (int i = 0; i < languageIds.length; i++) {
275                            w3cLanguageIds[i] = _toW3cLanguageId(languageIds[i]);
276                    }
277    
278                    return w3cLanguageIds;
279            }
280    
281            private static final int _MAX_LOCALES = 1000;
282    
283            private static Log _log = LogFactoryUtil.getLog(LocaleUtil.class);
284    
285            private static LocaleUtil _instance = new LocaleUtil();
286    
287            private Locale _locale;
288            private Map<String, Locale> _locales = new HashMap<String, Locale>();
289    
290    }