Ver4DictEncoder.java revision e708b1bc2e11285ad404133b8de21719ce08acb5
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 = 108 new PrevWordsInfo(new PrevWordsInfo.WordInfo(word0Property.mWord)); 109 if (!binaryDict.addNgramEntry(prevWordsInfo, word1.mWord, 110 word1.getProbability(), 0 /* timestamp */)) { 111 MakedictLog.e("Cannot add n-gram entry for " 112 + prevWordsInfo + " -> " + word1.mWord); 113 return; 114 } 115 if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) { 116 if (!binaryDict.flushWithGC()) { 117 MakedictLog.e("Cannot flush dict with GC."); 118 return; 119 } 120 } 121 } 122 } 123 if (!binaryDict.flushWithGC()) { 124 MakedictLog.e("Cannot flush dict with GC."); 125 return; 126 } 127 binaryDict.close(); 128 } 129 130 @Override 131 public void setPosition(int position) { 132 } 133 134 @Override 135 public int getPosition() { 136 return 0; 137 } 138 139 @Override 140 public void writePtNodeCount(int ptNodeCount) { 141 } 142 143 @Override 144 public void writeForwardLinkAddress(int forwardLinkAddress) { 145 } 146 147 @Override 148 public void writePtNode(PtNode ptNode, FusionDictionary dict) { 149 } 150} 151