1 /* 2 * Copyright (C) 2010 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 17 package com.example.android.searchabledict; 18 19 import android.app.SearchManager; 20 import android.content.ContentProvider; 21 import android.content.ContentResolver; 22 import android.content.ContentValues; 23 import android.content.UriMatcher; 24 import android.database.Cursor; 25 import android.net.Uri; 26 import android.provider.BaseColumns; 27 28 /** 29 * Provides access to the dictionary database. 30 */ 31 public class DictionaryProvider extends ContentProvider { 32 String TAG = "DictionaryProvider"; 33 34 public static String AUTHORITY = "com.example.android.searchabledict.DictionaryProvider"; 35 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/dictionary"); 36 37 // MIME types used for searching words or looking up a single definition 38 public static final String WORDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + 39 "/vnd.example.android.searchabledict"; 40 public static final String DEFINITION_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + 41 "/vnd.example.android.searchabledict"; 42 43 private DictionaryDatabase mDictionary; 44 45 // UriMatcher stuff 46 private static final int SEARCH_WORDS = 0; 47 private static final int GET_WORD = 1; 48 private static final int SEARCH_SUGGEST = 2; 49 private static final int REFRESH_SHORTCUT = 3; 50 private static final UriMatcher sURIMatcher = buildUriMatcher(); 51 52 /** 53 * Builds up a UriMatcher for search suggestion and shortcut refresh queries. 54 */ 55 private static UriMatcher buildUriMatcher() { 56 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 57 // to get definitions... 58 matcher.addURI(AUTHORITY, "dictionary", SEARCH_WORDS); 59 matcher.addURI(AUTHORITY, "dictionary/#", GET_WORD); 60 // to get suggestions... 61 matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST); 62 matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST); 63 64 /* The following are unused in this implementation, but if we include 65 * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our suggestions table, we 66 * could expect to receive refresh queries when a shortcutted suggestion is displayed in 67 * Quick Search Box, in which case, the following Uris would be provided and we 68 * would return a cursor with a single item representing the refreshed suggestion data. 69 */ 70 matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, REFRESH_SHORTCUT); 71 matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", REFRESH_SHORTCUT); 72 return matcher; 73 } 74 75 @Override 76 public boolean onCreate() { 77 mDictionary = new DictionaryDatabase(getContext()); 78 return true; 79 } 80 81 /** 82 * Handles all the dictionary searches and suggestion queries from the Search Manager. 83 * When requesting a specific word, the uri alone is required. 84 * When searching all of the dictionary for matches, the selectionArgs argument must carry 85 * the search query as the first element. 86 * All other arguments are ignored. 87 */ 88 @Override 89 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 90 String sortOrder) { 91 92 // Use the UriMatcher to see what kind of query we have and format the db query accordingly 93 switch (sURIMatcher.match(uri)) { 94 case SEARCH_SUGGEST: 95 if (selectionArgs == null) { 96 throw new IllegalArgumentException( 97 "selectionArgs must be provided for the Uri: " + uri); 98 } 99 return getSuggestions(selectionArgs[0]); 100 case SEARCH_WORDS: 101 if (selectionArgs == null) { 102 throw new IllegalArgumentException( 103 "selectionArgs must be provided for the Uri: " + uri); 104 } 105 return search(selectionArgs[0]); 106 case GET_WORD: 107 return getWord(uri); 108 case REFRESH_SHORTCUT: 109 return refreshShortcut(uri); 110 default: 111 throw new IllegalArgumentException("Unknown Uri: " + uri); 112 } 113 } 114 115 private Cursor getSuggestions(String query) { 116 query = query.toLowerCase(); 117 String[] columns = new String[] { 118 BaseColumns._ID, 119 DictionaryDatabase.KEY_WORD, 120 DictionaryDatabase.KEY_DEFINITION, 121 /* SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, 122 (only if you want to refresh shortcuts) */ 123 SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID}; 124 125 return mDictionary.getWordMatches(query, columns); 126 } 127 128 private Cursor search(String query) { 129 query = query.toLowerCase(); 130 String[] columns = new String[] { 131 BaseColumns._ID, 132 DictionaryDatabase.KEY_WORD, 133 DictionaryDatabase.KEY_DEFINITION}; 134 135 return mDictionary.getWordMatches(query, columns); 136 } 137 138 private Cursor getWord(Uri uri) { 139 String rowId = uri.getLastPathSegment(); 140 String[] columns = new String[] { 141 DictionaryDatabase.KEY_WORD, 142 DictionaryDatabase.KEY_DEFINITION}; 143 144 return mDictionary.getWord(rowId, columns); 145 } 146 147 private Cursor refreshShortcut(Uri uri) { 148 /* This won't be called with the current implementation, but if we include 149 * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our suggestions table, we 150 * could expect to receive refresh queries when a shortcutted suggestion is displayed in 151 * Quick Search Box. In which case, this method will query the table for the specific 152 * word, using the given item Uri and provide all the columns originally provided with the 153 * suggestion query. 154 */ 155 String rowId = uri.getLastPathSegment(); 156 String[] columns = new String[] { 157 BaseColumns._ID, 158 DictionaryDatabase.KEY_WORD, 159 DictionaryDatabase.KEY_DEFINITION, 160 SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, 161 SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID}; 162 163 return mDictionary.getWord(rowId, columns); 164 } 165 166 /** 167 * This method is required in order to query the supported types. 168 * It's also useful in our own query() method to determine the type of Uri received. 169 */ 170 @Override 171 public String getType(Uri uri) { 172 switch (sURIMatcher.match(uri)) { 173 case SEARCH_WORDS: 174 return WORDS_MIME_TYPE; 175 case GET_WORD: 176 return DEFINITION_MIME_TYPE; 177 case SEARCH_SUGGEST: 178 return SearchManager.SUGGEST_MIME_TYPE; 179 case REFRESH_SHORTCUT: 180 return SearchManager.SHORTCUT_MIME_TYPE; 181 default: 182 throw new IllegalArgumentException("Unknown URL " + uri); 183 } 184 } 185 186 // Other required implementations... 187 188 @Override 189 public Uri insert(Uri uri, ContentValues values) { 190 throw new UnsupportedOperationException(); 191 } 192 193 @Override 194 public int delete(Uri uri, String selection, String[] selectionArgs) { 195 throw new UnsupportedOperationException(); 196 } 197 198 @Override 199 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 200 throw new UnsupportedOperationException(); 201 } 202 203 } 204