001    /**
002     * Copyright (c) 2000-2013 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.language.LanguageUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
021    
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Locale;
025    import java.util.Map;
026    import java.util.Set;
027    import java.util.TreeMap;
028    
029    /**
030     * @author Brian Wing Shun Chan
031     * @author Raymond Aug??
032     */
033    public class LocaleUtil {
034    
035            public static boolean equals(Locale locale1, Locale locale2) {
036                    return getInstance()._equals(locale1, locale2);
037            }
038    
039            public static Locale fromLanguageId(String languageId) {
040                    return getInstance()._fromLanguageId(languageId, true);
041            }
042    
043            public static Locale fromLanguageId(String languageId, boolean validate) {
044                    return getInstance()._fromLanguageId(languageId, validate);
045            }
046    
047            public static Locale[] fromLanguageIds(List<String> languageIds) {
048                    return getInstance()._fromLanguageIds(languageIds);
049            }
050    
051            public static Locale[] fromLanguageIds(String[] languageIds) {
052                    return getInstance()._fromLanguageIds(languageIds);
053            }
054    
055            public static Locale getDefault() {
056                    return getInstance()._getDefault();
057            }
058    
059            public static LocaleUtil getInstance() {
060                    PortalRuntimePermission.checkGetBeanProperty(LocaleUtil.class);
061    
062                    return _instance;
063            }
064    
065            public static Map<String, String> getISOLanguages(Locale locale) {
066                    return getInstance()._getISOLanguages(locale);
067            }
068    
069            public static String getLongDisplayName(
070                    Locale locale, Set<String> duplicateLanguages) {
071    
072                    return getInstance()._getLongDisplayName(locale, duplicateLanguages);
073            }
074    
075            public static Locale getMostRelevantLocale() {
076                    return getInstance()._getMostRelevantLocale();
077            }
078    
079            public static String getShortDisplayName(
080                    Locale locale, Set<String> duplicateLanguages) {
081    
082                    return getInstance()._getShortDisplayName(locale, duplicateLanguages);
083            }
084    
085            public static void setDefault(
086                    String userLanguage, String userCountry, String userVariant) {
087    
088                    getInstance()._setDefault(userLanguage, userCountry, userVariant);
089            }
090    
091            public static String toLanguageId(Locale locale) {
092                    return getInstance()._toLanguageId(locale);
093            }
094    
095            public static String[] toLanguageIds(Locale[] locales) {
096                    return getInstance()._toLanguageIds(locales);
097            }
098    
099            public static String toW3cLanguageId(Locale locale) {
100                    return getInstance()._toW3cLanguageId(locale);
101            }
102    
103            public static String toW3cLanguageId(String languageId) {
104                    return getInstance()._toW3cLanguageId(languageId);
105            }
106    
107            public static String[] toW3cLanguageIds(Locale[] locales) {
108                    return getInstance()._toW3cLanguageIds(locales);
109            }
110    
111            public static String[] toW3cLanguageIds(String[] languageIds) {
112                    return getInstance()._toW3cLanguageIds(languageIds);
113            }
114    
115            private LocaleUtil() {
116                    _locale = new Locale("en", "US");
117            }
118    
119            private boolean _equals(Locale locale1, Locale locale2) {
120                    String languageId1 = _toLanguageId(locale1);
121                    String languageId2 = _toLanguageId(locale2);
122    
123                    return languageId1.equalsIgnoreCase(languageId2);
124            }
125    
126            private Locale _fromLanguageId(String languageId, boolean validate) {
127                    if (languageId == null) {
128                            return _locale;
129                    }
130    
131                    Locale locale = _locales.get(languageId);
132    
133                    if (locale != null) {
134                            return locale;
135                    }
136    
137                    try {
138                            int pos = languageId.indexOf(CharPool.UNDERLINE);
139    
140                            if (pos == -1) {
141                                    locale = new Locale(languageId);
142                            }
143                            else {
144                                    String[] languageIdParts = StringUtil.split(
145                                            languageId, CharPool.UNDERLINE);
146    
147                                    String languageCode = languageIdParts[0];
148                                    String countryCode = languageIdParts[1];
149    
150                                    String variant = null;
151    
152                                    if (languageIdParts.length > 2) {
153                                            variant = languageIdParts[2];
154                                    }
155    
156                                    if (Validator.isNotNull(variant)) {
157                                            locale = new Locale(languageCode, countryCode, variant);
158                                    }
159                                    else {
160                                            locale = new Locale(languageCode, countryCode);
161                                    }
162                            }
163    
164                            if (validate && !LanguageUtil.isAvailableLanguageCode(languageId)) {
165                                    throw new IllegalArgumentException("Invalid locale " + locale);
166                            }
167    
168                            _locales.put(languageId, locale);
169                    }
170                    catch (Exception e) {
171                            locale = null;
172    
173                            if (_log.isWarnEnabled()) {
174                                    _log.warn(languageId + " is not a valid language id");
175                            }
176                    }
177    
178                    if (locale == null) {
179                            locale = _locale;
180                    }
181    
182                    return locale;
183            }
184    
185            private Locale[] _fromLanguageIds(List<String> languageIds) {
186                    Locale[] locales = new Locale[languageIds.size()];
187    
188                    for (int i = 0; i < languageIds.size(); i++) {
189                            locales[i] = _fromLanguageId(languageIds.get(i), true);
190                    }
191    
192                    return locales;
193            }
194    
195            private Locale[] _fromLanguageIds(String[] languageIds) {
196                    Locale[] locales = new Locale[languageIds.length];
197    
198                    for (int i = 0; i < languageIds.length; i++) {
199                            locales[i] = _fromLanguageId(languageIds[i], true);
200                    }
201    
202                    return locales;
203            }
204    
205            private Locale _getDefault() {
206                    Locale locale = LocaleThreadLocal.getDefaultLocale();
207    
208                    if (locale != null) {
209                            return locale;
210                    }
211    
212                    return _locale;
213            }
214    
215            private String _getDisplayName(
216                    String language, String country, Locale locale,
217                    Set<String> duplicateLanguages) {
218    
219                    StringBundler sb = new StringBundler(6);
220    
221                    sb.append(language);
222    
223                    if (duplicateLanguages.contains(locale.getLanguage())) {
224                            sb.append(StringPool.SPACE);
225                            sb.append(StringPool.OPEN_PARENTHESIS);
226                            sb.append(country);
227                            sb.append(StringPool.CLOSE_PARENTHESIS);
228                    }
229    
230                    if (LanguageUtil.isBetaLocale(locale)) {
231                            sb.append(_BETA_SUFFIX);
232                    }
233    
234                    return sb.toString();
235            }
236    
237            private Map<String, String> _getISOLanguages(Locale locale) {
238                    Map<String, String> isoLanguages = new TreeMap<String, String>(
239                            String.CASE_INSENSITIVE_ORDER);
240    
241                    for (String isoLanguageId : Locale.getISOLanguages()) {
242                            Locale isoLocale = _fromLanguageId(isoLanguageId, true);
243    
244                            isoLanguages.put(
245                                    isoLocale.getDisplayLanguage(locale), isoLanguageId);
246                    }
247    
248                    return isoLanguages;
249            }
250    
251            private String _getLongDisplayName(
252                    Locale locale, Set<String> duplicateLanguages) {
253    
254                    return _getDisplayName(
255                            locale.getDisplayLanguage(locale), locale.getDisplayCountry(locale),
256                            locale, duplicateLanguages);
257            }
258    
259            private Locale _getMostRelevantLocale() {
260                    Locale locale = LocaleThreadLocal.getThemeDisplayLocale();
261    
262                    if (locale == null) {
263                            locale = _getDefault();
264                    }
265    
266                    return locale;
267            }
268    
269            private String _getShortDisplayName(
270                    Locale locale, Set<String> duplicateLanguages) {
271    
272                    String language = locale.getDisplayLanguage(locale);
273    
274                    if (language.length() > 3) {
275                            language = locale.getLanguage();
276                            language = language.toUpperCase();
277                    }
278    
279                    String country = locale.getCountry();
280    
281                    return _getDisplayName(
282                            language, country.toUpperCase(), locale, duplicateLanguages);
283            }
284    
285            private void _setDefault(
286                    String userLanguage, String userCountry, String userVariant) {
287    
288                    PortalRuntimePermission.checkSetBeanProperty(getClass());
289    
290                    if (Validator.isNotNull(userLanguage) &&
291                            Validator.isNull(userCountry) && Validator.isNull(userVariant)) {
292    
293                            _locale = new Locale(userLanguage);
294                    }
295                    else if (Validator.isNotNull(userLanguage) &&
296                                     Validator.isNotNull(userCountry) &&
297                                     Validator.isNull(userVariant)) {
298    
299                            _locale = new Locale(userLanguage, userCountry);
300                    }
301                    else if (Validator.isNotNull(userLanguage) &&
302                                     Validator.isNotNull(userCountry) &&
303                                     Validator.isNotNull(userVariant)) {
304    
305                            _locale = new Locale(userLanguage, userCountry, userVariant);
306                    }
307            }
308    
309            private String _toLanguageId(Locale locale) {
310                    if (locale == null) {
311                            locale = _locale;
312                    }
313    
314                    String country = locale.getCountry();
315    
316                    boolean hasCountry = false;
317    
318                    if (country.length() != 0) {
319                            hasCountry = true;
320                    }
321    
322                    String variant = locale.getVariant();
323    
324                    boolean hasVariant = false;
325    
326                    if (variant.length() != 0) {
327                            hasVariant = true;
328                    }
329    
330                    if (!hasCountry && !hasVariant) {
331                            return locale.getLanguage();
332                    }
333    
334                    int length = 3;
335    
336                    if (hasCountry && hasVariant) {
337                            length = 5;
338                    }
339    
340                    StringBundler sb = new StringBundler(length);
341    
342                    sb.append(locale.getLanguage());
343    
344                    if (hasCountry) {
345                            sb.append(StringPool.UNDERLINE);
346                            sb.append(country);
347                    }
348    
349                    if (hasVariant) {
350                            sb.append(StringPool.UNDERLINE);
351                            sb.append(variant);
352                    }
353    
354                    return sb.toString();
355            }
356    
357            private String[] _toLanguageIds(Locale[] locales) {
358                    String[] languageIds = new String[locales.length];
359    
360                    for (int i = 0; i < locales.length; i++) {
361                            languageIds[i] = _toLanguageId(locales[i]);
362                    }
363    
364                    return languageIds;
365            }
366    
367            private String _toW3cLanguageId(Locale locale) {
368                    return _toW3cLanguageId(_toLanguageId(locale));
369            }
370    
371            private String _toW3cLanguageId(String languageId) {
372                    return StringUtil.replace(
373                            languageId, CharPool.UNDERLINE, CharPool.MINUS);
374            }
375    
376            private String[] _toW3cLanguageIds(Locale[] locales) {
377                    return _toW3cLanguageIds(_toLanguageIds(locales));
378            }
379    
380            private String[] _toW3cLanguageIds(String[] languageIds) {
381                    String[] w3cLanguageIds = new String[languageIds.length];
382    
383                    for (int i = 0; i < languageIds.length; i++) {
384                            w3cLanguageIds[i] = _toW3cLanguageId(languageIds[i]);
385                    }
386    
387                    return w3cLanguageIds;
388            }
389    
390            private static final String _BETA_SUFFIX = " [Beta]";
391    
392            private static Log _log = LogFactoryUtil.getLog(LocaleUtil.class);
393    
394            private static LocaleUtil _instance = new LocaleUtil();
395    
396            private Locale _locale;
397            private Map<String, Locale> _locales = new HashMap<String, Locale>();
398    
399    }