/* * Copyright (C) 2010 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 tof.cv.search; import java.util.HashMap; import android.app.SearchManager; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteQueryBuilder; import android.provider.BaseColumns; /** * Contains logic to return specific words from the dictionary, and load the * dictionary table when it needs to be created. */ public class SearchDatabase { // The columns we'll include in the dictionary table public static final String KEY_ITEM = SearchManager.SUGGEST_COLUMN_TEXT_1; public static final String KEY_TYPE = SearchManager.SUGGEST_COLUMN_TEXT_2; private static final String FTS_VIRTUAL_TABLE = "FTSdictionary"; private final SearchDatabaseHelper mDatabaseOpenHelper; private final HashMap<String, String> mColumnMap = buildColumnMap(); /** * Constructor * * @param context * The Context within which to work, used to create the DB */ public SearchDatabase(Context context) { mDatabaseOpenHelper = new SearchDatabaseHelper(context); } /** * Builds a map for all columns that may be requested, which will be given * to the SQLiteQueryBuilder. This is a good way to define aliases for * column names, but must include all columns, even if the value is the key. * This allows the ContentProvider to request columns w/o the need to know * real column names and create the alias itself. */ private HashMap<String, String> buildColumnMap() { HashMap<String, String> map = new HashMap<String, String>(); map.put(KEY_ITEM, KEY_ITEM); map.put(KEY_TYPE, KEY_TYPE); map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID); map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID); return map; } /** * Returns a Cursor positioned at the word specified by rowId * * @param rowId * id of word to retrieve * @param columns * The columns to include, if null then all are included * @return Cursor positioned to matching word, or null if not found. */ public Cursor getItem(String rowId, String[] columns) { String selection = "rowid = ?"; String[] selectionArgs = new String[] { rowId }; return query(selection, selectionArgs, columns); /* * This builds a query that looks like: SELECT <columns> FROM <table> * WHERE rowid = <rowId> */ } /** * Returns a Cursor over all words that match the given query * * @param query * The string to search for * @param columns * The columns to include, if null then all are included * @return Cursor over all words that match, or null if none found. */ public Cursor getItemMatches(String query, String[] columns) { String selection = KEY_ITEM + " MATCH ?"; String[] selectionArgs = new String[] { query + "*" }; return query(selection, selectionArgs, columns); /* * This builds a query that looks like: SELECT <columns> FROM <table> * WHERE <KEY_WORD> MATCH 'query*' which is an FTS3 search for the query * text (plus a wildcard) inside the word column. * * - "rowid" is the unique id for all rows but we need this value for * the "_id" column in order for the Adapters to work, so the columns * need to make "_id" an alias for "rowid" - "rowid" also needs to be * used by the SUGGEST_COLUMN_INTENT_DATA alias in order for suggestions * to carry the proper intent data. These aliases are defined in the * DictionaryProvider when queries are made. - This can be revised to * also search the definition text with FTS3 by changing the selection * clause to use FTS_VIRTUAL_TABLE instead of KEY_WORD (to search across * the entire table, but sorting the relevance could be difficult. */ } /** * Performs a database query. * * @param selection * The selection clause * @param selectionArgs * Selection arguments for "?" components in the selection * @param columns * The columns to return * @return A Cursor over all rows matching the query */ private Cursor query(String selection, String[] selectionArgs, String[] columns) { /* * The SQLiteBuilder provides a map for all possible columns requested * to actual columns in the database, creating a simple column alias * mechanism by which the ContentProvider does not need to know the real * column names */ SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); builder.setTables(FTS_VIRTUAL_TABLE); builder.setProjectionMap(mColumnMap); Cursor cursor = builder.query( mDatabaseOpenHelper.getReadableDatabase(), columns, selection, selectionArgs, null, null, null); if (cursor == null) { return null; } else if (!cursor.moveToFirst()) { cursor.close(); return null; } return cursor; } }