Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.db;
7 import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
8 import org.mozilla.gecko.sync.Utils;
10 import android.content.ContentUris;
11 import android.content.ContentValues;
12 import android.content.UriMatcher;
13 import android.database.Cursor;
14 import android.database.sqlite.SQLiteDatabase;
15 import android.database.sqlite.SQLiteQueryBuilder;
16 import android.net.Uri;
17 import android.text.TextUtils;
19 public class ReadingListProvider extends SharedBrowserDatabaseProvider {
20 static final String TABLE_READING_LIST = ReadingListItems.TABLE_NAME;
22 static final int ITEMS = 101;
23 static final int ITEMS_ID = 102;
24 static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
26 static {
27 URI_MATCHER.addURI(BrowserContract.READING_LIST_AUTHORITY, "items", ITEMS);
28 URI_MATCHER.addURI(BrowserContract.READING_LIST_AUTHORITY, "items/#", ITEMS_ID);
29 }
31 /**
32 * Updates items that match the selection criteria. If no such items is found
33 * one is inserted with the attributes passed in. Returns 0 if no item updated.
34 *
35 * @return Number of items updated or inserted
36 */
37 public int updateOrInsertItem(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
38 int updated = updateItems(uri, values, selection, selectionArgs);
39 if (updated <= 0) {
40 updated = insertItem(uri, values) != -1 ? 1 : 0;
41 }
42 return updated;
43 }
45 /**
46 * Updates items that match the selection criteria.
47 *
48 * @return Number of items updated or inserted
49 */
50 public int updateItems(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
51 trace("Updating ReadingListItems on URI: " + uri);
52 final SQLiteDatabase db = getWritableDatabase(uri);
53 if (!values.containsKey(ReadingListItems.DATE_MODIFIED)) {
54 values.put(ReadingListItems.DATE_MODIFIED, System.currentTimeMillis());
55 }
56 return db.update(TABLE_READING_LIST, values, selection, selectionArgs);
57 }
59 /**
60 * Inserts a new item into the DB. DATE_CREATED, DATE_MODIFIED
61 * and GUID fields are generated if they are not specified.
62 *
63 * @return ID of the newly inserted item
64 */
65 long insertItem(Uri uri, ContentValues values) {
66 long now = System.currentTimeMillis();
67 if (!values.containsKey(ReadingListItems.DATE_CREATED)) {
68 values.put(ReadingListItems.DATE_CREATED, now);
69 }
71 if (!values.containsKey(ReadingListItems.DATE_MODIFIED)) {
72 values.put(ReadingListItems.DATE_MODIFIED, now);
73 }
75 if (!values.containsKey(ReadingListItems.GUID)) {
76 values.put(ReadingListItems.GUID, Utils.generateGuid());
77 }
79 String url = values.getAsString(ReadingListItems.URL);
80 debug("Inserting item in database with URL: " + url);
81 return getWritableDatabase(uri)
82 .insertOrThrow(TABLE_READING_LIST, null, values);
83 }
85 /**
86 * Deletes items. Item is marked as 'deleted' so that sync can
87 * detect the change.
88 *
89 * @return Number of deleted items
90 */
91 int deleteItems(Uri uri, String selection, String[] selectionArgs) {
92 debug("Deleting item entry for URI: " + uri);
93 final SQLiteDatabase db = getWritableDatabase(uri);
95 if (isCallerSync(uri)) {
96 return db.delete(TABLE_READING_LIST, selection, selectionArgs);
97 }
99 debug("Marking item entry as deleted for URI: " + uri);
100 ContentValues values = new ContentValues();
101 values.put(ReadingListItems.IS_DELETED, 1);
103 cleanUpSomeDeletedRecords(uri, TABLE_READING_LIST);
104 return updateItems(uri, values, selection, selectionArgs);
105 }
107 @Override
108 @SuppressWarnings("fallthrough")
109 public int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
110 trace("Calling update in transaction on URI: " + uri);
112 int updated = 0;
113 int match = URI_MATCHER.match(uri);
115 switch (match) {
116 case ITEMS_ID:
117 debug("Update on ITEMS_ID: " + uri);
118 selection = DBUtils.concatenateWhere(selection, TABLE_READING_LIST + "._id = ?");
119 selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
120 new String[] { Long.toString(ContentUris.parseId(uri)) });
122 case ITEMS: {
123 debug("Updating ITEMS: " + uri);
124 updated = shouldUpdateOrInsert(uri) ?
125 updateOrInsertItem(uri, values, selection, selectionArgs) :
126 updateItems(uri, values, selection, selectionArgs);
127 break;
128 }
130 default:
131 throw new UnsupportedOperationException("Unknown update URI " + uri);
132 }
134 debug("Updated " + updated + " rows for URI: " + uri);
135 return updated;
136 }
139 @Override
140 @SuppressWarnings("fallthrough")
141 public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) {
142 trace("Calling delete in transaction on URI: " + uri);
144 int numDeleted = 0;
145 int match = URI_MATCHER.match(uri);
147 switch (match) {
148 case ITEMS_ID:
149 debug("Deleting on ITEMS_ID: " + uri);
150 selection = DBUtils.concatenateWhere(selection, TABLE_READING_LIST + "._id = ?");
151 selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
152 new String[] { Long.toString(ContentUris.parseId(uri)) });
154 case ITEMS:
155 debug("Deleting ITEMS: " + uri);
156 numDeleted = deleteItems(uri, selection, selectionArgs);
157 break;
159 default:
160 throw new UnsupportedOperationException("Unknown update URI " + uri);
161 }
163 debug("Deleted " + numDeleted + " rows for URI: " + uri);
164 return numDeleted;
165 }
167 @Override
168 public Uri insertInTransaction(Uri uri, ContentValues values) {
169 trace("Calling insert in transaction on URI: " + uri);
170 long id = -1;
171 int match = URI_MATCHER.match(uri);
173 switch (match) {
174 case ITEMS:
175 trace("Insert on ITEMS: " + uri);
176 id = insertItem(uri, values);
177 break;
179 default:
180 throw new UnsupportedOperationException("Unknown insert URI " + uri);
181 }
183 debug("Inserted ID in database: " + id);
185 if (id >= 0) {
186 return ContentUris.withAppendedId(uri, id);
187 }
189 return null;
190 }
192 @Override
193 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
194 String groupBy = null;
195 SQLiteDatabase db = getReadableDatabase(uri);
196 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
197 String limit = uri.getQueryParameter(BrowserContract.PARAM_LIMIT);
199 final int match = URI_MATCHER.match(uri);
200 switch (match) {
201 case ITEMS_ID:
202 trace("Query on ITEMS_ID: " + uri);
203 selection = DBUtils.concatenateWhere(selection, ReadingListItems._ID + " = ?");
204 selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
205 new String[] { Long.toString(ContentUris.parseId(uri)) });
207 case ITEMS:
208 trace("Query on ITEMS: " + uri);
209 if (!shouldShowDeleted(uri))
210 selection = DBUtils.concatenateWhere(ReadingListItems.IS_DELETED + " = 0", selection);
211 break;
213 default:
214 throw new UnsupportedOperationException("Unknown query URI " + uri);
215 }
217 if (TextUtils.isEmpty(sortOrder)) {
218 sortOrder = ReadingListItems.DEFAULT_SORT_ORDER;
219 }
221 trace("Running built query.");
222 qb.setTables(TABLE_READING_LIST);
223 Cursor cursor = qb.query(db, projection, selection, selectionArgs, groupBy, null, sortOrder, limit);
224 cursor.setNotificationUri(getContext().getContentResolver(), uri);
226 return cursor;
227 }
229 @Override
230 public String getType(Uri uri) {
231 trace("Getting URI type: " + uri);
233 final int match = URI_MATCHER.match(uri);
234 switch (match) {
235 case ITEMS:
236 trace("URI is ITEMS: " + uri);
237 return ReadingListItems.CONTENT_TYPE;
239 case ITEMS_ID:
240 trace("URI is ITEMS_ID: " + uri);
241 return ReadingListItems.CONTENT_ITEM_TYPE;
242 }
244 debug("URI has unrecognized type: " + uri);
245 return null;
246 }
247 }