From e6df5f015c78ffea48e82ee9f9695991a6c4335e Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 2 Sep 2014 16:35:36 +0900 Subject: [ML5] Rewrite resetDictionariesWithDictNamePrefix This change rewrites resetDictionariesWithDictNamePrefix so that it would work if there were several locales, which is going to happen shortly. This change on its own is quite large and difficult already, so I didn't want to merge it into the change that actually makes several locales happen; another such change is following. Change-Id: Ibb80b05b73c0f0f0bea64b7e308cc4d38ca448f9 --- .../inputmethod/latin/DictionaryFacilitator.java | 123 ++++++++------ .../PersonalizationDictionaryFacilitator.java | 185 --------------------- ...sonalizationHelperForDictionaryFacilitator.java | 185 +++++++++++++++++++++ 3 files changed, 261 insertions(+), 232 deletions(-) delete mode 100644 java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java create mode 100644 java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 46428839f..31ff88e3c 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -67,7 +67,7 @@ public class DictionaryFacilitator { // To synchronize assigning mDictionaryGroup to ensure closing dictionaries. private final Object mLock = new Object(); private final DistracterFilter mDistracterFilter; - private final PersonalizationDictionaryFacilitator mPersonalizationDictionaryFacilitator; + private final PersonalizationHelperForDictionaryFacilitator mPersonalizationHelper; private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS = new String[] { @@ -175,22 +175,22 @@ public class DictionaryFacilitator { public DictionaryFacilitator() { mDistracterFilter = DistracterFilter.EMPTY_DISTRACTER_FILTER; - mPersonalizationDictionaryFacilitator = null; + mPersonalizationHelper = null; } public DictionaryFacilitator(final Context context) { mDistracterFilter = new DistracterFilterCheckingExactMatchesAndSuggestions(context); - mPersonalizationDictionaryFacilitator = - new PersonalizationDictionaryFacilitator(context, mDistracterFilter); + mPersonalizationHelper = + new PersonalizationHelperForDictionaryFacilitator(context, mDistracterFilter); } public void updateEnabledSubtypes(final List enabledSubtypes) { mDistracterFilter.updateEnabledSubtypes(enabledSubtypes); - mPersonalizationDictionaryFacilitator.updateEnabledSubtypes(enabledSubtypes); + mPersonalizationHelper.updateEnabledSubtypes(enabledSubtypes); } public void setIsMonolingualUser(final boolean isMonolingualUser) { - mPersonalizationDictionaryFacilitator.setIsMonolingualUser(isMonolingualUser); + mPersonalizationHelper.setIsMonolingualUser(isMonolingualUser); } public Locale getLocale() { @@ -226,76 +226,105 @@ public class DictionaryFacilitator { usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */); } - public void resetDictionariesWithDictNamePrefix(final Context context, final Locale newLocale, + public void resetDictionariesWithDictNamePrefix(final Context context, + final Locale newLocaleToUse, final boolean useContactsDict, final boolean usePersonalizedDicts, final boolean forceReloadMainDictionary, final DictionaryInitializationListener listener, final String dictNamePrefix) { - final boolean localeHasBeenChanged = !newLocale.equals(mDictionaryGroup.mLocale); - // We always try to have the main dictionary. Other dictionaries can be unused. - final boolean reloadMainDictionary = localeHasBeenChanged || forceReloadMainDictionary; + final HashMap> existingDictsToCleanup = new HashMap<>(); + // TODO: use several locales + final Locale[] newLocales = new Locale[] { newLocaleToUse }; // TODO: Make subDictTypesToUse configurable by resource or a static final list. final HashSet subDictTypesToUse = new HashSet<>(); + subDictTypesToUse.add(Dictionary.TYPE_USER); if (useContactsDict) { subDictTypesToUse.add(Dictionary.TYPE_CONTACTS); } - subDictTypesToUse.add(Dictionary.TYPE_USER); if (usePersonalizedDicts) { subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY); subDictTypesToUse.add(Dictionary.TYPE_PERSONALIZATION); subDictTypesToUse.add(Dictionary.TYPE_CONTEXTUAL); } - final Dictionary newMainDict; - if (reloadMainDictionary) { - // The main dictionary will be asynchronously loaded. - newMainDict = null; - } else { - newMainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN); - } - - final Map subDicts = new HashMap<>(); - for (final String dictType : SUB_DICT_TYPES) { - if (!subDictTypesToUse.contains(dictType)) { - // This dictionary will not be used. + // Gather all dictionaries. We'll remove them from the list to clean up later. + for (final Locale newLocale : newLocales) { + final ArrayList dictsForLocale = new ArrayList<>(); + existingDictsToCleanup.put(newLocale, dictsForLocale); + final DictionaryGroup currentDictionaryGroupForLocale = + newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null; + if (null == currentDictionaryGroupForLocale) { continue; } - final ExpandableBinaryDictionary dict; - if (!localeHasBeenChanged && mDictionaryGroup.hasDict(dictType)) { - // Continue to use current dictionary. - dict = mDictionaryGroup.getSubDict(dictType); + for (final String dictType : SUB_DICT_TYPES) { + if (currentDictionaryGroupForLocale.hasDict(dictType)) { + dictsForLocale.add(dictType); + } + } + if (currentDictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN)) { + dictsForLocale.add(Dictionary.TYPE_MAIN); + } + } + + final HashMap newDictionaryGroups = new HashMap<>(); + for (final Locale newLocale : newLocales) { + final DictionaryGroup dictionaryGroupForLocale = + newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null; + final ArrayList dictsToCleanupForLocale = existingDictsToCleanup.get(newLocale); + final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale); + + final Dictionary mainDict; + if (forceReloadMainDictionary || noExistingDictsForThisLocale + || !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN)) { + mainDict = null; } else { - // Start to use new dictionary. - dict = getSubDict(dictType, context, newLocale, null /* dictFile */, - dictNamePrefix); + mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN); + dictsToCleanupForLocale.remove(Dictionary.TYPE_MAIN); } - subDicts.put(dictType, dict); + + final Map subDicts = new HashMap<>(); + for (final String subDictType : subDictTypesToUse) { + final ExpandableBinaryDictionary subDict; + if (noExistingDictsForThisLocale + || !dictionaryGroupForLocale.hasDict(subDictType)) { + // Create a new dictionary. + subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */, + dictNamePrefix); + } else { + // Reuse the existing dictionary, and don't close it at the end + subDict = dictionaryGroupForLocale.getSubDict(subDictType); + dictsToCleanupForLocale.remove(subDictType); + } + subDicts.put(subDictType, subDict); + } + newDictionaryGroups.put(newLocale, new DictionaryGroup(newLocale, mainDict, subDicts)); } - // Replace DictionaryGroup. - final DictionaryGroup newDictionaryGroup = new DictionaryGroup(newLocale, newMainDict, subDicts); + // Replace Dictionaries. + // TODO: use multiple locales. + final DictionaryGroup newDictionaryGroup = newDictionaryGroups.get(newLocaleToUse); final DictionaryGroup oldDictionaryGroup; synchronized (mLock) { oldDictionaryGroup = mDictionaryGroup; mDictionaryGroup = newDictionaryGroup; mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context); - if (reloadMainDictionary) { - asyncReloadMainDictionary(context, newLocale, listener); + if (null == newDictionaryGroup.getDict(Dictionary.TYPE_MAIN)) { + asyncReloadMainDictionary(context, newLocaleToUse, listener); } } if (listener != null) { listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary()); } + // Clean up old dictionaries. - if (reloadMainDictionary) { - oldDictionaryGroup.closeDict(Dictionary.TYPE_MAIN); - } - for (final String dictType : SUB_DICT_TYPES) { - if (localeHasBeenChanged || !subDictTypesToUse.contains(dictType)) { - oldDictionaryGroup.closeDict(dictType); + for (final Locale localeToCleanUp : existingDictsToCleanup.keySet()) { + final ArrayList dictTypesToCleanUp = + existingDictsToCleanup.get(localeToCleanUp); + final DictionaryGroup dictionarySetToCleanup = oldDictionaryGroup; + for (final String dictType : dictTypesToCleanUp) { + dictionarySetToCleanup.closeDict(dictType); } } - oldDictionaryGroup.mSubDictMap.clear(); } private void asyncReloadMainDictionary(final Context context, final Locale locale, @@ -362,8 +391,8 @@ public class DictionaryFacilitator { dictionaryGroup.closeDict(dictType); } mDistracterFilter.close(); - if (mPersonalizationDictionaryFacilitator != null) { - mPersonalizationDictionaryFacilitator.close(); + if (mPersonalizationHelper != null) { + mPersonalizationHelper.close(); } } @@ -386,7 +415,7 @@ public class DictionaryFacilitator { public void flushPersonalizationDictionary() { final ExpandableBinaryDictionary personalizationDictUsedForSuggestion = mDictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION); - mPersonalizationDictionaryFacilitator.flushPersonalizationDictionariesToUpdate( + mPersonalizationHelper.flushPersonalizationDictionariesToUpdate( personalizationDictUsedForSuggestion); mDistracterFilter.close(); } @@ -592,7 +621,7 @@ public class DictionaryFacilitator { // personalization dictionary. public void clearPersonalizationDictionary() { clearSubDictionary(Dictionary.TYPE_PERSONALIZATION); - mPersonalizationDictionaryFacilitator.clearDictionariesToUpdate(); + mPersonalizationHelper.clearDictionariesToUpdate(); } public void clearContextualDictionary() { @@ -603,7 +632,7 @@ public class DictionaryFacilitator { final PersonalizationDataChunk personalizationDataChunk, final SpacingAndPunctuations spacingAndPunctuations, final AddMultipleDictionaryEntriesCallback callback) { - mPersonalizationDictionaryFacilitator.addEntriesToPersonalizationDictionariesToUpdate( + mPersonalizationHelper.addEntriesToPersonalizationDictionariesToUpdate( getLocale(), personalizationDataChunk, spacingAndPunctuations, callback); } diff --git a/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java deleted file mode 100644 index aa8e312a4..000000000 --- a/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2014 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 com.android.inputmethod.latin; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicInteger; - -import android.content.Context; -import android.view.inputmethod.InputMethodSubtype; - -import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback; -import com.android.inputmethod.latin.personalization.PersonalizationDataChunk; -import com.android.inputmethod.latin.personalization.PersonalizationDictionary; -import com.android.inputmethod.latin.settings.SpacingAndPunctuations; -import com.android.inputmethod.latin.utils.DistracterFilter; -import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary; -import com.android.inputmethod.latin.utils.LanguageModelParam; -import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; - -/** - * Class for managing and updating personalization dictionaries. - */ -public class PersonalizationDictionaryFacilitator { - private final Context mContext; - private final DistracterFilter mDistracterFilter; - private final HashMap> mLangToLocalesMap = new HashMap<>(); - private final HashMap mPersonalizationDictsToUpdate = - new HashMap<>(); - private boolean mIsMonolingualUser = false;; - - PersonalizationDictionaryFacilitator(final Context context, - final DistracterFilter distracterFilter) { - mContext = context; - mDistracterFilter = distracterFilter; - } - - public void close() { - mLangToLocalesMap.clear(); - for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) { - dict.close(); - } - mPersonalizationDictsToUpdate.clear(); - } - - public void clearDictionariesToUpdate() { - for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) { - dict.clear(); - } - mPersonalizationDictsToUpdate.clear(); - } - - public void updateEnabledSubtypes(final List enabledSubtypes) { - for (final InputMethodSubtype subtype : enabledSubtypes) { - final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); - final String language = locale.getLanguage(); - final HashSet locales = mLangToLocalesMap.get(language); - if (locales != null) { - locales.add(locale); - } else { - final HashSet localeSet = new HashSet<>(); - localeSet.add(locale); - mLangToLocalesMap.put(language, localeSet); - } - } - } - - public void setIsMonolingualUser(final boolean isMonolingualUser) { - mIsMonolingualUser = isMonolingualUser; - } - - /** - * Flush personalization dictionaries to dictionary files. Close dictionaries after writing - * files except the dictionary that is used for generating suggestions. - * - * @param personalizationDictUsedForSuggestion the personalization dictionary used for - * generating suggestions that won't be closed. - */ - public void flushPersonalizationDictionariesToUpdate( - final ExpandableBinaryDictionary personalizationDictUsedForSuggestion) { - for (final ExpandableBinaryDictionary personalizationDict : - mPersonalizationDictsToUpdate.values()) { - personalizationDict.asyncFlushBinaryDictionary(); - if (personalizationDict != personalizationDictUsedForSuggestion) { - // Close if the dictionary is not being used for suggestion. - personalizationDict.close(); - } - } - mDistracterFilter.close(); - mPersonalizationDictsToUpdate.clear(); - } - - private ExpandableBinaryDictionary getPersonalizationDictToUpdate(final Context context, - final Locale locale) { - ExpandableBinaryDictionary personalizationDict = mPersonalizationDictsToUpdate.get(locale); - if (personalizationDict != null) { - return personalizationDict; - } - personalizationDict = PersonalizationDictionary.getDictionary(context, locale, - null /* dictFile */, "" /* dictNamePrefix */); - mPersonalizationDictsToUpdate.put(locale, personalizationDict); - return personalizationDict; - } - - private void addEntriesToPersonalizationDictionariesForLocale(final Locale locale, - final PersonalizationDataChunk personalizationDataChunk, - final SpacingAndPunctuations spacingAndPunctuations, - final AddMultipleDictionaryEntriesCallback callback) { - final ExpandableBinaryDictionary personalizationDict = - getPersonalizationDictToUpdate(mContext, locale); - if (personalizationDict == null) { - if (callback != null) { - callback.onFinished(); - } - return; - } - final ArrayList languageModelParams = - LanguageModelParam.createLanguageModelParamsFrom( - personalizationDataChunk.mTokens, - personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations, - locale, new DistracterFilterCheckingIsInDictionary( - mDistracterFilter, personalizationDict)); - if (languageModelParams == null || languageModelParams.isEmpty()) { - if (callback != null) { - callback.onFinished(); - } - return; - } - personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback); - } - - public void addEntriesToPersonalizationDictionariesToUpdate(final Locale defaultLocale, - final PersonalizationDataChunk personalizationDataChunk, - final SpacingAndPunctuations spacingAndPunctuations, - final AddMultipleDictionaryEntriesCallback callback) { - final String language = personalizationDataChunk.mDetectedLanguage; - final HashSet locales; - if (mIsMonolingualUser && PersonalizationDataChunk.LANGUAGE_UNKNOWN.equals(language) - && mLangToLocalesMap.size() == 1) { - locales = mLangToLocalesMap.get(defaultLocale.getLanguage()); - } else { - locales = mLangToLocalesMap.get(language); - } - if (locales == null || locales.isEmpty()) { - if (callback != null) { - callback.onFinished(); - } - return; - } - final AtomicInteger remainingTaskCount = new AtomicInteger(locales.size()); - final AddMultipleDictionaryEntriesCallback callbackForLocales = - new AddMultipleDictionaryEntriesCallback() { - @Override - public void onFinished() { - if (remainingTaskCount.decrementAndGet() == 0) { - // Update tasks for all locales have been finished. - if (callback != null) { - callback.onFinished(); - } - } - } - }; - for (final Locale locale : locales) { - addEntriesToPersonalizationDictionariesForLocale(locale, personalizationDataChunk, - spacingAndPunctuations, callbackForLocales); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java new file mode 100644 index 000000000..43cebdfa4 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2014 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 com.android.inputmethod.latin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicInteger; + +import android.content.Context; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback; +import com.android.inputmethod.latin.personalization.PersonalizationDataChunk; +import com.android.inputmethod.latin.personalization.PersonalizationDictionary; +import com.android.inputmethod.latin.settings.SpacingAndPunctuations; +import com.android.inputmethod.latin.utils.DistracterFilter; +import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary; +import com.android.inputmethod.latin.utils.LanguageModelParam; +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +/** + * Class for managing and updating personalization dictionaries. + */ +public class PersonalizationHelperForDictionaryFacilitator { + private final Context mContext; + private final DistracterFilter mDistracterFilter; + private final HashMap> mLangToLocalesMap = new HashMap<>(); + private final HashMap mPersonalizationDictsToUpdate = + new HashMap<>(); + private boolean mIsMonolingualUser = false; + + PersonalizationHelperForDictionaryFacilitator(final Context context, + final DistracterFilter distracterFilter) { + mContext = context; + mDistracterFilter = distracterFilter; + } + + public void close() { + mLangToLocalesMap.clear(); + for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) { + dict.close(); + } + mPersonalizationDictsToUpdate.clear(); + } + + public void clearDictionariesToUpdate() { + for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) { + dict.clear(); + } + mPersonalizationDictsToUpdate.clear(); + } + + public void updateEnabledSubtypes(final List enabledSubtypes) { + for (final InputMethodSubtype subtype : enabledSubtypes) { + final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + final String language = locale.getLanguage(); + final HashSet locales = mLangToLocalesMap.get(language); + if (locales != null) { + locales.add(locale); + } else { + final HashSet localeSet = new HashSet<>(); + localeSet.add(locale); + mLangToLocalesMap.put(language, localeSet); + } + } + } + + public void setIsMonolingualUser(final boolean isMonolingualUser) { + mIsMonolingualUser = isMonolingualUser; + } + + /** + * Flush personalization dictionaries to dictionary files. Close dictionaries after writing + * files except the dictionary that is used for generating suggestions. + * + * @param personalizationDictUsedForSuggestion the personalization dictionary used for + * generating suggestions that won't be closed. + */ + public void flushPersonalizationDictionariesToUpdate( + final ExpandableBinaryDictionary personalizationDictUsedForSuggestion) { + for (final ExpandableBinaryDictionary personalizationDict : + mPersonalizationDictsToUpdate.values()) { + personalizationDict.asyncFlushBinaryDictionary(); + if (personalizationDict != personalizationDictUsedForSuggestion) { + // Close if the dictionary is not being used for suggestion. + personalizationDict.close(); + } + } + mDistracterFilter.close(); + mPersonalizationDictsToUpdate.clear(); + } + + private ExpandableBinaryDictionary getPersonalizationDictToUpdate(final Context context, + final Locale locale) { + ExpandableBinaryDictionary personalizationDict = mPersonalizationDictsToUpdate.get(locale); + if (personalizationDict != null) { + return personalizationDict; + } + personalizationDict = PersonalizationDictionary.getDictionary(context, locale, + null /* dictFile */, "" /* dictNamePrefix */); + mPersonalizationDictsToUpdate.put(locale, personalizationDict); + return personalizationDict; + } + + private void addEntriesToPersonalizationDictionariesForLocale(final Locale locale, + final PersonalizationDataChunk personalizationDataChunk, + final SpacingAndPunctuations spacingAndPunctuations, + final AddMultipleDictionaryEntriesCallback callback) { + final ExpandableBinaryDictionary personalizationDict = + getPersonalizationDictToUpdate(mContext, locale); + if (personalizationDict == null) { + if (callback != null) { + callback.onFinished(); + } + return; + } + final ArrayList languageModelParams = + LanguageModelParam.createLanguageModelParamsFrom( + personalizationDataChunk.mTokens, + personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations, + locale, new DistracterFilterCheckingIsInDictionary( + mDistracterFilter, personalizationDict)); + if (languageModelParams == null || languageModelParams.isEmpty()) { + if (callback != null) { + callback.onFinished(); + } + return; + } + personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback); + } + + public void addEntriesToPersonalizationDictionariesToUpdate(final Locale defaultLocale, + final PersonalizationDataChunk personalizationDataChunk, + final SpacingAndPunctuations spacingAndPunctuations, + final AddMultipleDictionaryEntriesCallback callback) { + final String language = personalizationDataChunk.mDetectedLanguage; + final HashSet locales; + if (mIsMonolingualUser && PersonalizationDataChunk.LANGUAGE_UNKNOWN.equals(language) + && mLangToLocalesMap.size() == 1) { + locales = mLangToLocalesMap.get(defaultLocale.getLanguage()); + } else { + locales = mLangToLocalesMap.get(language); + } + if (locales == null || locales.isEmpty()) { + if (callback != null) { + callback.onFinished(); + } + return; + } + final AtomicInteger remainingTaskCount = new AtomicInteger(locales.size()); + final AddMultipleDictionaryEntriesCallback callbackForLocales = + new AddMultipleDictionaryEntriesCallback() { + @Override + public void onFinished() { + if (remainingTaskCount.decrementAndGet() == 0) { + // Update tasks for all locales have been finished. + if (callback != null) { + callback.onFinished(); + } + } + } + }; + for (final Locale locale : locales) { + addEntriesToPersonalizationDictionariesForLocale(locale, personalizationDataChunk, + spacingAndPunctuations, callbackForLocales); + } + } +} -- cgit v1.2.3-83-g751a