1bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka/* 2bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * Copyright (C) 2012 The Android Open Source Project 3bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * 4bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 5bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * you may not use this file except in compliance with the License. 6bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * You may obtain a copy of the License at 7bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * 8bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 9bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * 10bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * Unless required by applicable law or agreed to in writing, software 11bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 12bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * See the License for the specific language governing permissions and 14bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * limitations under the License. 15bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka */ 16bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 17ffcbbaf12788a9fc9398607a548e552d7d2bf05eSatoshi Kataokapackage com.android.inputmethod.latin.personalization; 18bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 19bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataokaimport android.util.Log; 20bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 21b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasaimport com.android.inputmethod.annotations.UsedForTesting; 22e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CollectionUtils; 23b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa 24bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataokaimport java.util.HashMap; 25bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataokaimport java.util.Set; 26bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 27bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka/** 28bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * A store of bigrams which will be updated when the user history dictionary is closed 29bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale 30bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka * bigrams when we write to the SQL DB. 31bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka */ 32b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa@UsedForTesting 33a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class UserHistoryDictionaryBigramList { 34a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0; 35bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName(); 365f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka private static final HashMap<String, Byte> EMPTY_BIGRAM_MAP = CollectionUtils.newHashMap(); 375f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka private final HashMap<String, HashMap<String, Byte>> mBigramMap = CollectionUtils.newHashMap(); 38bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka private int mSize = 0; 39bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 40bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public void evictAll() { 41bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka mSize = 0; 42bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka mBigramMap.clear(); 43bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 44bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 45a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka /** 46a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka * Called when the user typed a word. 47a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka */ 486e04d6593239e841f5dac0d3f32d613967c11e22Keisuke Kuroyanagi @UsedForTesting 49bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public void addBigram(String word1, String word2) { 50a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka addBigram(word1, word2, FORGETTING_CURVE_INITIAL_VALUE); 51a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka } 52a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka 53a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka /** 54a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka * Called when loaded from the SQL DB. 55a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka */ 56a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka public void addBigram(String word1, String word2, byte fcValue) { 575ef6209656c51df0f0542d2a75c2df93c8d0f027Keisuke Kuroyanagi if (DecayingExpandableBinaryDictionaryBase.DBG_SAVE_RESTORE) { 58a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka Log.d(TAG, "--- add bigram: " + word1 + ", " + word2 + ", " + fcValue); 59bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 60a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka final HashMap<String, Byte> map; 61bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka if (mBigramMap.containsKey(word1)) { 62a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka map = mBigramMap.get(word1); 63bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } else { 645f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka map = CollectionUtils.newHashMap(); 65a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka mBigramMap.put(word1, map); 66bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 67a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka if (!map.containsKey(word2)) { 68bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka ++mSize; 69a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka map.put(word2, fcValue); 70bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 71bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 72bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 73a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka /** 74a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka * Called when inserted to the SQL DB. 75a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka */ 76a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka public void updateBigram(String word1, String word2, byte fcValue) { 775ef6209656c51df0f0542d2a75c2df93c8d0f027Keisuke Kuroyanagi if (DecayingExpandableBinaryDictionaryBase.DBG_SAVE_RESTORE) { 78a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka Log.d(TAG, "--- update bigram: " + word1 + ", " + word2 + ", " + fcValue); 79a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka } 80a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka final HashMap<String, Byte> map; 81a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka if (mBigramMap.containsKey(word1)) { 82a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka map = mBigramMap.get(word1); 83a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka } else { 84a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka return; 85a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka } 86a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka if (!map.containsKey(word2)) { 87a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka return; 88a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka } 89a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka map.put(word2, fcValue); 90a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka } 91a836808f8b6b4cf3d5ff2cf93f079763fca86abbSatoshi Kataoka 92bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public int size() { 93bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return mSize; 94bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 95bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 96bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public boolean isEmpty() { 97bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return mBigramMap.isEmpty(); 98bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 99bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 100e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka public boolean containsKey(String word) { 101e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka return mBigramMap.containsKey(word); 102e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka } 103e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka 104bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public Set<String> keySet() { 105bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return mBigramMap.keySet(); 106bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 107bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 108a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka public HashMap<String, Byte> getBigrams(String word1) { 109e9a86e2cdb58dd8d5601138294521e966d164520Jean Chalard if (mBigramMap.containsKey(word1)) return mBigramMap.get(word1); 110e9a86e2cdb58dd8d5601138294521e966d164520Jean Chalard // TODO: lower case according to locale 111e9a86e2cdb58dd8d5601138294521e966d164520Jean Chalard final String lowerWord1 = word1.toLowerCase(); 112e9a86e2cdb58dd8d5601138294521e966d164520Jean Chalard if (mBigramMap.containsKey(lowerWord1)) return mBigramMap.get(lowerWord1); 113e9a86e2cdb58dd8d5601138294521e966d164520Jean Chalard return EMPTY_BIGRAM_MAP; 114bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 115bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka 116bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka public boolean removeBigram(String word1, String word2) { 117a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka final HashMap<String, Byte> set = getBigrams(word1); 118bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka if (set.isEmpty()) { 119bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return false; 120bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 121a8c13e7942ed88f58b534f2f853dafb804a72894Satoshi Kataoka if (set.containsKey(word2)) { 122bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka set.remove(word2); 123bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka --mSize; 124bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return true; 125bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 126bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka return false; 127bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka } 128bc5688506229bd5cd5e6f4dcdc73c21dc6b80ecbSatoshi Kataoka} 129