From 986de7792b126f07bc687326d93fcd1f4a52bebd Mon Sep 17 00:00:00 2001 From: Tim Su Date: Thu, 19 Aug 2010 16:56:35 -0700 Subject: [PATCH] Fully fleshed out content provider. Now for unit tests --- .../com/todoroo/astrid/model/Metadata.java | 5 + .../com/todoroo/astrid/model/StoreObject.java | 5 + .../provider/Astrid3ContentProvider.java | 149 +++++++----------- 3 files changed, 64 insertions(+), 95 deletions(-) diff --git a/astrid/src/com/todoroo/astrid/model/Metadata.java b/astrid/src/com/todoroo/astrid/model/Metadata.java index f1c71abe6..d9d838e13 100644 --- a/astrid/src/com/todoroo/astrid/model/Metadata.java +++ b/astrid/src/com/todoroo/astrid/model/Metadata.java @@ -12,6 +12,7 @@ import com.todoroo.andlib.data.Property.LongProperty; import com.todoroo.andlib.data.Property.StringProperty; import com.todoroo.andlib.data.Table; import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.astrid.api.AstridApiConstants; /** * Data Model which represents a piece of metadata associated with a task @@ -24,8 +25,12 @@ public class Metadata extends AbstractModel { // --- table + /** table for this model */ public static final Table TABLE = new Table("metadata", Metadata.class); + /** content uri for this model */ + public static final String CONTENT_URI = "content://" + AstridApiConstants.PACKAGE + "/metadata/"; + // --- properties /** ID */ diff --git a/astrid/src/com/todoroo/astrid/model/StoreObject.java b/astrid/src/com/todoroo/astrid/model/StoreObject.java index 9d1294cdf..6558d3205 100644 --- a/astrid/src/com/todoroo/astrid/model/StoreObject.java +++ b/astrid/src/com/todoroo/astrid/model/StoreObject.java @@ -12,6 +12,7 @@ import com.todoroo.andlib.data.Property.LongProperty; import com.todoroo.andlib.data.Property.StringProperty; import com.todoroo.andlib.data.Table; import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.astrid.api.AstridApiConstants; /** * Data Model which represents a piece of data unrelated to a task @@ -24,8 +25,12 @@ public class StoreObject extends AbstractModel { // --- table + /** table for this model */ public static final Table TABLE = new Table("store", StoreObject.class); + /** content uri for this model */ + public static final String CONTENT_URI = "content://" + AstridApiConstants.PACKAGE + "/store/"; + // --- properties /** ID */ diff --git a/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java b/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java index 519aa47f8..705fd56a2 100644 --- a/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java +++ b/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java @@ -10,6 +10,7 @@ import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.text.TextUtils; import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.GenericDao; @@ -18,6 +19,8 @@ import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.ExceptionService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.dao.Database; +import com.todoroo.astrid.dao.MetadataDao; +import com.todoroo.astrid.dao.StoreObjectDao; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.model.Metadata; import com.todoroo.astrid.model.StoreObject; @@ -45,7 +48,7 @@ import com.todoroo.astrid.service.AstridDependencyInjector; * @author Tim Su * */ -@SuppressWarnings({"nls","unused"}) +@SuppressWarnings("nls") public class Astrid3ContentProvider extends ContentProvider { static { @@ -71,6 +74,12 @@ public class Astrid3ContentProvider extends ContentProvider { @Autowired private TaskDao taskDao; + @Autowired + private MetadataDao metadataDao; + + @Autowired + private StoreObjectDao storeObjectDao; + @Autowired private ExceptionService exceptionService; @@ -89,9 +98,12 @@ public class Astrid3ContentProvider extends ContentProvider { DependencyInjectionService.getInstance().inject(this); uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - uriMatcher.addURI(Task.CONTENT_URI, "", URI_DIR); - uriMatcher.addURI(Task.CONTENT_URI, "#", URI_ITEM); - uriMatcher.addURI(Task.CONTENT_URI, "groupby/*", URI_GROUP); + + for(String uri : new String[] { Task.CONTENT_URI, Metadata.CONTENT_URI, StoreObject.CONTENT_URI }) { + uriMatcher.addURI(uri, "", URI_DIR); + uriMatcher.addURI(uri, "#", URI_ITEM); + uriMatcher.addURI(uri, "groupby/*", URI_GROUP); + } setReadPermission(AstridApiConstants.PERMISSION_READ); setWritePermission(AstridApiConstants.PERMISSION_WRITE); @@ -140,6 +152,16 @@ public class Astrid3ContentProvider extends ContentProvider { helper.model = populateModel ? new Task() : null; helper.dao = taskDao; return helper; + } else if(uri.toString().startsWith(Metadata.CONTENT_URI)) { + UriHelper helper = new UriHelper(); + helper.model = populateModel ? new Metadata() : null; + helper.dao = metadataDao; + return helper; + } else if(uri.toString().startsWith(StoreObject.CONTENT_URI)) { + UriHelper helper = new UriHelper(); + helper.model = populateModel ? new StoreObject() : null; + helper.dao = storeObjectDao; + return helper; } throw new UnsupportedOperationException("Unknown URI " + uri); @@ -155,6 +177,7 @@ public class Astrid3ContentProvider extends ContentProvider { */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { + UriHelper helper = generateHelper(uri, false); switch (uriMatcher.match(uri)) { // illegal operations @@ -166,18 +189,23 @@ public class Astrid3ContentProvider extends ContentProvider { // valid operations case URI_ITEM: { + String itemSelector = String.format("%s = '%s'", + AbstractModel.ID_PROPERTY, uri.getPathSegments().get(1)); + if(TextUtils.isEmpty(selection)) + selection = itemSelector; + else + selection = itemSelector + " AND " + selection; - return 0; } - case URI_DIR: { - - return 0; - } + case URI_DIR: + break; default: throw new IllegalArgumentException("Unknown URI " + uri); } + + return database.delete(helper.dao.getTable().name, selection, selectionArgs); } /* ====================================================================== @@ -189,6 +217,7 @@ public class Astrid3ContentProvider extends ContentProvider { */ @Override public Uri insert(Uri uri, ContentValues values) { + UriHelper helper = generateHelper(uri, true); switch (uriMatcher.match(uri)) { // illegal operations @@ -201,12 +230,10 @@ public class Astrid3ContentProvider extends ContentProvider { // valid operations case URI_DIR: { - - UriHelper helper = generateHelper(uri, true); helper.model.mergeWith(values); helper.create(); - - return ContentUris.withAppendedId(uri, helper.model.getId()); + Uri newUri = ContentUris.withAppendedId(uri, helper.model.getId()); + getContext().getContentResolver().notifyChange(newUri, null); } default: @@ -218,95 +245,27 @@ public class Astrid3ContentProvider extends ContentProvider { * =========================================================== update === * ====================================================================== */ - /** - * Unescapes a string for use in a URI. Used internally to pass extra data - * to the content provider. - * @param component - * @return - */ - private static String unescapeUriComponent(String component) { - return component.replace("%s", "/").replace("%o", "%"); - } - - /** - * Escapes a string for use as part of a URI string. Used internally to pass extra data - * to the content provider. - * @param component - * @return - */ - private static String[] unpackUriSubComponent(String component) { - return component.replace("$s", "|").replace("o", "$").split("|"); - } - @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - /*switch (uriMatcher.match(uri)) { - case URI_DIR_WITH_METADATA: { - SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); - String[] metadata = unpackUriSubComponent(uri.getPathSegments().get(1)); - StringBuilder tables = new StringBuilder(Database.TASK_TABLE).append(" t"); - for(int i = 0; i < metadata.length; i++) { - String tableName = "m" + i; - tables.append(String.format(" LEFT OUTER JOIN %s %s ON t._id = %s.%s", - Database.METADATA_TABLE, tableName, tableName, Metadata.TASK.name)); - builder.appendWhereEscapeString(String.format("%s.%s = '%s' AND ", - tableName, Metadata.KEY.name, projection[i])); - } - } - - case URI_DIR: { - // UPDATE tasks SET ... WHERE ... - taskValues = initialize(taskValues); - metadataValues = initialize(metadataValues); - separateTaskColumnsFromMetadata(values, taskValues, metadataValues); - - count = database.getDatabase().update(getTableName(), valuesWithDefaults, - selection, selectionArgs); - - // SELECT _id WHERE ... - - // INSERT OR REPLACE INTO metadata (...) VALUES (...) - long taskId = TodorooContentProvider.insertHelper(database, - Database.TASK_TABLE, taskValues, Task.getStaticDefaultValues()); - - for(Entry metadata : metadataValues.valueSet()) { - tempValues = initialize(tempValues); - tempValues.put(Metadata.KEY.name, metadata.getKey()); - tempValues.put(Metadata.VALUE.name, metadata.getValue().toString()); - TodorooContentProvider.insertHelper(database, - Database.METADATA_TABLE, tempValues, null); - } + UriHelper helper = generateHelper(uri, true); - if (taskId > 0) { - Uri _uri = ContentUris.withAppendedId(makeContentUri(), taskId); - getContext().getContentResolver().notifyChange(_uri, null); - return _uri; + Cursor cursor = query(uri, new String[] { AbstractModel.ID_PROPERTY.name }, + selection, selectionArgs, null); + try { + for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + long id = cursor.getLong(0); + helper.model.mergeWith(values); + helper.model.setId(id); + helper.update(); + helper.model.clear(); } - break; - } - case ITEM: - String id = uri.getPathSegments().get(0); - ContentValues newValues = new ContentValues(); - rewriteKeysFor(values, newValues); - count = database.getDatabase().update( - getTableName(), - newValues, - (AbstractModel.ID_PROPERTY + "=" + id) - + (!TextUtils.isEmpty(selection) ? " AND (" - + selection + ')' : ""), selectionArgs); - break; - case GROUP: - throw new IllegalArgumentException("Invalid URI for update: " + uri); - - default: - throw new IllegalArgumentException("Unknown URI " + uri); + getContext().getContentResolver().notifyChange(uri, null); + return cursor.getCount(); + } finally { + cursor.close(); } - getContext().getContentResolver().notifyChange(uri, null); - return count;*/ - - return 0; // FIXME } /* ======================================================================