blob: 9ccc35b59a5803ccd9f3eccfd1f15b7f5bcbd9b0 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 android.support.v4.os;
import android.os.Build;
import android.os.LocaleList;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.Size;
import java.util.Locale;
/**
* Helper for accessing features in {@link LocaleList}.
*/
public final class LocaleListCompat {
static final LocaleListInterface IMPL;
private static final LocaleListCompat sEmptyLocaleList = new LocaleListCompat();
static class LocaleListCompatBaseImpl implements LocaleListInterface {
private LocaleListHelper mLocaleList = new LocaleListHelper();
@Override
public void setLocaleList(@NonNull Locale... list) {
mLocaleList = new LocaleListHelper(list);
}
@Override
public Object getLocaleList() {
return mLocaleList;
}
@Override
public Locale get(int index) {
return mLocaleList.get(index);
}
@Override
public boolean isEmpty() {
return mLocaleList.isEmpty();
}
@Override
@IntRange(from = 0)
public int size() {
return mLocaleList.size();
}
@Override
@IntRange(from = -1)
public int indexOf(Locale locale) {
return mLocaleList.indexOf(locale);
}
@Override
public boolean equals(Object other) {
return mLocaleList.equals(((LocaleListCompat) other).unwrap());
}
@Override
public int hashCode() {
return mLocaleList.hashCode();
}
@Override
public String toString() {
return mLocaleList.toString();
}
@Override
public String toLanguageTags() {
return mLocaleList.toLanguageTags();
}
@Nullable
@Override
public Locale getFirstMatch(String[] supportedLocales) {
if (mLocaleList != null) {
return mLocaleList.getFirstMatch(supportedLocales);
}
return null;
}
}
@RequiresApi(24)
static class LocaleListCompatApi24Impl implements LocaleListInterface {
private LocaleList mLocaleList = new LocaleList();
@Override
public void setLocaleList(@NonNull Locale... list) {
mLocaleList = new LocaleList(list);
}
@Override
public Object getLocaleList() {
return mLocaleList;
}
@Override
public Locale get(int index) {
return mLocaleList.get(index);
}
@Override
public boolean isEmpty() {
return mLocaleList.isEmpty();
}
@Override
@IntRange(from = 0)
public int size() {
return mLocaleList.size();
}
@Override
@IntRange(from = -1)
public int indexOf(Locale locale) {
return mLocaleList.indexOf(locale);
}
@Override
public boolean equals(Object other) {
return mLocaleList.equals(((LocaleListCompat) other).unwrap());
}
@Override
public int hashCode() {
return mLocaleList.hashCode();
}
@Override
public String toString() {
return mLocaleList.toString();
}
@Override
public String toLanguageTags() {
return mLocaleList.toLanguageTags();
}
@Nullable
@Override
public Locale getFirstMatch(String[] supportedLocales) {
if (mLocaleList != null) {
return mLocaleList.getFirstMatch(supportedLocales);
}
return null;
}
}
static {
if (Build.VERSION.SDK_INT >= 24) {
IMPL = new LocaleListCompatApi24Impl();
} else {
IMPL = new LocaleListCompatBaseImpl();
}
}
private LocaleListCompat() {}
/**
* Creates a new instance of {@link LocaleListCompat} from the Locale list.
*/
@RequiresApi(24)
public static LocaleListCompat wrap(Object object) {
LocaleListCompat instance = new LocaleListCompat();
if (object instanceof LocaleList) {
instance.setLocaleList((LocaleList) object);
}
return instance;
}
/**
* Gets the underlying framework object.
*
* @return an android.os.LocaleList object if API >= 24 , or {@link Locale} if not.
*/
@Nullable
public Object unwrap() {
return IMPL.getLocaleList();
}
/**
* Creates a new instance of {@link LocaleListCompat} from the {@link Locale} array.
*/
public static LocaleListCompat create(@NonNull Locale... localeList) {
LocaleListCompat instance = new LocaleListCompat();
instance.setLocaleListArray(localeList);
return instance;
}
/**
* Retrieves the {@link Locale} at the specified index.
*
* @param index The position to retrieve.
* @return The {@link Locale} in the given index
*/
public Locale get(int index) {
return IMPL.get(index);
}
/**
* Returns whether the {@link LocaleListCompat} contains no {@link Locale} items.
*
* @return {@code true} if this {@link LocaleListCompat} has no {@link Locale} items,
* {@code false} otherwise
*/
public boolean isEmpty() {
return IMPL.isEmpty();
}
/**
* Returns the number of {@link Locale} items in this {@link LocaleListCompat}.
*/
@IntRange(from = 0)
public int size() {
return IMPL.size();
}
/**
* Searches this {@link LocaleListCompat} for the specified {@link Locale} and returns the
* index of the first occurrence.
*
* @param locale The {@link Locale} to search for.
* @return The index of the first occurrence of the {@link Locale} or {@code -1} if the item
* wasn't found
*/
@IntRange(from = -1)
public int indexOf(Locale locale) {
return IMPL.indexOf(locale);
}
/**
* Retrieves a String representation of the language tags in this list.
*/
@NonNull
public String toLanguageTags() {
return IMPL.toLanguageTags();
}
/**
* Returns the first match in the locale list given an unordered array of supported locales
* in BCP 47 format.
*
* @return The first {@link Locale} from this list that appears in the given array, or
* {@code null} if the {@link LocaleListCompat} is empty.
*/
public Locale getFirstMatch(String[] supportedLocales) {
return IMPL.getFirstMatch(supportedLocales);
}
/**
* Retrieve an empty instance of {@link LocaleList}.
*/
@NonNull
public static LocaleListCompat getEmptyLocaleList() {
return sEmptyLocaleList;
}
/**
* Generates a new LocaleList with the given language tags.
*
* <p>Note that for API < 24 only the first language tag will be used.</>
*
* @param list The language tags to be included as a single {@link String} separated by commas.
* @return A new instance with the {@link Locale} items identified by the given tags.
*/
@NonNull
public static LocaleListCompat forLanguageTags(@Nullable String list) {
if (list == null || list.isEmpty()) {
return getEmptyLocaleList();
} else {
final String[] tags = list.split(",");
final Locale[] localeArray = new Locale[tags.length];
for (int i = 0; i < localeArray.length; i++) {
localeArray[i] = Build.VERSION.SDK_INT >= 21
? Locale.forLanguageTag(tags[i])
: LocaleHelper.forLanguageTag(tags[i]);
}
LocaleListCompat instance = new LocaleListCompat();
instance.setLocaleListArray(localeArray);
return instance;
}
}
/**
* Returns the default locale list, adjusted by moving the default locale to its first
* position.
*/
@NonNull @Size(min = 1)
public static LocaleListCompat getAdjustedDefault() {
if (Build.VERSION.SDK_INT >= 24) {
return LocaleListCompat.wrap(LocaleList.getAdjustedDefault());
} else {
return LocaleListCompat.create(Locale.getDefault());
}
}
/**
* The result is guaranteed to include the default Locale returned by Locale.getDefault(), but
* not necessarily at the top of the list. The default locale not being at the top of the list
* is an indication that the system has set the default locale to one of the user's other
* preferred locales, having concluded that the primary preference is not supported but a
* secondary preference is.
*
* <p>Note that for API &gt;= 24 the default LocaleList would change if Locale.setDefault() is
* called. This method takes that into account by always checking the output of
* Locale.getDefault() and recalculating the default LocaleList if needed.</p>
*/
@NonNull @Size(min = 1)
public static LocaleListCompat getDefault() {
if (Build.VERSION.SDK_INT >= 24) {
return LocaleListCompat.wrap(LocaleList.getDefault());
} else {
return LocaleListCompat.create(Locale.getDefault());
}
}
@Override
public boolean equals(Object other) {
return IMPL.equals(other);
}
@Override
public int hashCode() {
return IMPL.hashCode();
}
@Override
public String toString() {
return IMPL.toString();
}
@RequiresApi(24)
private void setLocaleList(LocaleList localeList) {
final int localeListSize = localeList.size();
if (localeListSize > 0) {
Locale[] localeArrayList = new Locale[localeListSize];
for (int i = 0; i < localeListSize; i++) {
localeArrayList[i] = localeList.get(i);
}
IMPL.setLocaleList(localeArrayList);
}
}
private void setLocaleListArray(Locale... localeArrayList) {
IMPL.setLocaleList(localeArrayList);
}
}