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.
167 lines
5.6 KiB
Java
167 lines
5.6 KiB
Java
/**
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
*
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.gtasks;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import com.todoroo.andlib.data.Property.IntegerProperty;
|
|
import com.todoroo.andlib.data.Property.LongProperty;
|
|
import com.todoroo.andlib.sql.Criterion;
|
|
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.data.Metadata;
|
|
import com.todoroo.astrid.data.Task;
|
|
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
|
|
|
|
import org.tasks.injection.ApplicationScope;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import timber.log.Timber;
|
|
|
|
@ApplicationScope
|
|
public class GtasksTaskListUpdater extends OrderedMetadataListUpdater<GtasksList> {
|
|
|
|
/** map of task -> parent task */
|
|
final HashMap<Long, Long> parents = new HashMap<>();
|
|
|
|
/** map of task -> prior sibling */
|
|
final HashMap<Long, Long> siblings = new HashMap<>();
|
|
|
|
final HashMap<Long, String> localToRemoteIdMap =
|
|
new HashMap<>();
|
|
|
|
private final GtasksSyncService gtasksSyncService;
|
|
private final MetadataDao metadataDao;
|
|
|
|
@Inject
|
|
public GtasksTaskListUpdater(GtasksSyncService gtasksSyncService, MetadataDao metadataDao) {
|
|
super(metadataDao);
|
|
this.gtasksSyncService = gtasksSyncService;
|
|
this.metadataDao = metadataDao;
|
|
}
|
|
|
|
// --- overrides
|
|
|
|
@Override
|
|
protected IntegerProperty indentProperty() {
|
|
return GtasksMetadata.INDENT;
|
|
}
|
|
|
|
@Override
|
|
protected LongProperty orderProperty() {
|
|
return GtasksMetadata.ORDER;
|
|
}
|
|
|
|
@Override
|
|
protected LongProperty parentProperty() {
|
|
return GtasksMetadata.PARENT_TASK;
|
|
}
|
|
|
|
@Override
|
|
protected Metadata getTaskMetadata(long taskId) {
|
|
return metadataDao.getFirstActiveByTaskAndKey(taskId, GtasksMetadata.METADATA_KEY);
|
|
}
|
|
@Override
|
|
protected Metadata createEmptyMetadata(GtasksList list, long taskId) {
|
|
Metadata metadata = GtasksMetadata.createEmptyMetadataWithoutList(taskId);
|
|
metadata.setValue(GtasksMetadata.LIST_ID, list.getRemoteId());
|
|
return metadata;
|
|
}
|
|
|
|
@Override
|
|
protected void beforeIndent(GtasksList list) {
|
|
updateParentSiblingMapsFor(list);
|
|
}
|
|
|
|
@Override
|
|
protected void iterateThroughList(GtasksList list, OrderedListIterator iterator) {
|
|
String listId = list.getRemoteId();
|
|
gtasksSyncService.iterateThroughList(listId, iterator, 0, false);
|
|
}
|
|
|
|
@Override
|
|
protected void onMovedOrIndented(Metadata metadata) {
|
|
gtasksSyncService.triggerMoveForMetadata(metadata);
|
|
}
|
|
|
|
// --- used during synchronization
|
|
|
|
public void correctOrderAndIndentForList(String listId) {
|
|
orderAndIndentHelper(listId, new AtomicLong(0L), Task.NO_ID, 0,
|
|
new HashSet<>());
|
|
}
|
|
|
|
private void orderAndIndentHelper(final String listId, final AtomicLong order, final long parent, final int indentLevel, final Set<Long> 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, 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);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
void updateParentSiblingMapsFor(GtasksList list) {
|
|
final AtomicLong previousTask = new AtomicLong(Task.NO_ID);
|
|
final AtomicInteger previousIndent = new AtomicInteger(-1);
|
|
|
|
iterateThroughList(list, (taskId, metadata) -> {
|
|
int indent = metadata.getValue(GtasksMetadata.INDENT);
|
|
|
|
try {
|
|
long parent, sibling;
|
|
if(indent > previousIndent.get()) {
|
|
parent = previousTask.get();
|
|
sibling = Task.NO_ID;
|
|
} else if(indent == previousIndent.get()) {
|
|
sibling = previousTask.get();
|
|
parent = parents.get(sibling);
|
|
} else {
|
|
// move up once for each indent
|
|
sibling = previousTask.get();
|
|
for(int i = indent; i < previousIndent.get(); i++) {
|
|
sibling = parents.get(sibling);
|
|
}
|
|
if(parents.containsKey(sibling)) {
|
|
parent = parents.get(sibling);
|
|
} else {
|
|
parent = Task.NO_ID;
|
|
}
|
|
}
|
|
parents.put(taskId, parent);
|
|
siblings.put(taskId, sibling);
|
|
} catch (Exception e) {
|
|
Timber.e(e, e.getMessage());
|
|
}
|
|
|
|
previousTask.set(taskId);
|
|
previousIndent.set(indent);
|
|
if(!TextUtils.isEmpty(metadata.getValue(GtasksMetadata.ID))) {
|
|
localToRemoteIdMap.put(taskId, metadata.getValue(GtasksMetadata.ID));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|