Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2006-2015 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.phloc.commons.locale;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.phloc.commons.CGlobal;
import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.annotations.IsLocked;
import com.phloc.commons.annotations.IsLocked.ELockType;
import com.phloc.commons.annotations.PresentForCodeCoverage;
import com.phloc.commons.annotations.ReturnsImmutableObject;
import com.phloc.commons.annotations.ReturnsMutableCopy;
import com.phloc.commons.cache.AbstractNotifyingCache;
import com.phloc.commons.collections.ContainerHelper;
import com.phloc.commons.regex.RegExHelper;
import com.phloc.commons.state.EChange;
import com.phloc.commons.string.StringHelper;
import com.phloc.commons.system.SystemHelper;
/**
* Misc locale utility methods.
*
* @author Philip Helger
*/
@Immutable
public final class LocaleUtils
{
/**
* Small cache for the resolved locales.
*
* @author Philip Helger
*/
private static final class LocaleListCache extends AbstractNotifyingCache >
{
public LocaleListCache ()
{
super (LocaleListCache.class.getName ());
}
@Override
@Nullable
@IsLocked (ELockType.WRITE)
protected List getValueToCache (@Nullable final Locale aBaseLocale)
{
if (aBaseLocale == null)
return null;
// List has a maximum of 3 entries
final List ret = new ArrayList (3);
final String sLanguage = aBaseLocale.getLanguage ();
if (sLanguage.length () > 0)
{
// Use only the language
ret.add (0, LocaleCache.getLocale (sLanguage));
final String sCountry = aBaseLocale.getCountry ();
if (sCountry.length () > 0)
{
// Use language + country
ret.add (0, LocaleCache.getLocale (sLanguage, sCountry));
final String sVariant = aBaseLocale.getVariant ();
if (sVariant.length () > 0)
{
// Use language + country + variant
ret.add (0, LocaleCache.getLocale (sLanguage, sCountry, sVariant));
}
}
}
return ContainerHelper.makeUnmodifiable (ret);
}
}
private static final String LOCALE_ALL_STR = CGlobal.LOCALE_ALL.toString ();
private static final String LOCALE_INDEPENDENT_STR = CGlobal.LOCALE_INDEPENDENT.toString ();
private static final LocaleListCache s_aLocaleListCache = new LocaleListCache ();
@PresentForCodeCoverage
@SuppressWarnings ("unused")
private static final LocaleUtils s_aInstance = new LocaleUtils ();
private LocaleUtils ()
{}
/**
* Get the display name of the passed language in the currently selected UI
* language.
*
* @param aLocale
* The locale from which the display name is required. May be
* null.
* @param aContentLocale
* The locale in which the name of the locale is required. If aLocale
* is "de" and display locale is "de" the result would be "Deutsch"
* whereas if display locale is "en" the result would be "German".
* @return the display name of the language or a fixed text if the passed
* Locale is null, "all" or "independent"
* @see CGlobal#LOCALE_ALL
* @see CGlobal#LOCALE_INDEPENDENT
*/
@Nonnull
public static String getLocaleDisplayName (@Nullable final Locale aLocale, @Nonnull final Locale aContentLocale)
{
ValueEnforcer.notNull (aContentLocale, "ContentLocale");
if (aLocale == null || aLocale.equals (CGlobal.LOCALE_INDEPENDENT))
return ELocaleName.ID_LANGUAGE_INDEPENDENT.getDisplayText (aContentLocale);
if (aLocale.equals (CGlobal.LOCALE_ALL))
return ELocaleName.ID_LANGUAGE_ALL.getDisplayText (aContentLocale);
return aLocale.getDisplayName (aContentLocale);
}
/**
* Get the display name of the passed locale in the passed locale.
*
* @param aLocale
* The locale to use. May not be null.
* @return The native display name of the passed locale.
*/
@Nonnull
public static String getLocaleNativeDisplayName (@Nonnull final Locale aLocale)
{
ValueEnforcer.notNull (aLocale, "Locale");
return getLocaleDisplayName (aLocale, aLocale);
}
/**
* Get all possible locale names in the passed locale
*
* @param aContentLocale
* the locale ID in which the language list is required
* @return The mapping from the input locale to the display text. The result
* map is not ordered.
*/
@Nonnull
@ReturnsMutableCopy
public static Map getAllLocaleDisplayNames (@Nonnull final Locale aContentLocale)
{
ValueEnforcer.notNull (aContentLocale, "ContentLocale");
final Map ret = new HashMap ();
for (final Locale aCurLocale : LocaleCache.getAllLocales ())
ret.put (aCurLocale, getLocaleDisplayName (aCurLocale, aContentLocale));
return ret;
}
/**
* Get a list with all valid locale permutations of the passed locale. If the
* passed locale has no language, always an empty list is returned.
* Examples:
*
*
* @param aLocale
* The locale to get the permutation from. May not be null
* .
* @return A non-null unmodifiable list of all permutations of
* the locale, with the most specific locale being first. The returned
* list has never more than three entries. The returned list may have
* no entries, if the passed locale has no language.
*/
@Nonnull
@ReturnsImmutableObject
public static List getCalculatedLocaleListForResolving (@Nonnull final Locale aLocale)
{
ValueEnforcer.notNull (aLocale, "Locale");
return s_aLocaleListCache.getFromCache (aLocale);
}
/**
* Convert a String in the form "language-country-variant" to a Locale object.
* Language needs to have exactly 2 characters. Country is optional but if
* present needs to have exactly 2 characters. Variant is optional.
*
* @param sLocaleAsString
* The string representation to be converted to a Locale.
* @return Never null. If the passed parameter is
* null or empty, {@link SystemHelper#getSystemLocale()}
* is returned.
*/
@Nonnull
public static Locale getLocaleFromString (@Nullable final String sLocaleAsString)
{
if (StringHelper.hasNoText (sLocaleAsString))
{
// not specified => getDefault
return SystemHelper.getSystemLocale ();
}
String sLanguage;
String sCountry;
String sVariant;
int i1 = sLocaleAsString.indexOf (CGlobal.LOCALE_SEPARATOR);
if (i1 < 0)
{
// No separator present -> use as is
sLanguage = sLocaleAsString;
sCountry = "";
sVariant = "";
}
else
{
// Language found
sLanguage = sLocaleAsString.substring (0, i1);
++i1;
// Find next separator
final int i2 = sLocaleAsString.indexOf (CGlobal.LOCALE_SEPARATOR, i1);
if (i2 < 0)
{
// No other separator -> country is the rest
sCountry = sLocaleAsString.substring (i1);
sVariant = "";
}
else
{
// We have country and variant
sCountry = sLocaleAsString.substring (i1, i2);
sVariant = sLocaleAsString.substring (i2 + 1);
}
}
// Unify elements
if (sLanguage.length () == 2)
sLanguage = sLanguage.toLowerCase (Locale.US);
else
sLanguage = "";
if (sCountry.length () == 2)
sCountry = sCountry.toUpperCase (Locale.US);
else
sCountry = "";
if (sVariant.length () > 0 && (sLanguage.length () == 2 || sCountry.length () == 2))
sVariant = sVariant.toUpperCase (Locale.US);
else
sVariant = "";
// And now resolve using the locale cache
return LocaleCache.getLocale (sLanguage, sCountry, sVariant);
}
@Nullable
public static Locale getLocaleToUseOrNull (@Nonnull final Locale aRequestLocale,
@Nonnull final Collection aAvailableLocales)
{
return getLocaleToUseOrFallback (aRequestLocale, aAvailableLocales, null);
}
@Nullable
public static Locale getLocaleToUseOrFallback (@Nonnull final Locale aRequestLocale,
@Nonnull final Collection aAvailableLocales,
@Nullable final Locale aFallback)
{
ValueEnforcer.notNull (aRequestLocale, "RequestLocale");
ValueEnforcer.notNull (aAvailableLocales, "AvailableLocales");
// first check direct match
if (aAvailableLocales.contains (aRequestLocale))
return aRequestLocale;
// try to resolve a more general locale than asked for
for (final Locale aCurrentLocale : getCalculatedLocaleListForResolving (aRequestLocale))
if (aAvailableLocales.contains (aCurrentLocale))
return aCurrentLocale;
// try to resolve a more specific locale than asked for (only check
// language)
final String sRequestLanguage = aRequestLocale.getLanguage ();
if (sRequestLanguage != null)
for (final Locale aCurrentAvailableLocale : aAvailableLocales)
if (sRequestLanguage.equals (aCurrentAvailableLocale.getLanguage ()))
return aCurrentAvailableLocale;
// If none matched, check if "all" is provided
if (aAvailableLocales.contains (CGlobal.LOCALE_ALL))
return CGlobal.LOCALE_ALL;
// If none matched, check if "independent" is provided
if (aAvailableLocales.contains (CGlobal.LOCALE_INDEPENDENT))
return CGlobal.LOCALE_INDEPENDENT;
// No matching found -> fallback locale
return aFallback;
}
/**
* Check if the passed locale is one of the special locales "all" or
* "independent"
*
* @param aLocale
* The locale to check. May be null.
* @return if the passed locale is not null and a special locale.
* @see CGlobal#LOCALE_ALL
* @see CGlobal#LOCALE_INDEPENDENT
*/
public static boolean isSpecialLocale (@Nullable final Locale aLocale)
{
return CGlobal.LOCALE_ALL.equals (aLocale) || CGlobal.LOCALE_INDEPENDENT.equals (aLocale);
}
/**
* Check if the passed locale is one of the special locales "all" or
* "independent"
*
* @param sLocale
* The locale to check. May be null.
* @return if the passed locale is not null and a special locale.
* @see CGlobal#LOCALE_ALL
* @see CGlobal#LOCALE_INDEPENDENT
*/
public static boolean isSpecialLocaleCode (@Nullable final String sLocale)
{
return LOCALE_ALL_STR.equalsIgnoreCase (sLocale) || LOCALE_INDEPENDENT_STR.equalsIgnoreCase (sLocale);
}
@Nullable
public static String getValidLanguageCode (@Nullable final String sCode)
{
if (StringHelper.hasText (sCode) &&
(RegExHelper.stringMatchesPattern ("[a-zA-Z]{2,8}", sCode) || isSpecialLocaleCode (sCode)))
{
return sCode.toLowerCase (Locale.US);
}
return null;
}
@Nullable
public static String getValidCountryCode (@Nullable final String sCode)
{
if (StringHelper.hasText (sCode) && RegExHelper.stringMatchesPattern ("[a-zA-Z]{2}|[0-9]{3}", sCode))
{
return sCode.toUpperCase (CGlobal.LOCALE_FIXED_NUMBER_FORMAT);
}
return null;
}
/**
* Clear all stored locale lists
*
* @return {@link EChange}.
*/
@Nonnull
public static EChange clearCache ()
{
return s_aLocaleListCache.clearCache ();
}
}