• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.inputmethod.latin.makedict;
18 
19 import com.android.inputmethod.annotations.UsedForTesting;
20 import com.android.inputmethod.latin.BinaryDictionary;
21 import com.android.inputmethod.latin.Dictionary;
22 import com.android.inputmethod.latin.NgramContext;
23 import com.android.inputmethod.latin.common.LocaleUtils;
24 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
25 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
26 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
27 
28 import java.io.File;
29 import java.io.IOException;
30 import java.util.HashMap;
31 
32 /**
33  * An implementation of DictEncoder for version 4 binary dictionary.
34  */
35 @UsedForTesting
36 public class Ver4DictEncoder implements DictEncoder {
37     private final File mDictPlacedDir;
38 
39     @UsedForTesting
Ver4DictEncoder(final File dictPlacedDir)40     public Ver4DictEncoder(final File dictPlacedDir) {
41         mDictPlacedDir = dictPlacedDir;
42     }
43 
44     // TODO: This builds a FusionDictionary first and iterates it to add words to the binary
45     // dictionary. However, it is possible to just add words directly to the binary dictionary
46     // instead.
47     // In the long run, when we stop supporting version 2, FusionDictionary will become deprecated
48     // and we can remove it. Then we'll be able to just call BinaryDictionary directly.
49     @Override
writeDictionary(FusionDictionary dict, FormatOptions formatOptions)50     public void writeDictionary(FusionDictionary dict, FormatOptions formatOptions)
51             throws IOException, UnsupportedFormatException {
52         if (formatOptions.mVersion != FormatSpec.VERSION4) {
53             throw new UnsupportedFormatException("File header has a wrong version number : "
54                     + formatOptions.mVersion);
55         }
56         if (!mDictPlacedDir.isDirectory()) {
57             throw new UnsupportedFormatException("Given path is not a directory.");
58         }
59         if (!BinaryDictionaryUtils.createEmptyDictFile(mDictPlacedDir.getAbsolutePath(),
60                 FormatSpec.VERSION4, LocaleUtils.constructLocaleFromString(
61                 dict.mOptions.mAttributes.get(DictionaryHeader.DICTIONARY_LOCALE_KEY)),
62                 dict.mOptions.mAttributes)) {
63             throw new IOException("Cannot create dictionary file : "
64                 + mDictPlacedDir.getAbsolutePath());
65         }
66         final BinaryDictionary binaryDict = new BinaryDictionary(mDictPlacedDir.getAbsolutePath(),
67                 0l, mDictPlacedDir.length(), true /* useFullEditDistance */,
68                 LocaleUtils.constructLocaleFromString(dict.mOptions.mAttributes.get(
69                         DictionaryHeader.DICTIONARY_LOCALE_KEY)),
70                 Dictionary.TYPE_USER /* Dictionary type. Does not matter for us */,
71                 true /* isUpdatable */);
72         if (!binaryDict.isValidDictionary()) {
73             // Somehow createEmptyDictFile returned true, but the file was not created correctly
74             throw new IOException("Cannot create dictionary file");
75         }
76         for (final WordProperty wordProperty : dict) {
77             if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
78                     wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
79                     wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
80                 MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
81             }
82             if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
83                 if (!binaryDict.flushWithGC()) {
84                     MakedictLog.e("Cannot flush dict with GC.");
85                     return;
86                 }
87             }
88         }
89         for (final WordProperty word0Property : dict) {
90             if (!word0Property.mHasNgrams) continue;
91             // TODO: Support ngram.
92             for (final WeightedString word1 : word0Property.getBigrams()) {
93                 final NgramContext ngramContext =
94                         new NgramContext(new NgramContext.WordInfo(word0Property.mWord));
95                 if (!binaryDict.addNgramEntry(ngramContext, word1.mWord,
96                         word1.getProbability(), 0 /* timestamp */)) {
97                     MakedictLog.e("Cannot add n-gram entry for "
98                             + ngramContext + " -> " + word1.mWord);
99                     return;
100                 }
101                 if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
102                     if (!binaryDict.flushWithGC()) {
103                         MakedictLog.e("Cannot flush dict with GC.");
104                         return;
105                     }
106                 }
107             }
108         }
109         if (!binaryDict.flushWithGC()) {
110             MakedictLog.e("Cannot flush dict with GC.");
111             return;
112         }
113         binaryDict.close();
114     }
115 
116     @Override
setPosition(int position)117     public void setPosition(int position) {
118     }
119 
120     @Override
getPosition()121     public int getPosition() {
122         return 0;
123     }
124 
125     @Override
writePtNodeCount(int ptNodeCount)126     public void writePtNodeCount(int ptNodeCount) {
127     }
128 
129     @Override
writePtNode(PtNode ptNode, FusionDictionary dict, HashMap<Integer, Integer> codePointToOneByteCodeMap)130     public void writePtNode(PtNode ptNode, FusionDictionary dict,
131             HashMap<Integer, Integer> codePointToOneByteCodeMap) {
132     }
133 }
134