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.
tasks/src/googleplay/java/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.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));
}
});
}
}