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