Added properties to cursor, and gettin' stuff to work

pull/14/head
Tim Su 14 years ago
parent dd863f396d
commit 811b4862c9

@ -3,21 +3,20 @@ package com.todoroo.astrid.tags;
import java.util.ArrayList;
import android.content.Context;
import android.database.DatabaseUtils;
import com.thoughtworks.sql.Criterion;
import com.thoughtworks.sql.Order;
import com.thoughtworks.sql.Query;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.data.sql.Criterion;
import com.todoroo.andlib.data.sql.Join;
import com.todoroo.andlib.data.sql.Order;
import com.todoroo.andlib.data.sql.Query;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridContentProvider.AstridTask;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.service.MetadataService;
/**
@ -34,9 +33,6 @@ public class DataService {
*/
public static final String KEY = "tags-tag";
@Autowired
private Database database;
@Autowired
private MetadataDao metadataDao;
@ -62,7 +58,7 @@ public class DataService {
*
*/
public class Tag {
String tag;
public String tag;
int count;
@Override
@ -119,46 +115,24 @@ public class DataService {
Metadata metadata = new Metadata();
for (int i = 0; i < length; i++) {
tags.moveToNext();
metadata.readFromCursor(tags, PROP)
tagBuilder.append(]);
if (i < tags.length - 1)
metadata.readFromCursor(tags);
tagBuilder.append(metadata.getValue(Metadata.VALUE));
if (i < length - 1)
tagBuilder.append(", ");
}
return tagBuilder.toString();
}
private static final String query = String.format("INNER JOIN %s ON %s = "
+ "%s WHERE %s = 0 AND %s = '%s' AND %s = ",
AstridApiConstants.METADATA_TABLE,
AstridTask.ID, Metadata.TASK,
AstridTask.COMPLETION_DATE,
Metadata.KEY, KEY,
Metadata.VALUE);
/**
* Return SQL selector query for getting tasks with a given tag
*
* @param tag
* @return
*/
public String getQuery(String tag) {
return query + String.format("%s", DatabaseUtils.sqlEscapeString(tag));
}
private static final String newTaskSql = String.format(
"INSERT INTO %s (%s, %s, %s) " + "VALUES ($ID,'%s',",
AstridApiConstants.METADATA_TABLE,
Metadata.TASK.name,
Metadata.KEY.name,
Metadata.VALUE.name,
KEY);
/**
* Return SQL new task creator query
* @param tag
*/
public String getNewTaskSql(String tag) {
return newTaskSql + String.format("%s)", DatabaseUtils.sqlEscapeString(tag));
public Query tasksWithTag(String tag, Property<?>... properties) {
return Query.select(properties).join(Join.inner(Metadata.TABLE,
Task.ID.eq(Metadata.TASK))).where(Criterion.and(
MetadataCriteria.withKey(KEY), Metadata.VALUE.eq(tag)));
}
/**
@ -167,16 +141,15 @@ public class DataService {
* @param tags
*/
public void synchronizeTags(long taskId, ArrayList<String> tags) {
metadataDao.deleteWhere(database, MetadataSql.byTask(taskId) + " AND " +
MetadataSql.withKey(KEY));
metadataDao.deleteWhere(Criterion.and(MetadataCriteria.byTask(taskId),
MetadataCriteria.withKey(KEY)));
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, KEY);
metadata.setValue(Metadata.TASK, taskId);
for(String tag : tags) {
metadata.setValue(Metadata.VALUE, tag.trim());
metadataDao.save(database, metadata);
metadata.clearValue(Metadata.ID);
metadataDao.createItem(metadata);
}
}
}

@ -1,78 +0,0 @@
/*
* Copyright (c) 2009, Todoroo Inc
* All Rights Reserved
* http://www.todoroo.com
*/
package com.todoroo.astrid.tagsold;
import android.content.ContentValues;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
/**
* Data Model which represents a task users need to accomplish.
*
* @author Tim Su <tim@todoroo.com>
*
*/
@SuppressWarnings("nls")
public class Tag extends AbstractModel {
// --- table
public static final Table TABLE = new Table("tags", Tag.class);
// --- properties
/** ID */
public static final LongProperty ID = new LongProperty(
TABLE, ID_PROPERTY_NAME);
/** Name of Task */
public static final StringProperty NAME = new StringProperty(
TABLE, "name");
/** List of all properties for this model */
public static final Property<?>[] PROPERTIES = generateProperties(Tag.class);
// --- defaults
/** Default values container */
private static final ContentValues defaultValues = new ContentValues();
static {
defaultValues.put(NAME.name, "");
}
@Override
public ContentValues getDefaultValues() {
return defaultValues;
}
// --- data access boilerplate
public Tag() {
super();
}
public Tag(TodorooCursor<Tag> cursor, Property<?>[] properties) {
this();
readPropertiesFromCursor(cursor, properties);
}
public void readFromCursor(TodorooCursor<Tag> cursor, Property<?>[] properties) {
super.readPropertiesFromCursor(cursor, properties);
}
@Override
public long getId() {
return getIdHelper(ID);
}
}

@ -1,63 +0,0 @@
/*
* ASTRID: Android's Simple Task Recording Dashboard
*
* Copyright (c) 2009 Tim Su
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.todoroo.astrid.tagsold;
import android.database.SQLException;
import com.todoroo.andlib.data.GenericDao;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.sql.Join;
import com.todoroo.andlib.data.sql.Query;
import com.todoroo.astrid.model.Task;
/**
* Service layer for tags plugin
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class TagService {
private GenericDao<Tag> tagDao;
private GenericDao<TagToTaskMapping> tagToTaskDao;
public TagService() {
TagsDatabase tagDatabase = new TagsDatabase();
tagDao = new GenericDao<Tag>(Tag.class, tagDatabase);
tagToTaskDao = new GenericDao<TagToTaskMapping>(TagToTaskMapping.class,
tagDatabase);
}
// --- tag batch operations
/** Get a list of all tags */
public TodorooCursor<Tag> getAllTags(Property<?>... properties) {
return tagDao.query(Query.select(properties));
}
/** Get a list of tag identifiers for the given task */
public TodorooCursor<Tag> getTaskTags(Task task, Property<?>... properties) throws SQLException {
Query query = Query.select(properties).join(Join.inner(TagToTaskMapping.TABLE,
Tag.ID.eq(TagToTaskMapping.TAG))).where(TagToTaskMapping.TASK.eq(task.getId()));
return tagDao.query(query);
}
}

@ -1,73 +0,0 @@
/*
* Copyright (c) 2009, Todoroo Inc
* All Rights Reserved
* http://www.todoroo.com
*/
package com.todoroo.astrid.tagsold;
import android.content.ContentValues;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.LongProperty;
/**
* Data Model which represents a task users need to accomplish.
*
* @author Tim Su <tim@todoroo.com>
*
*/
@SuppressWarnings("nls")
public class TagToTaskMapping extends AbstractModel {
// --- table
public static final Table TABLE = new Table("tagTaskMap", TagToTaskMapping.class);
// --- properties
/** Tag */
public static final LongProperty TAG = new LongProperty(
TABLE, "tag");
/** Task */
public static final LongProperty TASK = new LongProperty(
TABLE, "task");
/** List of all properties for this model */
public static final Property<?>[] PROPERTIES = generateProperties(TagToTaskMapping.class);
// --- defaults
/** Default values container */
private static final ContentValues defaultValues = new ContentValues();
@Override
public ContentValues getDefaultValues() {
return defaultValues;
}
// --- data access boilerplate
public TagToTaskMapping() {
super();
}
public TagToTaskMapping(TodorooCursor<TagToTaskMapping> cursor, Property<?>[] properties) {
this();
readPropertiesFromCursor(cursor, properties);
}
public void readFromCursor(TodorooCursor<TagToTaskMapping> cursor, Property<?>[] properties) {
super.readPropertiesFromCursor(cursor, properties);
}
@Override
public long getId() {
return NO_ID;
}
}

@ -1,82 +0,0 @@
/*
* Copyright (c) 2009, Todoroo Inc
* All Rights Reserved
* http://www.todoroo.com
*/
package com.todoroo.astrid.tagsold;
import com.todoroo.andlib.data.AbstractDatabase;
import com.todoroo.andlib.data.Table;
/**
* Database wrapper
*
* @author Tim Su <tim@todoroo.com>
*
*/
@SuppressWarnings("nls")
public class TagsDatabase extends AbstractDatabase {
// --- constants
/**
* Database version number. This variable must be updated when database
* tables are updated, as it determines whether a database needs updating.
*/
public static final int VERSION = 1;
/**
* Database name (must be unique)
*/
private static final String NAME = "tags";
/**
* List of table/ If you're adding a new table, add it to this list and
* also make sure that our SQLite helper does the right thing.
*/
public static final Table[] TABLES = new Table[] {
Tag.TABLE,
TagToTaskMapping.TABLE,
};
// --- implementation
@Override
protected String getName() {
return NAME;
}
@Override
protected int getVersion() {
return VERSION;
}
@Override
public Table[] getTables() {
return TABLES;
}
@Override
protected void onCreateTables() {
StringBuilder sql = new StringBuilder();
sql.append("CREATE INDEX IF NOT EXISTS tm_tag ON ").
append(TagToTaskMapping.TABLE).append('(').
append(TagToTaskMapping.TAG.name).
append(')');
database.execSQL(sql.toString());
sql.setLength(0);
sql.append("CREATE INDEX IF NOT EXISTS tm_task ON ").
append(TagToTaskMapping.TABLE).append('(').
append(TagToTaskMapping.TASK.name).
append(')');
database.execSQL(sql.toString());
}
@Override
protected boolean onUpgrade(int oldVersion, int newVersion) {
return false;
}
}

@ -66,7 +66,7 @@ public class MetadataDao extends GenericDao<Metadata> {
Query sql = Query.select(properties).from(Metadata.TABLE).join(Join.left(Task.TABLE,
Metadata.TASK.eq(Task.ID))).where(Task.TITLE.isNull());
Cursor cursor = database.getDatabase().rawQuery(sql.toString(), null);
return new TodorooCursor<Metadata>(cursor);
return new TodorooCursor<Metadata>(cursor, properties);
}
}

@ -63,17 +63,27 @@ public class Metadata extends AbstractModel {
super();
}
public Metadata(TodorooCursor<Metadata> cursor, Property<?>[] properties) {
public Metadata(TodorooCursor<Metadata> cursor) {
this();
readPropertiesFromCursor(cursor, properties);
readPropertiesFromCursor(cursor);
}
public void readFromCursor(TodorooCursor<Metadata> cursor, Property<?>[] properties) {
super.readPropertiesFromCursor(cursor, properties);
public void readFromCursor(TodorooCursor<Metadata> cursor) {
super.readPropertiesFromCursor(cursor);
}
@Override
public long getId() {
return getIdHelper(ID);
};
// --- parcelable helpers
private static final Creator<Task> CREATOR = new ModelCreator<Task>(Task.class);
@Override
protected Creator<? extends AbstractModel> getCreator() {
return CREATOR;
}
}

@ -184,13 +184,13 @@ public class Task extends AbstractModel {
super();
}
public Task(TodorooCursor<Task> cursor, Property<?>[] properties) {
public Task(TodorooCursor<Task> cursor) {
this();
readPropertiesFromCursor(cursor, properties);
readPropertiesFromCursor(cursor);
}
public void readFromCursor(TodorooCursor<Task> cursor, Property<?>[] properties) {
super.readPropertiesFromCursor(cursor, properties);
public void readFromCursor(TodorooCursor<Task> cursor) {
super.readPropertiesFromCursor(cursor);
}
@Override
@ -198,6 +198,15 @@ public class Task extends AbstractModel {
return getIdHelper(ID);
}
// --- parcelable helpers
private static final Creator<Task> CREATOR = new ModelCreator<Task>(Task.class);
@Override
protected Creator<? extends AbstractModel> getCreator() {
return CREATOR;
}
// --- data access methods
/** Checks whether task is done. Requires COMPLETION_DATE */

@ -33,7 +33,7 @@ public class MetadataDaoTests extends DatabaseTestCase {
// create "happy"
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, "happy");
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
cursor = metadataDao.query(
Query.select(MetadataService.idProperty()));
assertEquals(1, cursor.getCount());
@ -46,7 +46,7 @@ public class MetadataDaoTests extends DatabaseTestCase {
// create "sad"
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "sad");
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
cursor = metadataDao.query(Query.select(MetadataService.idProperty()));
assertEquals(2, cursor.getCount());
cursor.close();
@ -55,7 +55,7 @@ public class MetadataDaoTests extends DatabaseTestCase {
long sadId = metadata.getId();
assertNotSame(Metadata.NO_ID, sadId);
metadata.setValue(Metadata.KEY, "melancholy");
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
cursor = metadataDao.query(
Query.select(MetadataService.idProperty()));
assertEquals(2, cursor.getCount());
@ -73,7 +73,7 @@ public class MetadataDaoTests extends DatabaseTestCase {
Query.select(KEYS));
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
metadata.readFromCursor(cursor, KEYS);
metadata.readFromCursor(cursor);
assertEquals("happy", metadata.getValue(Metadata.KEY));
cursor.close();
}
@ -86,27 +86,27 @@ public class MetadataDaoTests extends DatabaseTestCase {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with1");
metadata.setValue(Metadata.TASK, 1L);
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with2");
metadata.setValue(Metadata.TASK, 2L);
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with1");
metadata.setValue(Metadata.TASK, 1L);
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
TodorooCursor<Metadata> cursor = metadataDao.query(
Query.select(KEYS).where(MetadataCriteria.byTask(1)));
assertEquals(2, cursor.getCount());
cursor.moveToFirst();
metadata.readFromCursor(cursor, KEYS);
metadata.readFromCursor(cursor);
assertEquals("with1", metadata.getValue(Metadata.KEY));
cursor.moveToNext();
metadata.readFromCursor(cursor, KEYS);
metadata.readFromCursor(cursor);
assertEquals("with1", metadata.getValue(Metadata.KEY));
cursor.close();
@ -133,11 +133,11 @@ public class MetadataDaoTests extends DatabaseTestCase {
cursor.close();
Task task1 = new Task();
taskDao.save(task1);
taskDao.persist(task1);
Task task2 = new Task();
taskDao.save(task2);
taskDao.persist(task2);
Task task3 = new Task();
taskDao.save(task3);
taskDao.persist(task3);
// fetch with only tasks
cursor = metadataDao.fetchDangling(KEYS);
@ -147,17 +147,17 @@ public class MetadataDaoTests extends DatabaseTestCase {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with1");
metadata.setValue(Metadata.TASK, task1.getId());
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with2");
metadata.setValue(Metadata.TASK, task2.getId());
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with3");
metadata.setValue(Metadata.TASK, task3.getId());
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
// fetch with tasks and corresponding metadata
cursor = metadataDao.fetchDangling(KEYS);
@ -176,14 +176,14 @@ public class MetadataDaoTests extends DatabaseTestCase {
metadata = new Metadata();
metadata.setValue(Metadata.KEY, "with2");
metadata.setValue(Metadata.TASK, task2Id);
assertTrue(metadataDao.save(metadata));
assertTrue(metadataDao.persist(metadata));
// but if we simulate something bad happening by creating
// it manually.. well, what can i say, it should be broken
cursor = metadataDao.fetchDangling(KEYS);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
metadata.readFromCursor(cursor, KEYS);
metadata.readFromCursor(cursor);
assertEquals("with2", metadata.getValue(Metadata.KEY));
cursor.close();
}

@ -5,7 +5,6 @@ import com.todoroo.andlib.service.TestDependencyInjector;
import com.todoroo.andlib.test.TodorooTestCase;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.tagsold.TagsDatabase;
/**
* Test case that automatically sets up and tears down a test database
@ -44,10 +43,6 @@ public class DatabaseTestCase extends TodorooTestCase {
database.clear();
database.openForWriting();
// and plugin databases too
TagsDatabase tagsDatabase = new TagsDatabase();
tagsDatabase.clear();
// clear legacy databases
getContext().deleteDatabase(TASKS_TEST);
getContext().deleteDatabase(TAGS_TEST);
@ -61,7 +56,7 @@ public class DatabaseTestCase extends TodorooTestCase {
database.close();
}
public static class TestDatabase extends TagsDatabase {
public static class TestDatabase extends Database {
private static final String NAME = "databasetest";
@Override

@ -15,8 +15,8 @@ import com.todoroo.astrid.legacy.data.task.TaskModelForEdit;
import com.todoroo.astrid.legacy.data.task.AbstractTaskModel.RepeatInfo;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.service.UpgradeService;
import com.todoroo.astrid.tagsold.Tag;
import com.todoroo.astrid.tagsold.TagService;
import com.todoroo.astrid.tags.DataService;
import com.todoroo.astrid.tags.DataService.Tag;
import com.todoroo.astrid.test.DatabaseTestCase;
public class Astrid2To3UpgradeTests extends DatabaseTestCase {
@ -81,7 +81,7 @@ public class Astrid2To3UpgradeTests extends DatabaseTestCase {
assertEquals(2, tasks.getCount());
tasks.moveToFirst();
Task task = new Task(tasks, Task.PROPERTIES);
Task task = new Task(tasks);
assertEquals(griffey.getName(), task.getValue(Task.TITLE));
assertDatesEqual(griffey.getDefiniteDueDate(), task.getValue(Task.DUE_DATE));
assertEquals((Integer)Task.IMPORTANCE_SHOULD_DO, task.getValue(Task.IMPORTANCE));
@ -91,7 +91,7 @@ public class Astrid2To3UpgradeTests extends DatabaseTestCase {
assertEquals((Integer)0, task.getValue(Task.HIDDEN_UNTIL));
tasks.moveToNext();
task = new Task(tasks, Task.PROPERTIES);
task = new Task(tasks);
assertEquals(guti.getName(), task.getValue(Task.TITLE));
assertDatesEqual(guti.getDefiniteDueDate(), task.getValue(Task.DUE_DATE));
assertDatesEqual(guti.getPreferredDueDate(), task.getValue(Task.DUE_DATE));
@ -132,9 +132,24 @@ public class Astrid2To3UpgradeTests extends DatabaseTestCase {
upgrade2To3();
// verify that data exists in our new table
TagService tagService = new TagService();
TodorooCursor<Tag> tags = tagService.getAllTags(Tag.NAME);
assertEquals(2, tags.getCount());
DataService tagService = new DataService(getContext());
Tag[] tags = tagService.getGroupedTags(DataService.GROUPED_TAGS_BY_ALPHA);
assertEquals(2, tags.length);
assertEquals("salty", tags[0].tag);
assertEquals("tasty", tags[0].tag);
// verify that tags are applied correctly
TodorooCursor<Task> tasks = taskDao.query(Query.select(Task.PROPERTIES));
assertEquals(3, tasks.getCount());
tasks.moveToFirst();
Task task = new Task(tasks);
assertEquals("tasty,salty", tagService.getTagsAsString(task.getId()));
tasks.moveToNext();
task.readFromCursor(tasks);
assertEquals("tasty", tagService.getTagsAsString(task.getId()));
tasks.moveToNext();
task.readFromCursor(tasks);
assertEquals("", tagService.getTagsAsString(task.getId()));
}

Loading…
Cancel
Save