Remove GtasksMetadataService

pull/437/head
Alex Baker 8 years ago
parent 7c84c3c1b6
commit 4ba4ce9ba4

@ -22,7 +22,6 @@ import javax.inject.Inject;
@SuppressWarnings("nls")
public class GtasksIndentActionTest extends DatabaseTestCase {
@Inject GtasksMetadataService gtasksMetadataService;
@Inject GtasksListService gtasksListService;
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject MetadataDao metadataDao;
@ -173,7 +172,7 @@ public class GtasksIndentActionTest extends DatabaseTestCase {
}
private void thenExpectIndentationLevel(Task targetTask, int expected) {
Metadata metadata = gtasksMetadataService.getActiveTaskMetadata(targetTask.getId());
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(targetTask.getId(), GtasksMetadata.METADATA_KEY);
assertNotNull("task has metadata", metadata);
int indentation = metadata.getValue(GtasksMetadata.INDENT);
assertTrue("indentation: " + indentation,

@ -50,7 +50,6 @@ public class GtasksMetadataServiceTest extends DatabaseTestCase {
}
@Inject GtasksTestPreferenceService preferences;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject MetadataDao metadataDao;
@Inject TaskService taskService;
@Inject GtasksMetadata gtasksMetadata;
@ -101,7 +100,7 @@ public class GtasksMetadataServiceTest extends DatabaseTestCase {
}
private void whenSearchForMetadata() {
metadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
metadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
}
private Task taskWithMetadata(String id) {

@ -26,7 +26,6 @@ public class GtasksTaskListUpdaterTest extends DatabaseTestCase {
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject GtasksListService gtasksListService;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject MetadataDao metadataDao;
@Inject TaskService taskService;
@Inject GtasksMetadata gtasksMetadata;
@ -87,14 +86,14 @@ public class GtasksTaskListUpdaterTest extends DatabaseTestCase {
// --- helpers
private void thenExpectMetadataIndentAndOrder(Task task, long order, int indent) {
Metadata metadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
assertNotNull("metadata was found", metadata);
assertEquals("order", order, metadata.getValue(GtasksMetadata.ORDER).longValue());
assertEquals("indentation", indent, (int)metadata.getValue(GtasksMetadata.INDENT));
}
private void thenExpectMetadataParent(Task task, Task expectedParent) {
Metadata metadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
long parent = metadata.getValue(GtasksMetadata.PARENT_TASK);
if(expectedParent == null)
assertEquals("Task " + task.getTitle() + " parent none", 0, parent);

@ -25,7 +25,6 @@ public class GtasksTaskMovingTest extends DatabaseTestCase {
private static final int VALUE_UNSET = -1;
@Inject GtasksListService gtasksListService;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject MetadataDao metadataDao;
@Inject TaskService taskService;
@ -237,7 +236,7 @@ public class GtasksTaskMovingTest extends DatabaseTestCase {
}
private void thenExpectMetadataOrderAndIndent(Task task, long order, int indent) {
Metadata metadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
assertNotNull("metadata was found", metadata);
assertEquals("order", order, metadata.getValue(GtasksMetadata.ORDER).longValue());
assertEquals("indentation", indent, (int)metadata.getValue(GtasksMetadata.INDENT));

@ -1,229 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gtasks;
import android.content.ContentValues;
import android.text.TextUtils;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Field;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer;
import com.todoroo.astrid.gtasks.OrderedMetadataListUpdater.OrderedListIterator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Service for working with GTasks metadata
*
* @author Tim Su <tim@todoroo.com>
*
*/
@Singleton
public final class GtasksMetadataService {
private final TaskDao taskDao;
private final MetadataDao metadataDao;
@Inject
public GtasksMetadataService(TaskDao taskDao, MetadataDao metadataDao) {
this.taskDao = taskDao;
this.metadataDao = metadataDao;
}
/**
* Clears metadata information. Used when user logs out of sync provider
*/
public void clearMetadata() {
metadataDao.deleteWhere(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY));
}
/**
* Saves a task and its metadata
*/
public void saveTaskAndMetadata(GtasksTaskContainer task) {
task.prepareForSaving();
taskDao.save(task.task);
synchronizeMetadata(task.task.getId(), task.metadata, GtasksMetadata.METADATA_KEY);
}
/**
* Reads metadata out of a task
* @return null if no metadata found
*/
public Metadata getActiveTaskMetadata(long taskId) {
return metadataDao.getFirst(Query.select(Metadata.PROPERTIES).where(Criterion.and(
MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY),
MetadataCriteria.isActive())));
}
public List<Metadata> getDeleted(long taskId) {
return metadataDao.toList(Criterion.and(
MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY),
MetadataCriteria.isDeleted()));
}
/**
* Synchronize metadata for given task id. Deletes rows in database that
* are not identical to those in the metadata list, creates rows that
* have no match.
*
* @param taskId id of task to perform synchronization on
* @param metadata list of new metadata items to save
* @param metadataKey metadata key
*/
private void synchronizeMetadata(long taskId, ArrayList<Metadata> metadata, String metadataKey) {
final Set<ContentValues> newMetadataValues = new HashSet<>();
for(Metadata metadatum : metadata) {
metadatum.setTask(taskId);
metadatum.clearValue(Metadata.ID);
newMetadataValues.add(metadatum.getMergedValues());
}
metadataDao.byTaskAndKey(taskId, metadataKey, new Callback<Metadata>() {
@Override
public void apply(Metadata item) {
long id = item.getId();
// clear item id when matching with incoming values
item.clearValue(Metadata.ID);
ContentValues itemMergedValues = item.getMergedValues();
if(newMetadataValues.contains(itemMergedValues)) {
newMetadataValues.remove(itemMergedValues);
} else {
// not matched. cut it
metadataDao.delete(id);
}
}
});
// everything that remains shall be written
for(ContentValues values : newMetadataValues) {
Metadata item = new Metadata();
item.mergeWith(values);
metadataDao.persist(item);
}
}
public synchronized void findLocalMatch(GtasksTaskContainer remoteTask) {
if(remoteTask.task.getId() != Task.NO_ID) {
return;
}
Metadata metadata = getMetadataByGtaskId(remoteTask.gtaskMetadata.getValue(GtasksMetadata.ID));
if (metadata != null) {
remoteTask.task.setId(metadata.getValue(Metadata.TASK));
remoteTask.task.setUuid(taskDao.uuidFromLocalId(remoteTask.task.getId()));
remoteTask.gtaskMetadata = metadata;
}
}
public long localIdForGtasksId(String gtasksId) {
Metadata metadata = getMetadataByGtaskId(gtasksId);
return metadata == null ? AbstractModel.NO_ID : metadata.getTask();
}
private Metadata getMetadataByGtaskId(String gtaskId) {
return metadataDao.getFirst(Query.select(Metadata.PROPERTIES).where(Criterion.and(
Metadata.KEY.eq(GtasksMetadata.METADATA_KEY),
GtasksMetadata.ID.eq(gtaskId))));
}
// --- list iterating helpers
public void iterateThroughList(GtasksList list, OrderedListIterator iterator) {
String listId = list.getRemoteId();
iterateThroughList(listId, iterator, 0, false);
}
private void iterateThroughList(String listId, final OrderedListIterator iterator, long startAtOrder, boolean reverse) {
Field orderField = Functions.cast(GtasksMetadata.ORDER, "LONG");
Order order = reverse ? Order.desc(orderField) : Order.asc(orderField);
Criterion startAtCriterion = reverse ? Functions.cast(GtasksMetadata.ORDER, "LONG").lt(startAtOrder) :
Functions.cast(GtasksMetadata.ORDER, "LONG").gt(startAtOrder - 1);
Query query = Query.select(Metadata.PROPERTIES).where(Criterion.and(
MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
GtasksMetadata.LIST_ID.eq(listId),
startAtCriterion)).
orderBy(order);
metadataDao.query(query, new Callback<Metadata>() {
@Override
public void apply(Metadata entry) {
long taskId = entry.getValue(Metadata.TASK);
Metadata metadata = getActiveTaskMetadata(taskId);
if(metadata != null) {
iterator.processTask(taskId, metadata);
}
}
});
}
/**
* Gets the remote id string of the parent task
*/
public String getRemoteParentId(Metadata gtasksMetadata) {
String parent = null;
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.PARENT_TASK)) {
long parentId = gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK);
Metadata parentMetadata = getActiveTaskMetadata(parentId);
if (parentMetadata != null && parentMetadata.containsNonNullValue(GtasksMetadata.ID)) {
parent = parentMetadata.getValue(GtasksMetadata.ID);
if (TextUtils.isEmpty(parent)) {
parent = null;
}
}
}
return parent;
}
/**
* Gets the remote id string of the previous sibling task
*/
public String getRemoteSiblingId(String listId, Metadata gtasksMetadata) {
final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getValue(GtasksMetadata.INDENT));
final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK));
final AtomicReference<String> sibling = new AtomicReference<>();
OrderedListIterator iterator = new OrderedListIterator() {
@Override
public void processTask(long taskId, Metadata metadata) {
Task t = taskDao.fetch(taskId, Task.TITLE, Task.DELETION_DATE);
if (t == null || t.isDeleted()) {
return;
}
int currIndent = metadata.getValue(GtasksMetadata.INDENT);
long currParent = metadata.getValue(GtasksMetadata.PARENT_TASK);
if (currIndent == indentToMatch.get() && currParent == parentToMatch.get()) {
if (sibling.get() == null) {
sibling.set(metadata.getValue(GtasksMetadata.ID));
}
}
}
};
this.iterateThroughList(listId, iterator, gtasksMetadata.getValue(GtasksMetadata.ORDER), true);
return sibling.get();
}
}

@ -42,15 +42,12 @@ public class GtasksTaskListUpdater extends OrderedMetadataListUpdater<GtasksList
final HashMap<Long, String> localToRemoteIdMap =
new HashMap<>();
private final GtasksMetadataService gtasksMetadataService;
private final GtasksSyncService gtasksSyncService;
private final MetadataDao metadataDao;
@Inject
public GtasksTaskListUpdater(GtasksMetadataService gtasksMetadataService, GtasksSyncService gtasksSyncService,
MetadataDao metadataDao) {
public GtasksTaskListUpdater(GtasksSyncService gtasksSyncService, MetadataDao metadataDao) {
super(metadataDao);
this.gtasksMetadataService = gtasksMetadataService;
this.gtasksSyncService = gtasksSyncService;
this.metadataDao = metadataDao;
}
@ -74,7 +71,7 @@ public class GtasksTaskListUpdater extends OrderedMetadataListUpdater<GtasksList
@Override
protected Metadata getTaskMetadata(long taskId) {
return gtasksMetadataService.getActiveTaskMetadata(taskId);
return metadataDao.getFirstActiveByTaskAndKey(taskId, GtasksMetadata.METADATA_KEY);
}
@Override
protected Metadata createEmptyMetadata(GtasksList list, long taskId) {
@ -90,7 +87,8 @@ public class GtasksTaskListUpdater extends OrderedMetadataListUpdater<GtasksList
@Override
protected void iterateThroughList(GtasksList list, OrderedListIterator iterator) {
gtasksMetadataService.iterateThroughList(list, iterator);
String listId = list.getRemoteId();
gtasksSyncService.iterateThroughList(listId, iterator, 0, false);
}
@Override
@ -131,7 +129,7 @@ public class GtasksTaskListUpdater extends OrderedMetadataListUpdater<GtasksList
final AtomicLong previousTask = new AtomicLong(Task.NO_ID);
final AtomicInteger previousIndent = new AtomicInteger(-1);
gtasksMetadataService.iterateThroughList(list, new OrderedListIterator() {
iterateThroughList(list, new OrderedListIterator() {
@Override
public void processTask(long taskId, Metadata metadata) {
int indent = metadata.getValue(GtasksMetadata.INDENT);

@ -8,6 +8,12 @@ package com.todoroo.astrid.gtasks.sync;
import android.content.ContentValues;
import android.text.TextUtils;
import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Field;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.MetadataDao;
@ -16,8 +22,8 @@ import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.OrderedMetadataListUpdater;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.HttpNotFoundException;
@ -26,7 +32,11 @@ import com.todoroo.astrid.gtasks.api.MoveRequest;
import org.tasks.gtasks.SyncAdapterHelper;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -39,7 +49,6 @@ public class GtasksSyncService {
private static final String DEFAULT_LIST = "@default"; //$NON-NLS-1$
private final MetadataDao metadataDao;
private final GtasksMetadataService gtasksMetadataService;
private final TaskDao taskDao;
private final GtasksPreferenceService gtasksPreferenceService;
private final GtasksMetadata gtasksMetadataFactory;
@ -48,12 +57,11 @@ public class GtasksSyncService {
private final SyncAdapterHelper syncAdapterHelper;
@Inject
public GtasksSyncService(MetadataDao metadataDao, GtasksMetadataService gtasksMetadataService,
TaskDao taskDao, GtasksPreferenceService gtasksPreferenceService,
public GtasksSyncService(MetadataDao metadataDao, TaskDao taskDao,
GtasksPreferenceService gtasksPreferenceService,
GtasksMetadata gtasksMetadataFactory, GtasksInvoker gtasksInvoker,
SyncAdapterHelper syncAdapterHelper) {
this.metadataDao = metadataDao;
this.gtasksMetadataService = gtasksMetadataService;
this.taskDao = taskDao;
this.gtasksPreferenceService = gtasksPreferenceService;
this.gtasksMetadataFactory = gtasksMetadataFactory;
@ -152,12 +160,12 @@ public class GtasksSyncService {
* Synchronize with server when data changes
*/
public void pushTaskOnSave(Task task, ContentValues values, GtasksInvoker invoker) throws IOException {
for (Metadata deleted : gtasksMetadataService.getDeleted(task.getId())) {
for (Metadata deleted : getDeleted(task.getId())) {
gtasksInvoker.deleteGtask(deleted.getValue(GtasksMetadata.LIST_ID), deleted.getValue(GtasksMetadata.ID));
metadataDao.delete(deleted.getId());
}
Metadata gtasksMetadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
Metadata gtasksMetadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
com.google.api.services.tasks.model.Task remoteModel;
boolean newlyCreated = false;
@ -232,8 +240,8 @@ public class GtasksSyncService {
return;
}
} else {
String parent = gtasksMetadataService.getRemoteParentId(gtasksMetadata);
String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, gtasksMetadata);
String parent = getRemoteParentId(gtasksMetadata);
String priorSibling = getRemoteSiblingId(listId, gtasksMetadata);
com.google.api.services.tasks.model.Task created = invoker.createGtask(listId, remoteModel, parent, priorSibling);
@ -258,8 +266,8 @@ public class GtasksSyncService {
String taskId = model.getValue(GtasksMetadata.ID);
String listId = model.getValue(GtasksMetadata.LIST_ID);
String parent = gtasksMetadataService.getRemoteParentId(model);
String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, model);
String parent = getRemoteParentId(model);
String priorSibling = getRemoteSiblingId(listId, model);
MoveRequest move = new MoveRequest(invoker, taskId, listId, parent, priorSibling);
com.google.api.services.tasks.model.Task result = move.push();
@ -270,4 +278,81 @@ public class GtasksSyncService {
metadataDao.saveExisting(model);
}
}
public void iterateThroughList(String listId, final OrderedMetadataListUpdater.OrderedListIterator iterator, long startAtOrder, boolean reverse) {
Field orderField = Functions.cast(GtasksMetadata.ORDER, "LONG");
Order order = reverse ? Order.desc(orderField) : Order.asc(orderField);
Criterion startAtCriterion = reverse ? Functions.cast(GtasksMetadata.ORDER, "LONG").lt(startAtOrder) :
Functions.cast(GtasksMetadata.ORDER, "LONG").gt(startAtOrder - 1);
Query query = Query.select(Metadata.PROPERTIES).where(Criterion.and(
MetadataDao.MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
GtasksMetadata.LIST_ID.eq(listId),
startAtCriterion)).
orderBy(order);
metadataDao.query(query, new Callback<Metadata>() {
@Override
public void apply(Metadata entry) {
long taskId = entry.getValue(Metadata.TASK);
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(taskId, GtasksMetadata.METADATA_KEY);
if(metadata != null) {
iterator.processTask(taskId, metadata);
}
}
});
}
private List<Metadata> getDeleted(long taskId) {
return metadataDao.toList(Criterion.and(
MetadataDao.MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY),
MetadataDao.MetadataCriteria.isDeleted()));
}
/**
* Gets the remote id string of the parent task
*/
private String getRemoteParentId(Metadata gtasksMetadata) {
String parent = null;
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.PARENT_TASK)) {
long parentId = gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK);
Metadata parentMetadata = metadataDao.getFirstActiveByTaskAndKey(parentId, GtasksMetadata.METADATA_KEY);
if (parentMetadata != null && parentMetadata.containsNonNullValue(GtasksMetadata.ID)) {
parent = parentMetadata.getValue(GtasksMetadata.ID);
if (TextUtils.isEmpty(parent)) {
parent = null;
}
}
}
return parent;
}
/**
* Gets the remote id string of the previous sibling task
*/
private String getRemoteSiblingId(String listId, Metadata gtasksMetadata) {
final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getValue(GtasksMetadata.INDENT));
final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK));
final AtomicReference<String> sibling = new AtomicReference<>();
OrderedMetadataListUpdater.OrderedListIterator iterator = new OrderedMetadataListUpdater.OrderedListIterator() {
@Override
public void processTask(long taskId, Metadata metadata) {
Task t = taskDao.fetch(taskId, Task.TITLE, Task.DELETION_DATE);
if (t == null || t.isDeleted()) {
return;
}
int currIndent = metadata.getValue(GtasksMetadata.INDENT);
long currParent = metadata.getValue(GtasksMetadata.PARENT_TASK);
if (currIndent == indentToMatch.get() && currParent == parentToMatch.get()) {
if (sibling.get() == null) {
sibling.set(metadata.getValue(GtasksMetadata.ID));
}
}
}
};
iterateThroughList(listId, iterator, gtasksMetadata.getValue(GtasksMetadata.ORDER), true);
return sibling.get();
}
}

@ -3,7 +3,9 @@ package org.tasks.activities;
import android.content.DialogInterface;
import android.os.Bundle;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import org.tasks.R;
@ -17,7 +19,7 @@ public class ClearGtaskDataActivity extends InjectingAppCompatActivity {
@Inject DialogBuilder dialogBuilder;
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject MetadataDao metadataDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -29,7 +31,7 @@ public class ClearGtaskDataActivity extends InjectingAppCompatActivity {
public void onClick(DialogInterface dialog, int which) {
gtasksPreferenceService.clearLastSyncDate();
gtasksPreferenceService.setUserName(null);
gtasksMetadataService.clearMetadata();
metadataDao.deleteWhere(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY));
setResult(RESULT_OK);
}
})

@ -19,6 +19,7 @@ package org.tasks.gtasks;
import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SyncResult;
import android.os.Bundle;
@ -28,6 +29,7 @@ import com.google.api.services.tasks.model.TaskList;
import com.google.api.services.tasks.model.TaskLists;
import com.google.api.services.tasks.model.Tasks;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join;
@ -42,7 +44,6 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksList;
import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
@ -60,7 +61,9 @@ import org.tasks.time.DateTime;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
@ -85,10 +88,11 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
@Inject StoreObjectDao storeObjectDao;
@Inject GtasksSyncService gtasksSyncService;
@Inject GtasksListService gtasksListService;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject GtasksTaskListUpdater gtasksTaskListUpdater;
@Inject Preferences preferences;
@Inject GtasksInvoker gtasksInvoker;
@Inject TaskDao taskDao;
@Inject MetadataDao metadataDao;
public GoogleTaskSyncAdapter(Context context, boolean autoInitialize) {
@ -234,9 +238,9 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
if (!tasks.isEmpty()) {
for (com.google.api.services.tasks.model.Task t : tasks) {
GtasksTaskContainer container = new GtasksTaskContainer(t, listId, GtasksMetadata.createEmptyMetadataWithoutList(AbstractModel.NO_ID));
gtasksMetadataService.findLocalMatch(container);
findLocalMatch(container);
container.gtaskMetadata.setValue(GtasksMetadata.GTASKS_ORDER, Long.parseLong(t.getPosition()));
container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK, gtasksMetadataService.localIdForGtasksId(t.getParent()));
container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK, localIdForGtasksId(t.getParent()));
container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
write(container);
lastSyncDate = Math.max(lastSyncDate, container.getUpdateTime());
@ -250,6 +254,29 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
}
}
private long localIdForGtasksId(String gtasksId) {
Metadata metadata = getMetadataByGtaskId(gtasksId);
return metadata == null ? AbstractModel.NO_ID : metadata.getTask();
}
private void findLocalMatch(GtasksTaskContainer remoteTask) {
if(remoteTask.task.getId() != Task.NO_ID) {
return;
}
Metadata metadata = getMetadataByGtaskId(remoteTask.gtaskMetadata.getValue(GtasksMetadata.ID));
if (metadata != null) {
remoteTask.task.setId(metadata.getValue(Metadata.TASK));
remoteTask.task.setUuid(taskDao.uuidFromLocalId(remoteTask.task.getId()));
remoteTask.gtaskMetadata = metadata;
}
}
private Metadata getMetadataByGtaskId(String gtaskId) {
return metadataDao.getFirst(Query.select(Metadata.PROPERTIES).where(Criterion.and(
Metadata.KEY.eq(GtasksMetadata.METADATA_KEY),
GtasksMetadata.ID.eq(gtaskId))));
}
private void write(GtasksTaskContainer task) {
// merge astrid dates with google dates
@ -269,10 +296,62 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
if (!TextUtils.isEmpty(task.task.getTitle())) {
task.task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
task.task.putTransitory(TaskDao.TRANS_SUPPRESS_REFRESH, true);
gtasksMetadataService.saveTaskAndMetadata(task);
saveTaskAndMetadata(task);
}
}
/**
* Saves a task and its metadata
*/
private void saveTaskAndMetadata(GtasksTaskContainer task) {
task.prepareForSaving();
taskDao.save(task.task);
synchronizeMetadata(task.task.getId(), task.metadata, GtasksMetadata.METADATA_KEY);
}
/**
* Synchronize metadata for given task id. Deletes rows in database that
* are not identical to those in the metadata list, creates rows that
* have no match.
*
* @param taskId id of task to perform synchronization on
* @param metadata list of new metadata items to save
* @param metadataKey metadata key
*/
private void synchronizeMetadata(long taskId, ArrayList<Metadata> metadata, String metadataKey) {
final Set<ContentValues> newMetadataValues = new HashSet<>();
for(Metadata metadatum : metadata) {
metadatum.setTask(taskId);
metadatum.clearValue(Metadata.ID);
newMetadataValues.add(metadatum.getMergedValues());
}
metadataDao.byTaskAndKey(taskId, metadataKey, new Callback<Metadata>() {
@Override
public void apply(Metadata item) {
long id = item.getId();
// clear item id when matching with incoming values
item.clearValue(Metadata.ID);
ContentValues itemMergedValues = item.getMergedValues();
if(newMetadataValues.contains(itemMergedValues)) {
newMetadataValues.remove(itemMergedValues);
} else {
// not matched. cut it
metadataDao.delete(id);
}
}
});
// everything that remains shall be written
for(ContentValues values : newMetadataValues) {
Metadata item = new Metadata();
item.mergeWith(values);
metadataDao.persist(item);
}
}
static void mergeDates(Task remote, Task local) {
if (remote.hasDueDate() && local.hasDueTime()) {
DateTime oldDate = newDateTime(local.getDueDate());

@ -16,7 +16,6 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksList;
import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import org.tasks.R;
@ -45,7 +44,6 @@ public class GoogleTaskListFragment extends TaskEditControlFragment {
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject GtasksListService gtasksListService;
@Inject GtasksMetadataService gtasksMetadataService;
@Inject MetadataDao metadataDao;
@Inject Tracker tracker;
@ -69,7 +67,7 @@ public class GoogleTaskListFragment extends TaskEditControlFragment {
selectedList = new GtasksList(selectedStoreObject);
}
} else {
Metadata metadata = gtasksMetadataService.getActiveTaskMetadata(taskId);
Metadata metadata = metadataDao.getFirstActiveByTaskAndKey(taskId, GtasksMetadata.METADATA_KEY);
if (metadata != null) {
originalList = gtasksListService.getList(metadata.getValue(GtasksMetadata.LIST_ID));
}
@ -132,7 +130,7 @@ public class GoogleTaskListFragment extends TaskEditControlFragment {
return;
}
Metadata taskMetadata = gtasksMetadataService.getActiveTaskMetadata(task.getId());
Metadata taskMetadata = metadataDao.getFirstActiveByTaskAndKey(task.getId(), GtasksMetadata.METADATA_KEY);
if (taskMetadata == null) {
taskMetadata = GtasksMetadata.createEmptyMetadataWithoutList(task.getId());
} else if (!taskMetadata.getValue(GtasksMetadata.LIST_ID).equals(selectedList.getRemoteId())) {

@ -48,6 +48,12 @@ public class MetadataDao {
return dao.getFirst(query);
}
public Metadata getFirstActiveByTaskAndKey(long taskId, String key) {
return getFirst(Query.select(Metadata.PROPERTIES).where(Criterion.and(
MetadataCriteria.byTaskAndwithKey(taskId, key),
MetadataCriteria.isActive())));
}
public int update(Criterion where, Metadata template) {
return dao.update(where, template);
}

Loading…
Cancel
Save