• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.android.providers.userdictionary;
18 
19 
20 import java.util.HashMap;
21 
22 import android.app.backup.BackupManager;
23 import android.content.ContentProvider;
24 import android.content.ContentUris;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.UriMatcher;
28 import android.database.Cursor;
29 import android.database.SQLException;
30 import android.database.sqlite.SQLiteDatabase;
31 import android.database.sqlite.SQLiteOpenHelper;
32 import android.database.sqlite.SQLiteQueryBuilder;
33 import android.net.Uri;
34 import android.provider.UserDictionary;
35 import android.provider.UserDictionary.Words;
36 import android.text.TextUtils;
37 import android.util.Log;
38 
39 /**
40  * Provides access to a database of user defined words. Each item has a word and a frequency.
41  */
42 public class UserDictionaryProvider extends ContentProvider {
43 
44     /**
45      * DB versions are as follow:
46      *
47      * Version 1:
48      *   Up to IceCreamSandwich 4.0.3 - API version 15
49      *   Contient ID (INTEGER PRIMARY KEY), WORD (TEXT), FREQUENCY (INTEGER),
50      *   LOCALE (TEXT), APP_ID (INTEGER).
51      *
52      * Version 2:
53      *   From IceCreamSandwich, 4.1 - API version 16
54      *   Adds SHORTCUT (TEXT).
55      */
56 
57     private static final String AUTHORITY = UserDictionary.AUTHORITY;
58 
59     private static final String TAG = "UserDictionaryProvider";
60 
61     private static final Uri CONTENT_URI = UserDictionary.CONTENT_URI;
62 
63     private static final String DATABASE_NAME = "user_dict.db";
64     private static final int DATABASE_VERSION = 2;
65 
66     private static final String USERDICT_TABLE_NAME = "words";
67 
68     private static HashMap<String, String> sDictProjectionMap;
69 
70     private static final UriMatcher sUriMatcher;
71 
72     private static final int WORDS = 1;
73 
74     private static final int WORD_ID = 2;
75 
76     private BackupManager mBackupManager;
77 
78     /**
79      * This class helps open, create, and upgrade the database file.
80      */
81     private static class DatabaseHelper extends SQLiteOpenHelper {
82 
DatabaseHelper(Context context)83         DatabaseHelper(Context context) {
84             super(context, DATABASE_NAME, null, DATABASE_VERSION);
85         }
86 
87         @Override
onCreate(SQLiteDatabase db)88         public void onCreate(SQLiteDatabase db) {
89             db.execSQL("CREATE TABLE " + USERDICT_TABLE_NAME + " ("
90                     + Words._ID + " INTEGER PRIMARY KEY,"
91                     + Words.WORD + " TEXT,"
92                     + Words.FREQUENCY + " INTEGER,"
93                     + Words.LOCALE + " TEXT,"
94                     + Words.APP_ID + " INTEGER,"
95                     + Words.SHORTCUT + " TEXT"
96                     + ");");
97         }
98 
99         @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)100         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
101             if (oldVersion == 1 && newVersion == 2) {
102                 Log.i(TAG, "Upgrading database from version " + oldVersion
103                         + " to version 2: adding " + Words.SHORTCUT + " column");
104                 db.execSQL("ALTER TABLE " + USERDICT_TABLE_NAME
105                         + " ADD " + Words.SHORTCUT + " TEXT;");
106             } else {
107                 Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
108                         + newVersion + ", which will destroy all old data");
109                 db.execSQL("DROP TABLE IF EXISTS " + USERDICT_TABLE_NAME);
110                 onCreate(db);
111             }
112         }
113     }
114 
115     private DatabaseHelper mOpenHelper;
116 
117     @Override
onCreate()118     public boolean onCreate() {
119         mOpenHelper = new DatabaseHelper(getContext());
120         mBackupManager = new BackupManager(getContext());
121         return true;
122     }
123 
124     @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)125     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
126             String sortOrder) {
127         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
128 
129         switch (sUriMatcher.match(uri)) {
130         case WORDS:
131             qb.setTables(USERDICT_TABLE_NAME);
132             qb.setProjectionMap(sDictProjectionMap);
133             break;
134 
135         case WORD_ID:
136             qb.setTables(USERDICT_TABLE_NAME);
137             qb.setProjectionMap(sDictProjectionMap);
138             qb.appendWhere("_id" + "=" + uri.getPathSegments().get(1));
139             break;
140 
141         default:
142             throw new IllegalArgumentException("Unknown URI " + uri);
143         }
144 
145         // If no sort order is specified use the default
146         String orderBy;
147         if (TextUtils.isEmpty(sortOrder)) {
148             orderBy = Words.DEFAULT_SORT_ORDER;
149         } else {
150             orderBy = sortOrder;
151         }
152 
153         // Get the database and run the query
154         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
155         Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
156 
157         // Tell the cursor what uri to watch, so it knows when its source data changes
158         c.setNotificationUri(getContext().getContentResolver(), uri);
159         return c;
160     }
161 
162     @Override
getType(Uri uri)163     public String getType(Uri uri) {
164         switch (sUriMatcher.match(uri)) {
165         case WORDS:
166             return Words.CONTENT_TYPE;
167 
168         case WORD_ID:
169             return Words.CONTENT_ITEM_TYPE;
170 
171         default:
172             throw new IllegalArgumentException("Unknown URI " + uri);
173         }
174     }
175 
176     @Override
insert(Uri uri, ContentValues initialValues)177     public Uri insert(Uri uri, ContentValues initialValues) {
178         // Validate the requested uri
179         if (sUriMatcher.match(uri) != WORDS) {
180             throw new IllegalArgumentException("Unknown URI " + uri);
181         }
182 
183         ContentValues values;
184         if (initialValues != null) {
185             values = new ContentValues(initialValues);
186         } else {
187             values = new ContentValues();
188         }
189 
190         if (values.containsKey(Words.WORD) == false) {
191             throw new SQLException("Word must be specified");
192         }
193 
194         if (values.containsKey(Words.FREQUENCY) == false) {
195             values.put(Words.FREQUENCY, "1");
196         }
197 
198         if (values.containsKey(Words.LOCALE) == false) {
199             values.put(Words.LOCALE, (String) null);
200         }
201 
202         if (values.containsKey(Words.SHORTCUT) == false) {
203             values.put(Words.SHORTCUT, (String) null);
204         }
205 
206         values.put(Words.APP_ID, 0);
207 
208         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
209         long rowId = db.insert(USERDICT_TABLE_NAME, Words.WORD, values);
210         if (rowId > 0) {
211             Uri wordUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI, rowId);
212             getContext().getContentResolver().notifyChange(wordUri, null);
213             mBackupManager.dataChanged();
214             return wordUri;
215         }
216 
217         throw new SQLException("Failed to insert row into " + uri);
218     }
219 
220     @Override
delete(Uri uri, String where, String[] whereArgs)221     public int delete(Uri uri, String where, String[] whereArgs) {
222         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
223         int count;
224         switch (sUriMatcher.match(uri)) {
225         case WORDS:
226             count = db.delete(USERDICT_TABLE_NAME, where, whereArgs);
227             break;
228 
229         case WORD_ID:
230             String wordId = uri.getPathSegments().get(1);
231             count = db.delete(USERDICT_TABLE_NAME, Words._ID + "=" + wordId
232                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
233             break;
234 
235         default:
236             throw new IllegalArgumentException("Unknown URI " + uri);
237         }
238 
239         getContext().getContentResolver().notifyChange(uri, null);
240         mBackupManager.dataChanged();
241         return count;
242     }
243 
244     @Override
update(Uri uri, ContentValues values, String where, String[] whereArgs)245     public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
246         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
247         int count;
248         switch (sUriMatcher.match(uri)) {
249         case WORDS:
250             count = db.update(USERDICT_TABLE_NAME, values, where, whereArgs);
251             break;
252 
253         case WORD_ID:
254             String wordId = uri.getPathSegments().get(1);
255             count = db.update(USERDICT_TABLE_NAME, values, Words._ID + "=" + wordId
256                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
257             break;
258 
259         default:
260             throw new IllegalArgumentException("Unknown URI " + uri);
261         }
262 
263         getContext().getContentResolver().notifyChange(uri, null);
264         mBackupManager.dataChanged();
265         return count;
266     }
267 
268     static {
269         sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, "words", WORDS)270         sUriMatcher.addURI(AUTHORITY, "words", WORDS);
sUriMatcher.addURI(AUTHORITY, "words/#", WORD_ID)271         sUriMatcher.addURI(AUTHORITY, "words/#", WORD_ID);
272 
273         sDictProjectionMap = new HashMap<String, String>();
sDictProjectionMap.put(Words._ID, Words._ID)274         sDictProjectionMap.put(Words._ID, Words._ID);
sDictProjectionMap.put(Words.WORD, Words.WORD)275         sDictProjectionMap.put(Words.WORD, Words.WORD);
sDictProjectionMap.put(Words.FREQUENCY, Words.FREQUENCY)276         sDictProjectionMap.put(Words.FREQUENCY, Words.FREQUENCY);
sDictProjectionMap.put(Words.LOCALE, Words.LOCALE)277         sDictProjectionMap.put(Words.LOCALE, Words.LOCALE);
sDictProjectionMap.put(Words.APP_ID, Words.APP_ID)278         sDictProjectionMap.put(Words.APP_ID, Words.APP_ID);
sDictProjectionMap.put(Words.SHORTCUT, Words.SHORTCUT)279         sDictProjectionMap.put(Words.SHORTCUT, Words.SHORTCUT);
280     }
281 }
282