From c1273f6b979f06f6d99a22f673cc361be97f455d Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 17 Jul 2014 12:01:09 -0500 Subject: [PATCH] Hide remaining Metadata cursors --- .../andlib/utility/AndroidUtilities.java | 1 - .../com/todoroo/astrid/data/Metadata.java | 11 --- .../todoroo/astrid/dao/MetadataDaoTests.java | 62 +++++---------- .../astrid/gtasks/GtasksTaskListUpdater.java | 44 +++++------ .../astrid/notes/EditNoteActivity.java | 17 +---- .../astrid/provider/Astrid2TaskProvider.java | 20 +---- .../astrid/service/TaskDuplicator.java | 38 +++++----- .../com/todoroo/astrid/tags/TagService.java | 75 +++++++++---------- .../todoroo/astrid/tags/TagsControlSet.java | 33 +++----- 9 files changed, 107 insertions(+), 194 deletions(-) diff --git a/api/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java b/api/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java index 1c821a4fe..1d62199c3 100644 --- a/api/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java +++ b/api/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java @@ -26,7 +26,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.Array; import java.util.Arrays; import java.util.Comparator; import java.util.Map.Entry; diff --git a/api/src/main/java/com/todoroo/astrid/data/Metadata.java b/api/src/main/java/com/todoroo/astrid/data/Metadata.java index 254c11907..795c872fd 100644 --- a/api/src/main/java/com/todoroo/astrid/data/Metadata.java +++ b/api/src/main/java/com/todoroo/astrid/data/Metadata.java @@ -14,7 +14,6 @@ import com.todoroo.andlib.data.Property; 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; /** @@ -99,16 +98,6 @@ public class Metadata extends AbstractModel { return defaultValues; } - // --- data access boilerplate - - public Metadata() { - super(); - } - - public Metadata(TodorooCursor cursor) { - super(cursor); - } - @Override public long getId() { return getIdHelper(ID); diff --git a/astrid/src/androidTest/java/com/todoroo/astrid/dao/MetadataDaoTests.java b/astrid/src/androidTest/java/com/todoroo/astrid/dao/MetadataDaoTests.java index 87c4c29b2..8edb5642c 100644 --- a/astrid/src/androidTest/java/com/todoroo/astrid/dao/MetadataDaoTests.java +++ b/astrid/src/androidTest/java/com/todoroo/astrid/dao/MetadataDaoTests.java @@ -6,13 +6,14 @@ package com.todoroo.astrid.dao; import com.todoroo.andlib.data.Property; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Query; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.test.DatabaseTestCase; +import java.util.List; + import javax.inject.Inject; public class MetadataDaoTests extends DatabaseTestCase { @@ -34,20 +35,14 @@ public class MetadataDaoTests extends DatabaseTestCase { * Test basic creation, fetch, and save */ public void testCrud() throws Exception { - TodorooCursor cursor = metadataDao.query( - Query.select(Metadata.ID)); - assertEquals(0, cursor.getCount()); - cursor.close(); + assertTrue(metadataDao.toList(Query.select(Metadata.ID)).isEmpty()); // create "happy" Metadata metadata = new Metadata(); metadata.setTask(1L); metadata.setKey("happy"); assertTrue(metadataDao.persist(metadata)); - cursor = metadataDao.query( - Query.select(Metadata.ID)); - assertEquals(1, cursor.getCount()); - cursor.close(); + assertEquals(1, metadataDao.toList(Query.select(Metadata.ID)).size()); long happyId = metadata.getId(); assertNotSame(Metadata.NO_ID, happyId); metadata = metadataDao.fetch(happyId, KEYS); @@ -58,19 +53,14 @@ public class MetadataDaoTests extends DatabaseTestCase { metadata.setTask(1L); metadata.setKey("sad"); assertTrue(metadataDao.persist(metadata)); - cursor = metadataDao.query(Query.select(Metadata.ID)); - assertEquals(2, cursor.getCount()); - cursor.close(); + assertEquals(2, metadataDao.toList(Query.select(Metadata.ID)).size()); // rename sad to melancholy long sadId = metadata.getId(); assertNotSame(Metadata.NO_ID, sadId); metadata.setKey("melancholy"); assertTrue(metadataDao.persist(metadata)); - cursor = metadataDao.query( - Query.select(Metadata.ID)); - assertEquals(2, cursor.getCount()); - cursor.close(); + assertEquals(2, metadataDao.toList(Query.select(Metadata.ID)).size()); // check state metadata = metadataDao.fetch(happyId, KEYS); @@ -80,13 +70,9 @@ public class MetadataDaoTests extends DatabaseTestCase { // delete sad assertTrue(metadataDao.delete(sadId)); - cursor = metadataDao.query( - Query.select(KEYS)); - assertEquals(1, cursor.getCount()); - cursor.moveToFirst(); - metadata = new Metadata(cursor); - assertEquals("happy", metadata.getKey()); - cursor.close(); + List metadataList = metadataDao.toList(Query.select(KEYS)); + assertEquals(1, metadataList.size()); + assertEquals("happy", metadataList.get(0).getKey()); } /** @@ -109,29 +95,15 @@ public class MetadataDaoTests extends DatabaseTestCase { metadata.setTask(1L); assertTrue(metadataDao.persist(metadata)); + List metadataList = metadataDao.toList(Query.select(KEYS).where(MetadataCriteria.byTask(1))); + assertEquals(2, metadataList.size()); + assertEquals("with1", metadataList.get(0).getKey()); + assertEquals("with1", metadataList.get(1).getKey()); + + assertTrue(metadataDao.toList(Query.select(KEYS).where(MetadataCriteria.byTask(3))).isEmpty()); - TodorooCursor cursor = metadataDao.query( - Query.select(KEYS).where(MetadataCriteria.byTask(1))); - assertEquals(2, cursor.getCount()); - cursor.moveToFirst(); - metadata = new Metadata(cursor); - assertEquals("with1", metadata.getKey()); - cursor.moveToNext(); - metadata = new Metadata(cursor); - assertEquals("with1", metadata.getKey()); - cursor.close(); - - cursor = metadataDao.query( - Query.select(KEYS).where(MetadataCriteria.byTask(3))); - assertEquals(0, cursor.getCount()); - cursor.close(); - - int deleted = metadataDao.deleteWhere(MetadataCriteria.byTask(1)); - assertEquals(2, deleted); - cursor = metadataDao.query( - Query.select(KEYS)); - assertEquals(1, cursor.getCount()); - cursor.close(); + assertEquals(2, metadataDao.deleteWhere(MetadataCriteria.byTask(1))); + assertEquals(1, metadataDao.toList(Query.select(KEYS)).size()); } public void testDontSaveMetadataWithoutTaskId() { diff --git a/astrid/src/main/java/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java b/astrid/src/main/java/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java index 0004cabbd..ed842bf04 100644 --- a/astrid/src/main/java/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java +++ b/astrid/src/main/java/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java @@ -7,9 +7,9 @@ package com.todoroo.astrid.gtasks; import android.text.TextUtils; +import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.data.Property.IntegerProperty; import com.todoroo.andlib.data.Property.LongProperty; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Functions; import com.todoroo.andlib.sql.Order; @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -149,31 +150,26 @@ public class GtasksTaskListUpdater extends OrderedMetadataListUpdater()); } - private void orderAndIndentHelper(String listId, AtomicLong order, long parent, int indentLevel, - HashSet alreadyChecked) { - TodorooCursor metadata = metadataDao.query(Query.select(Metadata.PROPERTIES) - .where(Criterion.and(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY), - GtasksMetadata.LIST_ID.eq(listId), GtasksMetadata.PARENT_TASK.eq(parent))) - .orderBy(Order.asc(Functions.cast(GtasksMetadata.GTASKS_ORDER, "INTEGER")))); //$NON-NLS-1$ - try { - if (metadata.getCount() > 0) { - for (metadata.moveToFirst(); !metadata.isAfterLast(); metadata.moveToNext()) { - Metadata curr = new Metadata(metadata); - if(alreadyChecked.contains(curr.getTask())) { - continue; + private void orderAndIndentHelper(final String listId, final AtomicLong order, final long parent, final int indentLevel, final Set alreadyChecked) { + Query query = Query.select(Metadata.PROPERTIES).where(Criterion.and( + Metadata.KEY.eq(GtasksMetadata.METADATA_KEY), + GtasksMetadata.LIST_ID.eq(listId), + GtasksMetadata.PARENT_TASK.eq(parent))) + .orderBy(Order.asc(Functions.cast(GtasksMetadata.GTASKS_ORDER, "INTEGER"))); + metadataDao.query(query, new Callback() { + @Override + public void apply(Metadata curr) { + if (!alreadyChecked.contains(curr.getTask())) { + curr.setValue(GtasksMetadata.INDENT, indentLevel); + curr.setValue(GtasksMetadata.ORDER, order.getAndIncrement()); + metadataDao.saveExisting(curr); + alreadyChecked.add(curr.getTask()); + + orderAndIndentHelper(listId, order, curr.getTask(), indentLevel + 1, alreadyChecked); + } } - - curr.setValue(GtasksMetadata.INDENT, indentLevel); - curr.setValue(GtasksMetadata.ORDER, order.getAndIncrement()); - metadataDao.saveExisting(curr); - alreadyChecked.add(curr.getTask()); - - orderAndIndentHelper(listId, order, curr.getTask(), indentLevel + 1, alreadyChecked); } - } - } finally { - metadata.close(); - } + ); } void updateParentSiblingMapsFor(StoreObject list) { diff --git a/astrid/src/main/java/com/todoroo/astrid/notes/EditNoteActivity.java b/astrid/src/main/java/com/todoroo/astrid/notes/EditNoteActivity.java index 31dc6c8d7..3094cc52d 100644 --- a/astrid/src/main/java/com/todoroo/astrid/notes/EditNoteActivity.java +++ b/astrid/src/main/java/com/todoroo/astrid/notes/EditNoteActivity.java @@ -32,8 +32,6 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import com.todoroo.andlib.data.Callback; -import com.todoroo.andlib.data.TodorooCursor; -import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.actfm.ActFmCameraModule; import com.todoroo.astrid.actfm.ActFmCameraModule.CameraResultCallback; @@ -41,7 +39,6 @@ import com.todoroo.astrid.actfm.ActFmCameraModule.ClearImageCallback; import com.todoroo.astrid.activity.AstridActivity; import com.todoroo.astrid.activity.TaskEditFragment; import com.todoroo.astrid.dao.MetadataDao; -import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.dao.UserActivityDao; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.RemoteModel; @@ -260,18 +257,12 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene private void setUpListAdapter() { items.clear(); this.removeAllViews(); - TodorooCursor notes = metadataDao.query( - Query.select(Metadata.PROPERTIES).where( - MetadataCriteria.byTaskAndwithKey(task.getId(), - NoteMetadata.METADATA_KEY))); - try { - for(notes.moveToFirst(); !notes.isAfterLast(); notes.moveToNext()) { - Metadata metadata = new Metadata(notes); + metadataDao.byTaskAndKey(task.getId(), NoteMetadata.METADATA_KEY, new Callback() { + @Override + public void apply(Metadata metadata) { items.add(NoteOrUpdate.fromMetadata(metadata)); } - } finally { - notes.close(); - } + }); userActivityDao.getCommentsForTask(task.getUuid(), new Callback() { @Override diff --git a/astrid/src/main/java/com/todoroo/astrid/provider/Astrid2TaskProvider.java b/astrid/src/main/java/com/todoroo/astrid/provider/Astrid2TaskProvider.java index 09ff9c910..e0becec76 100644 --- a/astrid/src/main/java/com/todoroo/astrid/provider/Astrid2TaskProvider.java +++ b/astrid/src/main/java/com/todoroo/astrid/provider/Astrid2TaskProvider.java @@ -12,18 +12,17 @@ import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; +import com.google.common.base.Joiner; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.core.SortHelper; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; -import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.tags.TagService; -import com.todoroo.astrid.tags.TaskToTagMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -271,21 +270,6 @@ public class Astrid2TaskProvider extends InjectingContentProvider { * @return empty string if no tags, otherwise string */ private String getTagsAsString(long taskId, String separator) { - StringBuilder tagBuilder = new StringBuilder(); - TodorooCursor tags = tagService.get().getTags(taskId); - try { - int length = tags.getCount(); - for (int i = 0; i < length; i++) { - tags.moveToNext(); - Metadata metadata = new Metadata(tags); - tagBuilder.append(metadata.getValue(TaskToTagMetadata.TAG_NAME)); - if (i < length - 1) { - tagBuilder.append(separator); - } - } - } finally { - tags.close(); - } - return tagBuilder.toString(); + return Joiner.on(separator).join(tagService.get().getTagNames(taskId)); } } diff --git a/astrid/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java b/astrid/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java index 5632edabc..a661e02c3 100644 --- a/astrid/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java +++ b/astrid/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java @@ -1,6 +1,5 @@ package com.todoroo.astrid.service; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.dao.MetadataDao; @@ -10,6 +9,8 @@ import com.todoroo.astrid.data.Task; import com.todoroo.astrid.gcal.GCalHelper; import com.todoroo.astrid.gtasks.GtasksMetadata; +import java.util.List; + import javax.inject.Inject; public class TaskDuplicator { @@ -50,31 +51,26 @@ public class TaskDuplicator { } newTask.clearValue(Task.ID); newTask.clearValue(Task.UUID); - TodorooCursor cursor = metadataDao.query( - Query.select(Metadata.PROPERTIES).where(MetadataDao.MetadataCriteria.byTask(task.getId()))); - try { - if(cursor.getCount() > 0) { - newTask.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true); - taskService.save(newTask); - long newId = newTask.getId(); - for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { - Metadata metadata = new Metadata(cursor); - if(!metadata.containsNonNullValue(Metadata.KEY)) { - continue; - } + List metadataList = metadataDao.toList(Query.select(Metadata.PROPERTIES).where(MetadataDao.MetadataCriteria.byTask(task.getId()))); - if(GtasksMetadata.METADATA_KEY.equals(metadata.getKey())) { - metadata.setValue(GtasksMetadata.ID, ""); //$NON-NLS-1$ - } + if (!metadataList.isEmpty()) { + newTask.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true); + taskService.save(newTask); + long newId = newTask.getId(); + for (Metadata metadata : metadataList) { + if(!metadata.containsNonNullValue(Metadata.KEY)) { + continue; + } - metadata.setTask(newId); - metadata.clearValue(Metadata.ID); - metadataDao.createNew(metadata); + if(GtasksMetadata.METADATA_KEY.equals(metadata.getKey())) { + metadata.setValue(GtasksMetadata.ID, ""); //$NON-NLS-1$ } + + metadata.setTask(newId); + metadata.clearValue(Metadata.ID); + metadataDao.createNew(metadata); } - } finally { - cursor.close(); } return newTask; } diff --git a/astrid/src/main/java/com/todoroo/astrid/tags/TagService.java b/astrid/src/main/java/com/todoroo/astrid/tags/TagService.java index c84962f15..af5eb6b10 100644 --- a/astrid/src/main/java/com/todoroo/astrid/tags/TagService.java +++ b/astrid/src/main/java/com/todoroo/astrid/tags/TagService.java @@ -9,7 +9,6 @@ import android.text.TextUtils; import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.data.Property.CountProperty; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Functions; import com.todoroo.andlib.sql.Join; @@ -60,41 +59,44 @@ public final class TagService { * @return empty array if no tags, otherwise array */ public TagData[] getGroupedTags(Order order, Criterion activeStatus) { - Criterion criterion = Criterion.and(activeStatus, MetadataCriteria.withKey(TaskToTagMetadata.KEY)); Query query = Query.select(TaskToTagMetadata.TAG_NAME, TaskToTagMetadata.TAG_UUID, COUNT). - join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). - where(criterion). - orderBy(order).groupBy(TaskToTagMetadata.TAG_NAME); - TodorooCursor cursor = metadataDao.query(query); - try { - ArrayList array = new ArrayList<>(); - for (int i = 0; i < cursor.getCount(); i++) { - cursor.moveToNext(); - TagData tag = tagFromUUID(cursor.get(TaskToTagMetadata.TAG_UUID)); + join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). + where(Criterion.and( + activeStatus, + MetadataCriteria.withKey(TaskToTagMetadata.KEY))). + orderBy(order).groupBy(TaskToTagMetadata.TAG_NAME); + final List array = new ArrayList<>(); + metadataDao.query(query, new Callback() { + @Override + public void apply(Metadata metadata) { + TagData tag = tagFromUUID(metadata.getValue(TaskToTagMetadata.TAG_UUID)); if (tag != null) { array.add(tag); } } - return (TagData[]) array.toArray(); - } finally { - cursor.close(); - } + }); + return (TagData[]) array.toArray(); } private TagData tagFromUUID(String uuid) { return tagDataDao.getByUuid(uuid, TagData.PROPERTIES); } - /** - * Return tags on the given task - * @return cursor. PLEASE CLOSE THE CURSOR! - */ - public TodorooCursor getTags(long taskId) { - Criterion criterion = Criterion.and(MetadataCriteria.withKey(TaskToTagMetadata.KEY), + public List getTagNames(long taskId) { + Query query = Query.select(TaskToTagMetadata.TAG_NAME, TaskToTagMetadata.TAG_UUID).where( + Criterion.and( + MetadataCriteria.withKey(TaskToTagMetadata.KEY), Metadata.DELETION_DATE.eq(0), - MetadataCriteria.byTask(taskId)); - Query query = Query.select(TaskToTagMetadata.TAG_NAME, TaskToTagMetadata.TAG_UUID).where(criterion).orderBy(Order.asc(Functions.upper(TaskToTagMetadata.TAG_NAME))); - return metadataDao.query(query); + MetadataCriteria.byTask(taskId))) + .orderBy(Order.asc(Functions.upper(TaskToTagMetadata.TAG_NAME))); + final List tagNames = new ArrayList<>(); + metadataDao.query(query, new Callback() { + @Override + public void apply(Metadata entry) { + tagNames.add(entry.getValue(TaskToTagMetadata.TAG_NAME)); + } + }); + return tagNames; } /** @@ -118,23 +120,16 @@ public final class TagService { * given tag, return that. Otherwise, return the argument */ public String getTagWithCase(String tag) { - String tagWithCase = tag; - TodorooCursor tagMetadata = metadataDao.query(Query.select(TaskToTagMetadata.TAG_NAME).where(TagService.tagEqIgnoreCase(tag, Criterion.all)).limit(1)); - try { - if (tagMetadata.getCount() > 0) { - tagMetadata.moveToFirst(); - Metadata tagMatch = new Metadata(tagMetadata); - tagWithCase = tagMatch.getValue(TaskToTagMetadata.TAG_NAME); - } else { - TagData tagData = tagDataDao.getTagByName(tag, TagData.NAME); - if (tagData != null) { - tagWithCase = tagData.getName(); - } - } - } finally { - tagMetadata.close(); + Metadata tagMetadata = metadataDao.getFirst(Query.select(TaskToTagMetadata.TAG_NAME).where(tagEqIgnoreCase(tag, Criterion.all)).limit(1)); + if (tagMetadata != null) { + return tagMetadata.getValue(TaskToTagMetadata.TAG_NAME); + } + + TagData tagData = tagDataDao.getTagByName(tag, TagData.NAME); + if (tagData != null) { + return tagData.getName(); } - return tagWithCase; + return tag; } private static Criterion tagEqIgnoreCase(String tag, Criterion additionalCriterion) { diff --git a/astrid/src/main/java/com/todoroo/astrid/tags/TagsControlSet.java b/astrid/src/main/java/com/todoroo/astrid/tags/TagsControlSet.java index 58ea83b1b..d1797d602 100644 --- a/astrid/src/main/java/com/todoroo/astrid/tags/TagsControlSet.java +++ b/astrid/src/main/java/com/todoroo/astrid/tags/TagsControlSet.java @@ -24,7 +24,7 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import com.todoroo.andlib.data.AbstractModel; -import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DateUtilities; @@ -248,17 +248,7 @@ public final class TagsControlSet extends PopupControlSet { public void readFromTask(Task task) { super.readFromTask(task); if(model.getId() != AbstractModel.NO_ID) { - TodorooCursor cursor = tagService.getTags(model.getId()); - LinkedHashSet tags = new LinkedHashSet<>(cursor.getCount()); - try { - for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { - String tag = cursor.get(TaskToTagMetadata.TAG_NAME); - tags.add(tag); - } - } finally { - cursor.close(); - } - model.putTransitory(TRANSITORY_TAGS, tags); + model.putTransitory(TRANSITORY_TAGS, new LinkedHashSet<>(tagService.getTagNames(model.getId()))); refreshDisplayView(); } } @@ -339,17 +329,18 @@ public final class TagsControlSet extends PopupControlSet { * Save the given array of tags into the database */ private void synchronizeTags(long taskId, String taskUuid, Set tags) { - HashSet existingLinks = new HashSet<>(); - TodorooCursor links = metadataDao.query(Query.select(Metadata.PROPERTIES) - .where(Criterion.and(TaskToTagMetadata.TASK_UUID.eq(taskUuid), Metadata.DELETION_DATE.eq(0)))); - try { - for (links.moveToFirst(); !links.isAfterLast(); links.moveToNext()) { - Metadata link = new Metadata(links); + Query query = Query.select(Metadata.PROPERTIES).where( + Criterion.and( + TaskToTagMetadata.TASK_UUID.eq(taskUuid), + Metadata.DELETION_DATE.eq(0)) + ); + final HashSet existingLinks = new HashSet<>(); + metadataDao.query(query, new Callback() { + @Override + public void apply(Metadata link) { existingLinks.add(link.getValue(TaskToTagMetadata.TAG_UUID)); } - } finally { - links.close(); - } + }); for (String tag : tags) { TagData tagData = tagDataDao.getTagByName(tag, TagData.NAME, TagData.UUID);