mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
8.1 KiB
Java
215 lines
8.1 KiB
Java
/**
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.gtasks;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import com.todoroo.andlib.data.AbstractModel;
|
|
import com.todoroo.andlib.data.TodorooCursor;
|
|
import com.todoroo.andlib.service.Autowired;
|
|
import com.todoroo.andlib.service.ContextManager;
|
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
|
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.core.PluginServices;
|
|
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
|
|
import com.todoroo.astrid.data.Metadata;
|
|
import com.todoroo.astrid.data.StoreObject;
|
|
import com.todoroo.astrid.data.Task;
|
|
import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer;
|
|
import com.todoroo.astrid.subtasks.OrderedListUpdater.OrderedListIterator;
|
|
import com.todoroo.astrid.sync.SyncMetadataService;
|
|
import com.todoroo.astrid.sync.SyncProviderUtilities;
|
|
|
|
/**
|
|
* Service for working with GTasks metadata
|
|
*
|
|
* @author Tim Su <tim@todoroo.com>
|
|
*
|
|
*/
|
|
public final class GtasksMetadataService extends SyncMetadataService<GtasksTaskContainer> {
|
|
|
|
@Autowired private GtasksPreferenceService gtasksPreferenceService;
|
|
|
|
public GtasksMetadataService() {
|
|
super(ContextManager.getContext());
|
|
DependencyInjectionService.getInstance().inject(this);
|
|
}
|
|
|
|
@Override
|
|
public GtasksTaskContainer createContainerFromLocalTask(Task task,
|
|
ArrayList<Metadata> metadata) {
|
|
return new GtasksTaskContainer(task, metadata);
|
|
}
|
|
|
|
@Override
|
|
public Criterion getLocalMatchCriteria(GtasksTaskContainer remoteTask) {
|
|
return GtasksMetadata.ID.eq(remoteTask.gtaskMetadata.getValue(GtasksMetadata.ID));
|
|
}
|
|
|
|
@Override
|
|
public Criterion getMetadataCriteria() {
|
|
return MetadataCriteria.withKey(getMetadataKey());
|
|
}
|
|
|
|
@Override
|
|
public String getMetadataKey() {
|
|
return GtasksMetadata.METADATA_KEY;
|
|
}
|
|
|
|
@Override
|
|
public SyncProviderUtilities getUtilities() {
|
|
return gtasksPreferenceService;
|
|
}
|
|
|
|
@Override
|
|
public Criterion getMetadataWithRemoteId() {
|
|
return GtasksMetadata.ID.neq(""); //$NON-NLS-1$
|
|
}
|
|
|
|
@Override
|
|
public synchronized void findLocalMatch(GtasksTaskContainer remoteTask) {
|
|
if(remoteTask.task.getId() != Task.NO_ID)
|
|
return;
|
|
TodorooCursor<Metadata> cursor = metadataDao.query(Query.select(Metadata.PROPERTIES).
|
|
where(Criterion.and(MetadataCriteria.withKey(getMetadataKey()),
|
|
getLocalMatchCriteria(remoteTask))));
|
|
try {
|
|
if(cursor.getCount() == 0)
|
|
return;
|
|
cursor.moveToFirst();
|
|
remoteTask.task.setId(cursor.get(Metadata.TASK));
|
|
remoteTask.gtaskMetadata = new Metadata(cursor);
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
|
|
public long localIdForGtasksId(String gtasksId) {
|
|
TodorooCursor<Metadata> metadata = metadataDao.query(Query.select(Metadata.TASK).where(
|
|
Criterion.and(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY), GtasksMetadata.ID.eq(gtasksId))));
|
|
try {
|
|
if (metadata.getCount() > 0) {
|
|
metadata.moveToFirst();
|
|
return (new Metadata(metadata).getValue(Metadata.TASK));
|
|
} else {
|
|
return AbstractModel.NO_ID;
|
|
}
|
|
} finally {
|
|
metadata.close();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected TodorooCursor<Task> filterLocallyUpdated(TodorooCursor<Task> tasks, long lastSyncDate) {
|
|
HashSet<Long> taskIds = new HashSet<Long>();
|
|
for(tasks.moveToFirst(); !tasks.isAfterLast(); tasks.moveToNext())
|
|
taskIds.add(tasks.get(Task.ID));
|
|
|
|
TodorooCursor<Metadata> metadata = metadataDao.query(Query.select(Metadata.TASK).where(
|
|
Criterion.and(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
|
|
GtasksMetadata.LAST_SYNC.gt(lastSyncDate))));
|
|
for(metadata.moveToFirst(); !metadata.isAfterLast(); metadata.moveToNext())
|
|
taskIds.remove(metadata.get(Metadata.TASK));
|
|
|
|
return taskDao.query(Query.select(Task.ID).where(
|
|
Task.ID.in(taskIds.toArray(new Long[taskIds.size()]))));
|
|
}
|
|
|
|
// --- list iterating helpers
|
|
|
|
|
|
public void iterateThroughList(StoreObject list, OrderedListIterator iterator) {
|
|
String listId = list.getValue(GtasksList.REMOTE_ID);
|
|
iterateThroughList(listId, iterator, 0, false);
|
|
}
|
|
|
|
@SuppressWarnings("nls")
|
|
public void iterateThroughList(String listId, 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);
|
|
TodorooCursor<Metadata> cursor = PluginServices.getMetadataService().query(query);
|
|
try {
|
|
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
|
long taskId = cursor.get(Metadata.TASK);
|
|
Metadata metadata = getTaskMetadata(taskId);
|
|
if(metadata == null)
|
|
continue;
|
|
iterator.processTask(taskId, metadata);
|
|
}
|
|
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the remote id string of the parent task
|
|
* @param gtasksMetadata
|
|
* @return
|
|
*/
|
|
public String getRemoteParentId(Metadata gtasksMetadata) {
|
|
String parent = null;
|
|
if (gtasksMetadata.containsNonNullValue(GtasksMetadata.PARENT_TASK)) {
|
|
long parentId = gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK);
|
|
Metadata parentMetadata = getTaskMetadata(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
|
|
* @param listId
|
|
* @param gtasksMetadata
|
|
* @return
|
|
*/
|
|
public String getRemoteSiblingId(String listId, Metadata gtasksMetadata) {
|
|
final AtomicInteger indentToMatch = new AtomicInteger(gtasksMetadata.getValue(GtasksMetadata.INDENT).intValue());
|
|
final AtomicLong parentToMatch = new AtomicLong(gtasksMetadata.getValue(GtasksMetadata.PARENT_TASK).longValue());
|
|
final AtomicReference<String> sibling = new AtomicReference<String>();
|
|
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).intValue();
|
|
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();
|
|
}
|
|
|
|
}
|