package com.todoroo.astrid.subtasks; import java.util.ArrayList; import android.util.Log; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.sql.Functions; import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmSyncService; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.TagDataService; import com.todoroo.astrid.subtasks.AstridOrderedListUpdater.Node; @SuppressWarnings("deprecation") // Subtasks metadata is deprecated public class SubtasksMetadataMigration { @Autowired private TagDataService tagDataService; @Autowired private MetadataService metadataService; @Autowired private ActFmPreferenceService actFmPreferenceService; @Autowired private ActFmSyncService actFmSyncService; public SubtasksMetadataMigration() { DependencyInjectionService.getInstance().inject(this); } public void performMigration() { TodorooCursor<Metadata> subtasksMetadata = metadataService.query(Query.select(Metadata.PROPERTIES) .where(MetadataCriteria.withKey(SubtasksMetadata.METADATA_KEY)) .orderBy(Order.asc(SubtasksMetadata.TAG), Order.asc(Functions.cast(SubtasksMetadata.ORDER, "LONG")))); //$NON-NLS-1$ try { Metadata m = new Metadata(); for (subtasksMetadata.moveToFirst(); !subtasksMetadata.isAfterLast(); subtasksMetadata.moveToNext()) { m.readFromCursor(subtasksMetadata); String tag = m.getValue(SubtasksMetadata.TAG); processTag(tag, subtasksMetadata); } } finally { subtasksMetadata.close(); } } @SuppressWarnings("nls") private void processTag(String tag, TodorooCursor<Metadata> subtasksMetadata) { Metadata item = new Metadata(); TagData td = null; try { if (!SubtasksMetadata.LIST_ACTIVE_TASKS.equals(tag)) { String idString = tag.replace("td:", ""); long id = Long.parseLong(idString); td = tagDataService.fetchById(id, TagData.ID); } } catch (NumberFormatException e) { Log.e("subtasks-migration", "Could not parse tag id from " + tag, e); } if (td == null && !SubtasksMetadata.LIST_ACTIVE_TASKS.equals(tag)) { for (; !subtasksMetadata.isAfterLast(); subtasksMetadata.moveToNext()) { item.readFromCursor(subtasksMetadata); if (!item.getValue(SubtasksMetadata.TAG).equals(tag)) break; } } else { String newTree = buildTreeModelFromMetadata(tag, subtasksMetadata); if (td != null) { td.setValue(TagData.TAG_ORDERING, newTree); tagDataService.save(td); } else { Preferences.setString(SubtasksUpdater.ACTIVE_TASKS_ORDER, newTree); } } subtasksMetadata.moveToPrevious(); // Move back one to undo the last iteration of the for loop } private String buildTreeModelFromMetadata(String tag, TodorooCursor<Metadata> cursor) { Metadata item = new Metadata(); Node root = new Node("-1", null, -1); //$NON-NLS-1$ for (; !cursor.isAfterLast(); cursor.moveToNext()) { item.clear(); item.readFromCursor(cursor); if (!item.getValue(SubtasksMetadata.TAG).equals(tag)) break; int indent = 0; if (item.containsNonNullValue(SubtasksMetadata.INDENT)) { Integer i = item.getValue(SubtasksMetadata.INDENT); if (i != null) indent = i.intValue(); } Node parent = findNextParentForIndent(root, indent); Node newNode = new Node(item.getValue(Metadata.TASK).toString(), parent, parent.indent + 1); parent.children.add(newNode); } return AstridOrderedListUpdater.serializeTree(root); } private Node findNextParentForIndent(Node root, int indent) { if (indent <= 0) return root; ArrayList<Node> children = root.children; if (children.size() == 0) return root; return findNextParentForIndent(children.get(children.size() - 1), indent - 1); } }