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