PersonalizationHelper.java revision d102eb80da07de6b9541c3e8d767441d84257b8d
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.inputmethod.latin.personalization;
18
19import com.android.inputmethod.latin.utils.CollectionUtils;
20import com.android.inputmethod.latin.utils.FileUtils;
21
22import android.content.Context;
23import android.util.Log;
24
25import java.io.File;
26import java.io.FilenameFilter;
27import java.lang.ref.SoftReference;
28import java.util.Locale;
29import java.util.concurrent.ConcurrentHashMap;
30
31public class PersonalizationHelper {
32    private static final String TAG = PersonalizationHelper.class.getSimpleName();
33    private static final boolean DEBUG = false;
34    private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
35            sLangUserHistoryDictCache = CollectionUtils.newConcurrentHashMap();
36    private static final ConcurrentHashMap<String, SoftReference<PersonalizationDictionary>>
37            sLangPersonalizationDictCache = CollectionUtils.newConcurrentHashMap();
38
39    public static UserHistoryDictionary getUserHistoryDictionary(
40            final Context context, final Locale locale) {
41        final String localeStr = locale.toString();
42        synchronized (sLangUserHistoryDictCache) {
43            if (sLangUserHistoryDictCache.containsKey(localeStr)) {
44                final SoftReference<UserHistoryDictionary> ref =
45                        sLangUserHistoryDictCache.get(localeStr);
46                final UserHistoryDictionary dict = ref == null ? null : ref.get();
47                if (dict != null) {
48                    if (DEBUG) {
49                        Log.w(TAG, "Use cached UserHistoryDictionary for " + locale);
50                    }
51                    dict.reloadDictionaryIfRequired();
52                    return dict;
53                }
54            }
55            final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale);
56            sLangUserHistoryDictCache.put(localeStr,
57                    new SoftReference<UserHistoryDictionary>(dict));
58            return dict;
59        }
60    }
61
62    public static void tryDecayingAllOpeningUserHistoryDictionary() {
63        for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry
64                : sLangUserHistoryDictCache.entrySet()) {
65            if (entry.getValue() != null) {
66                final UserHistoryDictionary dict = entry.getValue().get();
67                if (dict != null) {
68                    dict.decayIfNeeded();
69                }
70            }
71        }
72    }
73
74    public static PersonalizationDictionary getPersonalizationDictionary(
75            final Context context, final Locale locale) {
76        final String localeStr = locale.toString();
77        synchronized (sLangPersonalizationDictCache) {
78            if (sLangPersonalizationDictCache.containsKey(localeStr)) {
79                final SoftReference<PersonalizationDictionary> ref =
80                        sLangPersonalizationDictCache.get(localeStr);
81                final PersonalizationDictionary dict = ref == null ? null : ref.get();
82                if (dict != null) {
83                    if (DEBUG) {
84                        Log.w(TAG, "Use cached PersonalizationDictionary for " + locale);
85                    }
86                    return dict;
87                }
88            }
89            final PersonalizationDictionary dict = new PersonalizationDictionary(context, locale);
90            sLangPersonalizationDictCache.put(
91                    localeStr, new SoftReference<PersonalizationDictionary>(dict));
92            return dict;
93        }
94    }
95
96    public static void removeAllPersonalizationDictionaries(final Context context) {
97        removeAllDictionaries(context, sLangPersonalizationDictCache,
98                PersonalizationDictionary.NAME);
99    }
100
101    public static void removeAllUserHistoryDictionaries(final Context context) {
102        removeAllDictionaries(context, sLangUserHistoryDictCache,
103                UserHistoryDictionary.NAME);
104    }
105
106    private static <T extends DecayingExpandableBinaryDictionaryBase> void removeAllDictionaries(
107            final Context context, final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap,
108            final String dictNamePrefix) {
109        synchronized (dictionaryMap) {
110            for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry
111                    : dictionaryMap.entrySet()) {
112                if (entry.getValue() != null) {
113                    final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get();
114                    if (dict != null) {
115                        dict.clearAndFlushDictionary();
116                    }
117                }
118            }
119            dictionaryMap.clear();
120            if (!FileUtils.deleteFilteredFiles(
121                    context.getFilesDir(), new DictFilter(dictNamePrefix))) {
122                Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: "
123                        + context.getFilesDir().getAbsolutePath() + ", dictNamePrefix: "
124                        + dictNamePrefix);
125            }
126        }
127    }
128
129    private static class DictFilter implements FilenameFilter {
130        private final String mName;
131
132        DictFilter(final String name) {
133            mName = name;
134        }
135
136        @Override
137        public boolean accept(final File dir, final String name) {
138            return name.startsWith(mName);
139        }
140    }
141}
142