Merge "Change the dictionary file passing schema to a list of ids"

This commit is contained in:
Jean Chalard 2011-08-02 21:02:11 -07:00 committed by Android (Google) Code Review
commit 81f227de5a
2 changed files with 72 additions and 37 deletions

View file

@ -20,8 +20,10 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -29,7 +31,8 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -43,6 +46,8 @@ public class BinaryDictionaryFileDumper {
*/ */
static final int FILE_READ_BUFFER_SIZE = 1024; static final int FILE_READ_BUFFER_SIZE = 1024;
private static final String DICTIONARY_PROJECTION[] = { "id" };
// Prevents this class to be accidentally instantiated. // Prevents this class to be accidentally instantiated.
private BinaryDictionaryFileDumper() { private BinaryDictionaryFileDumper() {
} }
@ -75,12 +80,47 @@ public class BinaryDictionaryFileDumper {
/** /**
* Return for a given locale the provider URI to query to get the dictionary. * Return for a given locale the provider URI to query to get the dictionary.
*/ */
// TODO: remove this
public static Uri getProviderUri(Locale locale) { public static Uri getProviderUri(Locale locale) {
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath( .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
locale.toString()).build(); locale.toString()).build();
} }
/**
* Return for a given locale or dictionary id the provider URI to get the dictionary.
*/
private static Uri getProviderUri(String path) {
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
.authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
path).build();
}
/**
* Queries a content provider for the list of dictionaries for a specific locale
* available to copy into Latin IME.
*/
private static List<String> getDictIdList(final Locale locale, final Context context) {
final ContentResolver resolver = context.getContentResolver();
final Uri dictionaryPackUri = getProviderUri(locale);
final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null);
if (null == c) return Collections.<String>emptyList();
if (c.getCount() <= 0 || !c.moveToFirst()) {
c.close();
return Collections.<String>emptyList();
}
final List<String> list = new ArrayList<String>();
do {
final String id = c.getString(0);
if (TextUtils.isEmpty(id)) continue;
list.add(id);
} while (c.moveToNext());
c.close();
return list;
}
/** /**
* Queries a content provider for dictionary data for some locale and returns the file addresses * Queries a content provider for dictionary data for some locale and returns the file addresses
* *
@ -95,20 +135,26 @@ public class BinaryDictionaryFileDumper {
* @throw FileNotFoundException if the provider returns non-existent data. * @throw FileNotFoundException if the provider returns non-existent data.
* @throw IOException if the provider-returned data could not be read. * @throw IOException if the provider-returned data could not be read.
*/ */
public static List<AssetFileAddress> getDictSetFromContentProvider(Locale locale, public static List<AssetFileAddress> getDictSetFromContentProvider(final Locale locale,
Context context) throws FileNotFoundException, IOException { final Context context) throws FileNotFoundException, IOException {
// TODO: check whether the dictionary is the same or not and if it is, return the cached // TODO: check whether the dictionary is the same or not and if it is, return the cached
// file. // file.
// TODO: This should be able to read a number of files from the dictionary pack, copy // TODO: This should be able to read a number of files from the dictionary pack, copy
// them all and return them. // them all and return them.
final ContentResolver resolver = context.getContentResolver(); final ContentResolver resolver = context.getContentResolver();
final Uri dictionaryPackUri = getProviderUri(locale); final List<String> idList = getDictIdList(locale, context);
final AssetFileDescriptor afd = resolver.openAssetFileDescriptor(dictionaryPackUri, "r"); final List<AssetFileAddress> fileAddressList = new ArrayList<AssetFileAddress>();
if (null == afd) return null; for (String id : idList) {
final String fileName = final Uri dictionaryPackUri = getProviderUri(id);
copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context)); final AssetFileDescriptor afd =
afd.close(); resolver.openAssetFileDescriptor(dictionaryPackUri, "r");
return Arrays.asList(AssetFileAddress.makeFromFileName(fileName)); if (null == afd) continue;
final String fileName =
copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
afd.close();
fileAddressList.add(AssetFileAddress.makeFromFileName(fileName));
}
return fileAddressList;
} }
/** /**

View file

@ -63,9 +63,6 @@ class BinaryDictionaryGetter {
* Returns a list of file addresses for a given locale, trying relevant methods in order. * Returns a list of file addresses for a given locale, trying relevant methods in order.
* *
* Tries to get binary dictionaries from various sources, in order: * Tries to get binary dictionaries from various sources, in order:
* - Uses a private method of getting a private dictionaries, as implemented by the
* PrivateBinaryDictionaryGetter class.
* If that fails:
* - Uses a content provider to get a public dictionary set, as per the protocol described * - Uses a content provider to get a public dictionary set, as per the protocol described
* in BinaryDictionaryFileDumper. * in BinaryDictionaryFileDumper.
* If that fails: * If that fails:
@ -76,31 +73,23 @@ class BinaryDictionaryGetter {
*/ */
public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context, public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
int fallbackResId) { int fallbackResId) {
// Try first to query a private package signed the same way for private files. try {
final List<AssetFileAddress> privateFiles = List<AssetFileAddress> listFromContentProvider =
PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context); BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
if (null != privateFiles) { if (null != listFromContentProvider) {
return privateFiles; return listFromContentProvider;
} else {
try {
// If that was no-go, try to find a publicly exported dictionary.
List<AssetFileAddress> listFromContentProvider =
BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
if (null != listFromContentProvider) {
return listFromContentProvider;
}
// If the list is null, fall through and return the fallback
} catch (FileNotFoundException e) {
Log.e(TAG, "Unable to create dictionary file from provider for locale "
+ locale.toString() + ": falling back to internal dictionary");
} catch (IOException e) {
Log.e(TAG, "Unable to read source data for locale "
+ locale.toString() + ": falling back to internal dictionary");
} }
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId, // If the list is null, fall through and return the fallback
locale); } catch (FileNotFoundException e) {
if (null == fallbackAsset) return null; Log.e(TAG, "Unable to create dictionary file from provider for locale "
return Arrays.asList(fallbackAsset); + locale.toString() + ": falling back to internal dictionary");
} catch (IOException e) {
Log.e(TAG, "Unable to read source data for locale "
+ locale.toString() + ": falling back to internal dictionary");
} }
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
locale);
if (null == fallbackAsset) return null;
return Arrays.asList(fallbackAsset);
} }
} }