Fully fleshed out content provider. Now for unit tests

pull/14/head
Tim Su 16 years ago
parent 17a9ec4cb2
commit 986de7792b

@ -12,6 +12,7 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty; import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table; import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.astrid.api.AstridApiConstants;
/** /**
* Data Model which represents a piece of metadata associated with a task * Data Model which represents a piece of metadata associated with a task
@ -24,8 +25,12 @@ public class Metadata extends AbstractModel {
// --- table // --- table
/** table for this model */
public static final Table TABLE = new Table("metadata", Metadata.class); 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 // --- properties
/** ID */ /** ID */

@ -12,6 +12,7 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty; import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table; import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.astrid.api.AstridApiConstants;
/** /**
* Data Model which represents a piece of data unrelated to a task * Data Model which represents a piece of data unrelated to a task
@ -24,8 +25,12 @@ public class StoreObject extends AbstractModel {
// --- table // --- table
/** table for this model */
public static final Table TABLE = new Table("store", StoreObject.class); 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 // --- properties
/** ID */ /** ID */

@ -10,6 +10,7 @@ import android.content.UriMatcher;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils;
import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.GenericDao; 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.andlib.service.ExceptionService;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database; 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.dao.TaskDao;
import com.todoroo.astrid.model.Metadata; import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.StoreObject; import com.todoroo.astrid.model.StoreObject;
@ -45,7 +48,7 @@ import com.todoroo.astrid.service.AstridDependencyInjector;
* @author Tim Su <tim@todoroo.com> * @author Tim Su <tim@todoroo.com>
* *
*/ */
@SuppressWarnings({"nls","unused"}) @SuppressWarnings("nls")
public class Astrid3ContentProvider extends ContentProvider { public class Astrid3ContentProvider extends ContentProvider {
static { static {
@ -71,6 +74,12 @@ public class Astrid3ContentProvider extends ContentProvider {
@Autowired @Autowired
private TaskDao taskDao; private TaskDao taskDao;
@Autowired
private MetadataDao metadataDao;
@Autowired
private StoreObjectDao storeObjectDao;
@Autowired @Autowired
private ExceptionService exceptionService; private ExceptionService exceptionService;
@ -89,9 +98,12 @@ public class Astrid3ContentProvider extends ContentProvider {
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(Task.CONTENT_URI, "", URI_DIR);
uriMatcher.addURI(Task.CONTENT_URI, "#", URI_ITEM); for(String uri : new String[] { Task.CONTENT_URI, Metadata.CONTENT_URI, StoreObject.CONTENT_URI }) {
uriMatcher.addURI(Task.CONTENT_URI, "groupby/*", URI_GROUP); uriMatcher.addURI(uri, "", URI_DIR);
uriMatcher.addURI(uri, "#", URI_ITEM);
uriMatcher.addURI(uri, "groupby/*", URI_GROUP);
}
setReadPermission(AstridApiConstants.PERMISSION_READ); setReadPermission(AstridApiConstants.PERMISSION_READ);
setWritePermission(AstridApiConstants.PERMISSION_WRITE); setWritePermission(AstridApiConstants.PERMISSION_WRITE);
@ -140,6 +152,16 @@ public class Astrid3ContentProvider extends ContentProvider {
helper.model = populateModel ? new Task() : null; helper.model = populateModel ? new Task() : null;
helper.dao = taskDao; helper.dao = taskDao;
return helper; return helper;
} else if(uri.toString().startsWith(Metadata.CONTENT_URI)) {
UriHelper<Metadata> helper = new UriHelper<Metadata>();
helper.model = populateModel ? new Metadata() : null;
helper.dao = metadataDao;
return helper;
} else if(uri.toString().startsWith(StoreObject.CONTENT_URI)) {
UriHelper<StoreObject> helper = new UriHelper<StoreObject>();
helper.model = populateModel ? new StoreObject() : null;
helper.dao = storeObjectDao;
return helper;
} }
throw new UnsupportedOperationException("Unknown URI " + uri); throw new UnsupportedOperationException("Unknown URI " + uri);
@ -155,6 +177,7 @@ public class Astrid3ContentProvider extends ContentProvider {
*/ */
@Override @Override
public int delete(Uri uri, String selection, String[] selectionArgs) { public int delete(Uri uri, String selection, String[] selectionArgs) {
UriHelper<?> helper = generateHelper(uri, false);
switch (uriMatcher.match(uri)) { switch (uriMatcher.match(uri)) {
// illegal operations // illegal operations
@ -166,18 +189,23 @@ public class Astrid3ContentProvider extends ContentProvider {
// valid operations // valid operations
case URI_ITEM: { 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: { case URI_DIR:
break;
return 0;
}
default: default:
throw new IllegalArgumentException("Unknown URI " + uri); 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 @Override
public Uri insert(Uri uri, ContentValues values) { public Uri insert(Uri uri, ContentValues values) {
UriHelper<?> helper = generateHelper(uri, true);
switch (uriMatcher.match(uri)) { switch (uriMatcher.match(uri)) {
// illegal operations // illegal operations
@ -201,12 +230,10 @@ public class Astrid3ContentProvider extends ContentProvider {
// valid operations // valid operations
case URI_DIR: { case URI_DIR: {
UriHelper<?> helper = generateHelper(uri, true);
helper.model.mergeWith(values); helper.model.mergeWith(values);
helper.create(); helper.create();
Uri newUri = ContentUris.withAppendedId(uri, helper.model.getId());
return ContentUris.withAppendedId(uri, helper.model.getId()); getContext().getContentResolver().notifyChange(newUri, null);
} }
default: default:
@ -218,95 +245,27 @@ public class Astrid3ContentProvider extends ContentProvider {
* =========================================================== update === * =========================================================== 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 @Override
public int update(Uri uri, ContentValues values, String selection, public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) { String[] selectionArgs) {
/*switch (uriMatcher.match(uri)) { UriHelper<?> helper = generateHelper(uri, true);
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<String,Object> 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);
}
if (taskId > 0) { Cursor cursor = query(uri, new String[] { AbstractModel.ID_PROPERTY.name },
Uri _uri = ContentUris.withAppendedId(makeContentUri(), taskId); selection, selectionArgs, null);
getContext().getContentResolver().notifyChange(_uri, null); try {
return _uri; 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; getContext().getContentResolver().notifyChange(uri, null);
} return cursor.getCount();
case ITEM: } finally {
String id = uri.getPathSegments().get(0); cursor.close();
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 count;*/
return 0; // FIXME
} }
/* ====================================================================== /* ======================================================================

Loading…
Cancel
Save