1 | /* |
2 | * Copyright (C) 2007 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.notepad; |
18 | |
19 | import com.example.android.notepad.NotePad.NoteColumns; |
20 | |
21 | import android.content.ContentProvider; |
22 | import android.content.ContentUris; |
23 | import android.content.ContentValues; |
24 | import android.content.Context; |
25 | import android.content.UriMatcher; |
26 | import android.content.res.Resources; |
27 | import android.database.Cursor; |
28 | import android.database.SQLException; |
29 | import android.database.sqlite.SQLiteDatabase; |
30 | import android.database.sqlite.SQLiteOpenHelper; |
31 | import android.database.sqlite.SQLiteQueryBuilder; |
32 | import android.net.Uri; |
33 | import android.provider.BaseColumns; |
34 | import android.provider.LiveFolders; |
35 | import android.text.TextUtils; |
36 | import android.util.Log; |
37 | |
38 | import java.util.HashMap; |
39 | |
40 | /** |
41 | * Provides access to a database of notes. Each note has a title, the note |
42 | * itself, a creation date and a modified data. |
43 | */ |
44 | public class NotePadProvider extends ContentProvider { |
45 | |
46 | private static final String TAG = "NotePadProvider"; |
47 | |
48 | private static final String DATABASE_NAME = "notepad.db"; |
49 | private static final int DATABASE_VERSION = 2; |
50 | private static final String NOTES_TABLE_NAME = "notes"; |
51 | |
52 | private static HashMap<String, String> sNotesProjectionMap; |
53 | private static HashMap<String, String> sLiveFolderProjectionMap; |
54 | |
55 | private static final int NOTES = 1; |
56 | private static final int NOTE_ID = 2; |
57 | private static final int LIVE_FOLDER_NOTES = 3; |
58 | |
59 | private static final UriMatcher sUriMatcher; |
60 | |
61 | /** |
62 | * This class helps open, create, and upgrade the database file. |
63 | */ |
64 | private static class DatabaseHelper extends SQLiteOpenHelper { |
65 | |
66 | DatabaseHelper(Context context) { |
67 | super(context, DATABASE_NAME, null, DATABASE_VERSION); |
68 | } |
69 | |
70 | @Override |
71 | public void onCreate(SQLiteDatabase db) { |
72 | db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " (" |
73 | + BaseColumns._ID + " INTEGER PRIMARY KEY," |
74 | + NoteColumns.TITLE + " TEXT," |
75 | + NoteColumns.NOTE + " TEXT," |
76 | + NoteColumns.CREATED_DATE + " INTEGER," |
77 | + NoteColumns.MODIFIED_DATE + " INTEGER" |
78 | + ");"); |
79 | } |
80 | |
81 | @Override |
82 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
83 | Log.w(TAG, "Upgrading database from version " + oldVersion + " to " |
84 | + newVersion + ", which will destroy all old data"); |
85 | db.execSQL("DROP TABLE IF EXISTS notes"); |
86 | onCreate(db); |
87 | } |
88 | } |
89 | |
90 | private DatabaseHelper mOpenHelper; |
91 | |
92 | @Override |
93 | public boolean onCreate() { |
94 | mOpenHelper = new DatabaseHelper(getContext()); |
95 | return true; |
96 | } |
97 | |
98 | @Override |
99 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, |
100 | String sortOrder) { |
101 | SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); |
102 | qb.setTables(NOTES_TABLE_NAME); |
103 | |
104 | switch (sUriMatcher.match(uri)) { |
105 | case NOTES: |
106 | qb.setProjectionMap(sNotesProjectionMap); |
107 | break; |
108 | |
109 | case NOTE_ID: |
110 | qb.setProjectionMap(sNotesProjectionMap); |
111 | qb.appendWhere(BaseColumns._ID + "=" + uri.getPathSegments().get(1)); |
112 | break; |
113 | |
114 | case LIVE_FOLDER_NOTES: |
115 | qb.setProjectionMap(sLiveFolderProjectionMap); |
116 | break; |
117 | |
118 | default: |
119 | throw new IllegalArgumentException("Unknown URI " + uri); |
120 | } |
121 | |
122 | // If no sort order is specified use the default |
123 | String orderBy; |
124 | if (TextUtils.isEmpty(sortOrder)) { |
125 | orderBy = NoteColumns.DEFAULT_SORT_ORDER; |
126 | } else { |
127 | orderBy = sortOrder; |
128 | } |
129 | |
130 | // Get the database and run the query |
131 | SQLiteDatabase db = mOpenHelper.getReadableDatabase(); |
132 | Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); |
133 | |
134 | // Tell the cursor what uri to watch, so it knows when its source data changes |
135 | c.setNotificationUri(getContext().getContentResolver(), uri); |
136 | return c; |
137 | } |
138 | |
139 | @Override |
140 | public String getType(Uri uri) { |
141 | switch (sUriMatcher.match(uri)) { |
142 | case NOTES: |
143 | case LIVE_FOLDER_NOTES: |
144 | return NoteColumns.CONTENT_TYPE; |
145 | |
146 | case NOTE_ID: |
147 | return NoteColumns.CONTENT_ITEM_TYPE; |
148 | |
149 | default: |
150 | throw new IllegalArgumentException("Unknown URI " + uri); |
151 | } |
152 | } |
153 | |
154 | @Override |
155 | public Uri insert(Uri uri, ContentValues initialValues) { |
156 | // Validate the requested uri |
157 | if (sUriMatcher.match(uri) != NOTES) { |
158 | throw new IllegalArgumentException("Unknown URI " + uri); |
159 | } |
160 | |
161 | ContentValues values; |
162 | if (initialValues != null) { |
163 | values = new ContentValues(initialValues); |
164 | } else { |
165 | values = new ContentValues(); |
166 | } |
167 | |
168 | Long now = Long.valueOf(System.currentTimeMillis()); |
169 | |
170 | // Make sure that the fields are all set |
171 | if (values.containsKey(NoteColumns.CREATED_DATE) == false) { |
172 | values.put(NoteColumns.CREATED_DATE, now); |
173 | } |
174 | |
175 | if (values.containsKey(NoteColumns.MODIFIED_DATE) == false) { |
176 | values.put(NoteColumns.MODIFIED_DATE, now); |
177 | } |
178 | |
179 | if (values.containsKey(NoteColumns.TITLE) == false) { |
180 | Resources r = Resources.getSystem(); |
181 | values.put(NoteColumns.TITLE, r.getString(android.R.string.untitled)); |
182 | } |
183 | |
184 | if (values.containsKey(NoteColumns.NOTE) == false) { |
185 | values.put(NoteColumns.NOTE, ""); |
186 | } |
187 | |
188 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
189 | long rowId = db.insert(NOTES_TABLE_NAME, NoteColumns.NOTE, values); |
190 | if (rowId > 0) { |
191 | Uri noteUri = ContentUris.withAppendedId(NoteColumns.CONTENT_URI, rowId); |
192 | getContext().getContentResolver().notifyChange(noteUri, null); |
193 | return noteUri; |
194 | } |
195 | |
196 | throw new SQLException("Failed to insert row into " + uri); |
197 | } |
198 | |
199 | @Override |
200 | public int delete(Uri uri, String where, String[] whereArgs) { |
201 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
202 | int count; |
203 | switch (sUriMatcher.match(uri)) { |
204 | case NOTES: |
205 | count = db.delete(NOTES_TABLE_NAME, where, whereArgs); |
206 | break; |
207 | |
208 | case NOTE_ID: |
209 | String noteId = uri.getPathSegments().get(1); |
210 | count = db.delete(NOTES_TABLE_NAME, BaseColumns._ID + "=" + noteId |
211 | + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); |
212 | break; |
213 | |
214 | default: |
215 | throw new IllegalArgumentException("Unknown URI " + uri); |
216 | } |
217 | |
218 | getContext().getContentResolver().notifyChange(uri, null); |
219 | return count; |
220 | } |
221 | |
222 | @Override |
223 | public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { |
224 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
225 | int count; |
226 | switch (sUriMatcher.match(uri)) { |
227 | case NOTES: |
228 | count = db.update(NOTES_TABLE_NAME, values, where, whereArgs); |
229 | break; |
230 | |
231 | case NOTE_ID: |
232 | String noteId = uri.getPathSegments().get(1); |
233 | count = db.update(NOTES_TABLE_NAME, values, BaseColumns._ID + "=" + noteId |
234 | + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); |
235 | break; |
236 | |
237 | default: |
238 | throw new IllegalArgumentException("Unknown URI " + uri); |
239 | } |
240 | |
241 | getContext().getContentResolver().notifyChange(uri, null); |
242 | return count; |
243 | } |
244 | |
245 | static { |
246 | sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); |
247 | sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES); |
248 | sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID); |
249 | sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES); |
250 | |
251 | sNotesProjectionMap = new HashMap<String, String>(); |
252 | sNotesProjectionMap.put(BaseColumns._ID, BaseColumns._ID); |
253 | sNotesProjectionMap.put(NoteColumns.TITLE, NoteColumns.TITLE); |
254 | sNotesProjectionMap.put(NoteColumns.NOTE, NoteColumns.NOTE); |
255 | sNotesProjectionMap.put(NoteColumns.CREATED_DATE, NoteColumns.CREATED_DATE); |
256 | sNotesProjectionMap.put(NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE); |
257 | |
258 | // Support for Live Folders. |
259 | sLiveFolderProjectionMap = new HashMap<String, String>(); |
260 | sLiveFolderProjectionMap.put(BaseColumns._ID, BaseColumns._ID + " AS " + |
261 | BaseColumns._ID); |
262 | sLiveFolderProjectionMap.put(LiveFolders.NAME, NoteColumns.TITLE + " AS " + |
263 | LiveFolders.NAME); |
264 | // Add more columns here for more robust Live Folders. |
265 | } |
266 | } |