Merge "Dictionary migration in Java side."
This commit is contained in:
commit
781e3df73b
4 changed files with 150 additions and 1 deletions
|
@ -28,9 +28,10 @@ import com.android.inputmethod.latin.makedict.FormatSpec;
|
|||
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
|
||||
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
|
||||
import com.android.inputmethod.latin.makedict.WordProperty;
|
||||
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
|
||||
import com.android.inputmethod.latin.settings.NativeSuggestOptions;
|
||||
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
import com.android.inputmethod.latin.utils.FileUtils;
|
||||
import com.android.inputmethod.latin.utils.JniUtils;
|
||||
import com.android.inputmethod.latin.utils.LanguageModelParam;
|
||||
import com.android.inputmethod.latin.utils.StringUtils;
|
||||
|
@ -81,6 +82,8 @@ public final class BinaryDictionary extends Dictionary {
|
|||
public static final int FORMAT_WORD_PROPERTY_LEVEL_INDEX = 2;
|
||||
public static final int FORMAT_WORD_PROPERTY_COUNT_INDEX = 3;
|
||||
|
||||
public static final String DICT_FILE_NAME_SUFFIX_FOR_MIGRATION = ".migrate";
|
||||
|
||||
private long mNativeDict;
|
||||
private final Locale mLocale;
|
||||
private final long mDictSize;
|
||||
|
@ -458,6 +461,24 @@ public final class BinaryDictionary extends Dictionary {
|
|||
return needsToRunGCNative(mNativeDict, mindsBlockByGC);
|
||||
}
|
||||
|
||||
public boolean migrateTo(final int newFormatVersion) {
|
||||
if (!isValidDictionary()) {
|
||||
return false;
|
||||
}
|
||||
final String tmpDictFilePath = mDictFilePath + DICT_FILE_NAME_SUFFIX_FOR_MIGRATION;
|
||||
// TODO: Implement migrateNative(tmpDictFilePath, newFormatVersion).
|
||||
close();
|
||||
final File dictFile = new File(mDictFilePath);
|
||||
final File tmpDictFile = new File(tmpDictFilePath);
|
||||
FileUtils.deleteRecursively(dictFile);
|
||||
if (!BinaryDictionaryUtils.renameDict(tmpDictFile, dictFile)) {
|
||||
return false;
|
||||
}
|
||||
loadDictionary(dictFile.getAbsolutePath(), 0 /* startOffset */,
|
||||
dictFile.length(), mIsUpdatable);
|
||||
return true;
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public int calculateProbability(final int unigramProbability, final int bigramProbability) {
|
||||
if (!isValidDictionary()) return NOT_A_PROBABILITY;
|
||||
|
|
|
@ -137,6 +137,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
return formatVersion == FormatSpec.VERSION4;
|
||||
}
|
||||
|
||||
private boolean needsToMigrateDictionary(final int formatVersion) {
|
||||
// TODO: Check version.
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isValidDictionaryLocked() {
|
||||
return mBinaryDictionary.isValidDictionary();
|
||||
}
|
||||
|
@ -477,6 +482,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
|||
if (oldBinaryDictionary != null) {
|
||||
oldBinaryDictionary.close();
|
||||
}
|
||||
if (mBinaryDictionary.isValidDictionary()
|
||||
&& needsToMigrateDictionary(mBinaryDictionary.getFormatVersion())) {
|
||||
mBinaryDictionary.migrateTo(DICTIONARY_FORMAT_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class BinaryDictionaryUtils {
|
||||
private static final String TAG = BinaryDictionaryUtils.class.getSimpleName();
|
||||
|
@ -64,6 +66,31 @@ public final class BinaryDictionaryUtils {
|
|||
return header;
|
||||
}
|
||||
|
||||
public static boolean renameDict(final File dictFile, final File newDictFile) {
|
||||
if (dictFile.isFile()) {
|
||||
return dictFile.renameTo(newDictFile);
|
||||
} else if (dictFile.isDirectory()) {
|
||||
final String dictName = dictFile.getName();
|
||||
final String newDictName = newDictFile.getName();
|
||||
if (newDictFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
for (final File file : dictFile.listFiles()) {
|
||||
if (!file.isFile()) {
|
||||
continue;
|
||||
}
|
||||
final String fileName = file.getName();
|
||||
final String newFileName = fileName.replaceFirst(
|
||||
Pattern.quote(dictName), Matcher.quoteReplacement(newDictName));
|
||||
if (!file.renameTo(new File(dictFile, newFileName))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dictFile.renameTo(newDictFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean createEmptyDictFile(final String filePath, final long dictVersion,
|
||||
final Locale locale, final Map<String, String> attributeMap) {
|
||||
final String[] keyArray = new String[attributeMap.size()];
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.utils;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
|
||||
import com.android.inputmethod.latin.BinaryDictionary;
|
||||
import com.android.inputmethod.latin.makedict.DictionaryHeader;
|
||||
import com.android.inputmethod.latin.makedict.FormatSpec;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@LargeTest
|
||||
public class BinaryDictionaryUtilsTests extends AndroidTestCase {
|
||||
private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
|
||||
private static final String TEST_LOCALE = "test";
|
||||
|
||||
private File createEmptyDictionaryAndGetFile(final String dictId,
|
||||
final int formatVersion) throws IOException {
|
||||
if (formatVersion == FormatSpec.VERSION4) {
|
||||
return createEmptyVer4DictionaryAndGetFile(dictId);
|
||||
} else {
|
||||
throw new IOException("Dictionary format version " + formatVersion
|
||||
+ " is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
|
||||
final File file = getDictFile(dictId);
|
||||
FileUtils.deleteRecursively(file);
|
||||
Map<String, String> attributeMap = new HashMap<String, String>();
|
||||
attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId);
|
||||
attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
|
||||
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
|
||||
attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
|
||||
DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
|
||||
attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
|
||||
DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
|
||||
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), FormatSpec.VERSION4,
|
||||
LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
|
||||
return file;
|
||||
} else {
|
||||
throw new IOException("Empty dictionary " + file.getAbsolutePath()
|
||||
+ " cannot be created.");
|
||||
}
|
||||
}
|
||||
|
||||
private File getDictFile(final String dictId) {
|
||||
return new File(getContext().getCacheDir(), dictId + TEST_DICT_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
public void testRenameDictionary() {
|
||||
final int formatVersion = FormatSpec.VERSION4;
|
||||
File dictFile0 = null;
|
||||
try {
|
||||
dictFile0 = createEmptyDictionaryAndGetFile("MoveFromDictionary", formatVersion);
|
||||
} catch (IOException e) {
|
||||
fail("IOException while writing an initial dictionary : " + e);
|
||||
}
|
||||
final File dictFile1 = getDictFile("MoveToDictionary");
|
||||
FileUtils.deleteRecursively(dictFile1);
|
||||
assertTrue(BinaryDictionaryUtils.renameDict(dictFile0, dictFile1));
|
||||
assertFalse(dictFile0.exists());
|
||||
assertTrue(dictFile1.exists());
|
||||
BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile1.getAbsolutePath(),
|
||||
0 /* offset */, dictFile1.length(), true /* useFullEditDistance */,
|
||||
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
|
||||
assertTrue(binaryDictionary.isValidDictionary());
|
||||
assertTrue(binaryDictionary.getFormatVersion() == formatVersion);
|
||||
binaryDictionary.close();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue