|
|
|
@ -1,8 +1,10 @@
|
|
|
|
|
package com.todoroo.astrid.backup;
|
|
|
|
|
|
|
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
|
import java.io.FileReader;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.StringTokenizer;
|
|
|
|
|
|
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
|
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
@ -16,52 +18,53 @@ import android.os.Handler;
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
import com.google.ical.values.RRule;
|
|
|
|
|
import com.timsu.astrid.R;
|
|
|
|
|
import com.timsu.astrid.data.AbstractController;
|
|
|
|
|
import com.timsu.astrid.data.TaskController;
|
|
|
|
|
import com.timsu.astrid.data.TaskIdentifier;
|
|
|
|
|
import com.timsu.astrid.data.TaskModelForXml;
|
|
|
|
|
import com.timsu.astrid.data.alerts.AlertController;
|
|
|
|
|
import com.timsu.astrid.data.sync.SyncDataController;
|
|
|
|
|
import com.timsu.astrid.data.sync.SyncMapping;
|
|
|
|
|
import com.timsu.astrid.data.tag.TagController;
|
|
|
|
|
import com.timsu.astrid.data.tag.TagIdentifier;
|
|
|
|
|
import com.timsu.astrid.data.tag.TagModelForView;
|
|
|
|
|
import com.todoroo.andlib.data.TodorooCursor;
|
|
|
|
|
import com.todoroo.andlib.service.ContextManager;
|
|
|
|
|
import com.todoroo.andlib.service.ExceptionService;
|
|
|
|
|
import com.todoroo.andlib.sql.Query;
|
|
|
|
|
import com.todoroo.andlib.utility.DateUtilities;
|
|
|
|
|
import com.todoroo.astrid.core.PluginServices;
|
|
|
|
|
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
|
|
|
|
import com.todoroo.astrid.legacy.LegacyImportance;
|
|
|
|
|
import com.todoroo.astrid.legacy.LegacyRepeatInfo;
|
|
|
|
|
import com.todoroo.astrid.legacy.LegacyRepeatInfo.LegacyRepeatInterval;
|
|
|
|
|
import com.todoroo.astrid.legacy.LegacyTaskModel;
|
|
|
|
|
import com.todoroo.astrid.model.Metadata;
|
|
|
|
|
import com.todoroo.astrid.model.Task;
|
|
|
|
|
import com.todoroo.astrid.rmilk.data.MilkTask;
|
|
|
|
|
import com.todoroo.astrid.service.MetadataService;
|
|
|
|
|
import com.todoroo.astrid.service.TaskService;
|
|
|
|
|
import com.todoroo.astrid.tags.TagService;
|
|
|
|
|
|
|
|
|
|
public class TasksXmlImporter {
|
|
|
|
|
public static final String TAG = "TasksXmlImporter";
|
|
|
|
|
public static final String ASTRID_TAG = TasksXmlExporter.ASTRID_TAG;
|
|
|
|
|
public static final String ASTRID_ATTR_VERSION = TasksXmlExporter.ASTRID_ATTR_VERSION;
|
|
|
|
|
public static final String TASK_TAG = TasksXmlExporter.TASK_TAG;
|
|
|
|
|
public static final String TAG_TAG = TasksXmlExporter.TAG_TAG;
|
|
|
|
|
public static final String ALERT_TAG = TasksXmlExporter.ALERT_TAG;
|
|
|
|
|
public static final String SYNC_TAG = TasksXmlExporter.SYNC_TAG;
|
|
|
|
|
public static final String TASK_ID = AbstractController.KEY_ROWID;
|
|
|
|
|
public static final String TASK_NAME = TaskModelForXml.NAME;
|
|
|
|
|
public static final String TASK_CREATION_DATE = TaskModelForXml.CREATION_DATE;
|
|
|
|
|
public static final String TAG_ATTR_NAME = TasksXmlExporter.TAG_ATTR_NAME;
|
|
|
|
|
public static final String ALERT_ATTR_DATE = TasksXmlExporter.ALERT_ATTR_DATE;
|
|
|
|
|
public static final String SYNC_ATTR_SERVICE = TasksXmlExporter.SYNC_ATTR_SERVICE;
|
|
|
|
|
public static final String SYNC_ATTR_REMOTE_ID = TasksXmlExporter.SYNC_ATTR_REMOTE_ID;
|
|
|
|
|
|
|
|
|
|
private TaskController taskController;
|
|
|
|
|
private TagController tagController;
|
|
|
|
|
private AlertController alertController;
|
|
|
|
|
private SyncDataController syncDataController;
|
|
|
|
|
private XmlPullParser xpp;
|
|
|
|
|
private String input;
|
|
|
|
|
private Handler importHandler;
|
|
|
|
|
private final Context context;
|
|
|
|
|
|
|
|
|
|
// --- public interface
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Import tasks from the given file
|
|
|
|
|
*
|
|
|
|
|
* @param input
|
|
|
|
|
* @param runAfterImport
|
|
|
|
|
*/
|
|
|
|
|
public static void importTasks(String input, Runnable runAfterImport) {
|
|
|
|
|
new TasksXmlImporter(input, runAfterImport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- implementation
|
|
|
|
|
|
|
|
|
|
private final Handler importHandler;
|
|
|
|
|
private int taskCount;
|
|
|
|
|
private int importCount;
|
|
|
|
|
private int skipCount;
|
|
|
|
|
private final String input;
|
|
|
|
|
|
|
|
|
|
static ProgressDialog progressDialog;
|
|
|
|
|
|
|
|
|
|
public TasksXmlImporter(Context context) {
|
|
|
|
|
this.context = context;
|
|
|
|
|
setContext(context);
|
|
|
|
|
}
|
|
|
|
|
private final Context context = ContextManager.getContext();
|
|
|
|
|
private final TaskService taskService = PluginServices.getTaskService();
|
|
|
|
|
private final MetadataService metadataService = PluginServices.getMetadataService();
|
|
|
|
|
private final ExceptionService exceptionService = PluginServices.getExceptionService();
|
|
|
|
|
protected ProgressDialog progressDialog;
|
|
|
|
|
|
|
|
|
|
private void setProgressMessage(final String message) {
|
|
|
|
|
importHandler.post(new Runnable() {
|
|
|
|
@ -71,12 +74,18 @@ public class TasksXmlImporter {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void importTasks(final Runnable runAfterImport) {
|
|
|
|
|
/**
|
|
|
|
|
* Import tasks.
|
|
|
|
|
* @param runAfterImport optional runnable after import
|
|
|
|
|
*/
|
|
|
|
|
private TasksXmlImporter(String input, final Runnable runAfterImport) {
|
|
|
|
|
this.input = input;
|
|
|
|
|
|
|
|
|
|
importHandler = new Handler();
|
|
|
|
|
importHandler.post(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
TasksXmlImporter.progressDialog = new ProgressDialog(context);
|
|
|
|
|
progressDialog = new ProgressDialog(context);
|
|
|
|
|
progressDialog.setIcon(android.R.drawable.ic_dialog_info);
|
|
|
|
|
progressDialog.setTitle(R.string.import_progress_title);
|
|
|
|
|
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
|
|
|
@ -95,153 +104,61 @@ public class TasksXmlImporter {
|
|
|
|
|
if (runAfterImport != null) {
|
|
|
|
|
importHandler.post(runAfterImport);
|
|
|
|
|
}
|
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
|
Log.e("TasksXmlImporter", e.getMessage());
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
exceptionService.displayAndReportError(context,
|
|
|
|
|
context.getString(R.string.backup_TXI_error), e);
|
|
|
|
|
} catch (XmlPullParserException e) {
|
|
|
|
|
Log.e("TasksXmlImporter", e.getMessage());
|
|
|
|
|
exceptionService.displayAndReportError(context,
|
|
|
|
|
context.getString(R.string.backup_TXI_error), e);
|
|
|
|
|
}
|
|
|
|
|
Looper.loop();
|
|
|
|
|
}
|
|
|
|
|
}).start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void performImport() throws FileNotFoundException, XmlPullParserException {
|
|
|
|
|
@SuppressWarnings("nls")
|
|
|
|
|
private void performImport() throws IOException, XmlPullParserException {
|
|
|
|
|
taskCount = 0;
|
|
|
|
|
importCount = 0;
|
|
|
|
|
skipCount = 0;
|
|
|
|
|
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
|
|
|
|
xpp = factory.newPullParser();
|
|
|
|
|
XmlPullParser xpp = factory.newPullParser();
|
|
|
|
|
xpp.setInput(new FileReader(input));
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_opened));
|
|
|
|
|
|
|
|
|
|
openControllers();
|
|
|
|
|
try {
|
|
|
|
|
TaskModelForXml currentTask = null;
|
|
|
|
|
while (xpp.next() != XmlPullParser.END_DOCUMENT) {
|
|
|
|
|
String tag = xpp.getName();
|
|
|
|
|
if (xpp.getEventType() == XmlPullParser.END_TAG) {
|
|
|
|
|
// Ignore end tag.
|
|
|
|
|
// Ignore end tags
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (tag != null) {
|
|
|
|
|
if (tag.equals(ASTRID_TAG)) {
|
|
|
|
|
// Process <astrid ... >
|
|
|
|
|
// Perform version compatibility check?
|
|
|
|
|
}
|
|
|
|
|
else if (tag.equals(TASK_TAG)) {
|
|
|
|
|
// Parse <task ... >
|
|
|
|
|
currentTask = parseTask();
|
|
|
|
|
} else if (currentTask != null) {
|
|
|
|
|
// These tags all require that we have a task to associate them with.
|
|
|
|
|
if (tag.equals(TAG_TAG)) {
|
|
|
|
|
// Process <tag ... >
|
|
|
|
|
parseTag(currentTask.getTaskIdentifier());
|
|
|
|
|
} else if (tag.equals(ALERT_TAG)) {
|
|
|
|
|
// Process <alert ... >
|
|
|
|
|
parseAlert(currentTask.getTaskIdentifier());
|
|
|
|
|
} else if (tag.equals(SYNC_TAG)) {
|
|
|
|
|
// Process <sync ... >
|
|
|
|
|
parseSync(currentTask.getTaskIdentifier());
|
|
|
|
|
// Process <astrid ... >
|
|
|
|
|
if (tag.equals(BackupConstants.ASTRID_TAG)) {
|
|
|
|
|
String version = xpp.getAttributeValue(null, BackupConstants.ASTRID_ATTR_VERSION);
|
|
|
|
|
int intVersion;
|
|
|
|
|
try {
|
|
|
|
|
intVersion = Integer.parseInt(version);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new UnsupportedOperationException(
|
|
|
|
|
"Did not know how to import tasks with version '" +
|
|
|
|
|
version + "'");
|
|
|
|
|
}
|
|
|
|
|
if(intVersion <= 135)
|
|
|
|
|
new Astrid2TaskImporter(xpp);
|
|
|
|
|
else
|
|
|
|
|
new Astrid3TaskImporter(xpp);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "import error " + e.getMessage());
|
|
|
|
|
} finally {
|
|
|
|
|
closeControllers();
|
|
|
|
|
progressDialog.dismiss();
|
|
|
|
|
showSummary();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseSync(TaskIdentifier taskId) {
|
|
|
|
|
String service = xpp.getAttributeValue(null, SYNC_ATTR_SERVICE);
|
|
|
|
|
String remoteId = xpp.getAttributeValue(null, SYNC_ATTR_REMOTE_ID);
|
|
|
|
|
if (service != null && remoteId != null) {
|
|
|
|
|
int serviceInt = Integer.parseInt(service);
|
|
|
|
|
SyncMapping sm = new SyncMapping(taskId, serviceInt, remoteId);
|
|
|
|
|
syncDataController.saveSyncMapping(sm);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseAlert(TaskIdentifier taskId) {
|
|
|
|
|
String alert = xpp.getAttributeValue(null, ALERT_ATTR_DATE);
|
|
|
|
|
if (alert != null) {
|
|
|
|
|
Date alertDate = BackupDateUtilities.getDateFromIso8601String(alert);
|
|
|
|
|
if (alertDate != null) {
|
|
|
|
|
if (! alertController.addAlert(taskId, alertDate)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseTag(TaskIdentifier taskId) {
|
|
|
|
|
String tagName = xpp.getAttributeValue(null, TAG_ATTR_NAME);
|
|
|
|
|
if (tagName != null) {
|
|
|
|
|
TagIdentifier tagId;
|
|
|
|
|
TagModelForView tagModel;
|
|
|
|
|
tagModel = tagController.fetchTagFromName(tagName);
|
|
|
|
|
if (tagModel == null) {
|
|
|
|
|
// Tag not found, create a new one.
|
|
|
|
|
tagId = tagController.createTag(tagName);
|
|
|
|
|
} else {
|
|
|
|
|
tagId = tagModel.getTagIdentifier();
|
|
|
|
|
}
|
|
|
|
|
if (! tagController.addTag(taskId, tagId)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private TaskModelForXml parseTask() {
|
|
|
|
|
taskCount++;
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_read, taskCount));
|
|
|
|
|
TaskModelForXml task = null;
|
|
|
|
|
String taskName = xpp.getAttributeValue(null, TASK_NAME);
|
|
|
|
|
|
|
|
|
|
Date creationDate = null;
|
|
|
|
|
String createdString = xpp.getAttributeValue(null, TASK_CREATION_DATE);
|
|
|
|
|
if (createdString != null) {
|
|
|
|
|
creationDate = BackupDateUtilities.getDateFromIso8601String(createdString);
|
|
|
|
|
}
|
|
|
|
|
// If the task's name and creation date match an existing task, skip it.
|
|
|
|
|
if (creationDate != null && taskName != null) {
|
|
|
|
|
task = taskController.fetchTaskForXml(taskName, creationDate);
|
|
|
|
|
}
|
|
|
|
|
if (task != null) {
|
|
|
|
|
// Skip this task.
|
|
|
|
|
skipCount++;
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_skip, taskCount));
|
|
|
|
|
// Set currentTask to null so we skip its alerts/syncs/tags, too.
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// Else, make a new task model and add away.
|
|
|
|
|
task = new TaskModelForXml();
|
|
|
|
|
int numAttributes = xpp.getAttributeCount();
|
|
|
|
|
for (int i = 0; i < numAttributes; i++) {
|
|
|
|
|
String fieldName = xpp.getAttributeName(i);
|
|
|
|
|
String fieldValue = xpp.getAttributeValue(i);
|
|
|
|
|
task.setField(fieldName, fieldValue);
|
|
|
|
|
}
|
|
|
|
|
// Save the task to the database.
|
|
|
|
|
taskController.saveTask(task, false);
|
|
|
|
|
importCount++;
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_add, taskCount));
|
|
|
|
|
return task;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showSummary() {
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
|
|
|
builder.setTitle(R.string.import_summary_title);
|
|
|
|
@ -257,44 +174,248 @@ public class TasksXmlImporter {
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTaskController(TaskController taskController) {
|
|
|
|
|
this.taskController = taskController;
|
|
|
|
|
}
|
|
|
|
|
// --- importers
|
|
|
|
|
|
|
|
|
|
public void setTagController(TagController tagController) {
|
|
|
|
|
this.tagController = tagController;
|
|
|
|
|
}
|
|
|
|
|
private class Astrid3TaskImporter {
|
|
|
|
|
@SuppressWarnings("unused")
|
|
|
|
|
private final XmlPullParser xpp;
|
|
|
|
|
|
|
|
|
|
public void setAlertController(AlertController alertController) {
|
|
|
|
|
this.alertController = alertController;
|
|
|
|
|
public Astrid3TaskImporter(XmlPullParser xpp) {
|
|
|
|
|
this.xpp = xpp;
|
|
|
|
|
// TODO
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setSyncDataController(SyncDataController syncDataController) {
|
|
|
|
|
this.syncDataController = syncDataController;
|
|
|
|
|
}
|
|
|
|
|
private class Astrid2TaskImporter {
|
|
|
|
|
private final XmlPullParser xpp;
|
|
|
|
|
private Task currentTask = null;
|
|
|
|
|
private String upgradeNotes = null;
|
|
|
|
|
private boolean syncOnComplete = false;
|
|
|
|
|
|
|
|
|
|
public void setContext(Context ctx) {
|
|
|
|
|
setTaskController(new TaskController(ctx));
|
|
|
|
|
setTagController(new TagController(ctx));
|
|
|
|
|
setAlertController(new AlertController(ctx));
|
|
|
|
|
setSyncDataController(new SyncDataController(ctx));
|
|
|
|
|
}
|
|
|
|
|
private final ArrayList<String> tags = new ArrayList<String>();
|
|
|
|
|
|
|
|
|
|
private void closeControllers() {
|
|
|
|
|
taskController.close();
|
|
|
|
|
tagController.close();
|
|
|
|
|
alertController.close();
|
|
|
|
|
syncDataController.close();
|
|
|
|
|
}
|
|
|
|
|
public Astrid2TaskImporter(XmlPullParser xpp) throws XmlPullParserException, IOException {
|
|
|
|
|
this.xpp = xpp;
|
|
|
|
|
|
|
|
|
|
private void openControllers() {
|
|
|
|
|
taskController.open();
|
|
|
|
|
tagController.open();
|
|
|
|
|
alertController.open();
|
|
|
|
|
syncDataController.open();
|
|
|
|
|
}
|
|
|
|
|
while (xpp.next() != XmlPullParser.END_DOCUMENT) {
|
|
|
|
|
String tag = xpp.getName();
|
|
|
|
|
if (tag == null || xpp.getEventType() == XmlPullParser.END_TAG) {
|
|
|
|
|
saveTags();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setInput(String input) {
|
|
|
|
|
this.input = input;
|
|
|
|
|
if (tag.equals(BackupConstants.TASK_TAG)) {
|
|
|
|
|
// Parse <task ... >
|
|
|
|
|
currentTask = parseTask();
|
|
|
|
|
} else if (currentTask != null) {
|
|
|
|
|
// These tags all require that we have a task to associate
|
|
|
|
|
// them with.
|
|
|
|
|
if (tag.equals(BackupConstants.TAG_TAG)) {
|
|
|
|
|
// Process <tag ... >
|
|
|
|
|
parseTag();
|
|
|
|
|
} else if (tag.equals(BackupConstants.ALERT_TAG)) {
|
|
|
|
|
// Process <alert ... >
|
|
|
|
|
parseAlert();
|
|
|
|
|
} else if (tag.equals(BackupConstants.SYNC_TAG)) {
|
|
|
|
|
// Process <sync ... >
|
|
|
|
|
parseSync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseSync() {
|
|
|
|
|
String service = xpp.getAttributeValue(null, BackupConstants.SYNC_ATTR_SERVICE);
|
|
|
|
|
String remoteId = xpp.getAttributeValue(null, BackupConstants.SYNC_ATTR_REMOTE_ID);
|
|
|
|
|
if (service != null && remoteId != null) {
|
|
|
|
|
StringTokenizer strtok = new StringTokenizer(remoteId, "|"); //$NON-NLS-1$
|
|
|
|
|
String taskId = strtok.nextToken();
|
|
|
|
|
String taskSeriesId = strtok.nextToken();
|
|
|
|
|
String listId = strtok.nextToken();
|
|
|
|
|
|
|
|
|
|
Metadata metadata = new Metadata();
|
|
|
|
|
metadata.setValue(Metadata.TASK, currentTask.getId());
|
|
|
|
|
metadata.setValue(MilkTask.LIST_ID, Long.parseLong(listId));
|
|
|
|
|
metadata.setValue(MilkTask.TASK_SERIES_ID, Long.parseLong(taskSeriesId));
|
|
|
|
|
metadata.setValue(MilkTask.TASK_ID, Long.parseLong(taskId));
|
|
|
|
|
metadata.setValue(MilkTask.REPEATING, syncOnComplete ? 1 : 0);
|
|
|
|
|
metadataService.save(metadata);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseAlert() {
|
|
|
|
|
// drop it
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean parseTag() {
|
|
|
|
|
String tagName = xpp.getAttributeValue(null, BackupConstants.TAG_ATTR_NAME);
|
|
|
|
|
tags.add(tagName);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void saveTags() {
|
|
|
|
|
if(currentTask != null && tags.size() > 0) {
|
|
|
|
|
TagService.getInstance().synchronizeTags(currentTask.getId(), tags);
|
|
|
|
|
}
|
|
|
|
|
tags.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("nls")
|
|
|
|
|
private Task parseTask() {
|
|
|
|
|
taskCount++;
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_read,
|
|
|
|
|
taskCount));
|
|
|
|
|
|
|
|
|
|
String taskName = xpp.getAttributeValue(null, LegacyTaskModel.NAME);
|
|
|
|
|
Date creationDate = null;
|
|
|
|
|
String createdString = xpp.getAttributeValue(null,
|
|
|
|
|
LegacyTaskModel.CREATION_DATE);
|
|
|
|
|
if (createdString != null) {
|
|
|
|
|
creationDate = BackupDateUtilities.getDateFromIso8601String(createdString);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if we don't have task name or creation date, skip
|
|
|
|
|
if (creationDate == null || taskName == null) {
|
|
|
|
|
skipCount++;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the task's name and creation date match an existing task, skip
|
|
|
|
|
TodorooCursor<Task> cursor = taskService.query(Query.select(Task.ID).where(TaskCriteria.createdOn(creationDate.getTime())));
|
|
|
|
|
try {
|
|
|
|
|
if(cursor.getCount() > 0) {
|
|
|
|
|
skipCount++;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
cursor.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// else, make a new task model and add away.
|
|
|
|
|
Task task = new Task();
|
|
|
|
|
int numAttributes = xpp.getAttributeCount();
|
|
|
|
|
for (int i = 0; i < numAttributes; i++) {
|
|
|
|
|
String fieldName = xpp.getAttributeName(i);
|
|
|
|
|
String fieldValue = xpp.getAttributeValue(i);
|
|
|
|
|
if(!setTaskField(task, fieldName, fieldValue)) {
|
|
|
|
|
Log.i("astrid-xml-import", "Task: " + taskName + ": Unknown field '" +
|
|
|
|
|
fieldName + "' with value '" + fieldValue + "' disregarded.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(upgradeNotes != null) {
|
|
|
|
|
if(task.containsValue(Task.NOTES) && task.getValue(Task.NOTES).length() > 0)
|
|
|
|
|
task.setValue(Task.NOTES, task.getValue(Task.NOTES) + "\n" + upgradeNotes);
|
|
|
|
|
else
|
|
|
|
|
task.setValue(Task.NOTES, upgradeNotes);
|
|
|
|
|
upgradeNotes = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save the task to the database.
|
|
|
|
|
taskService.save(task, false);
|
|
|
|
|
importCount++;
|
|
|
|
|
setProgressMessage(context.getString(R.string.import_progress_add, taskCount));
|
|
|
|
|
return task;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** helper method to set field on a task */
|
|
|
|
|
@SuppressWarnings("nls")
|
|
|
|
|
private final boolean setTaskField(Task task, String field, String value) {
|
|
|
|
|
if(field.equals(LegacyTaskModel.NAME)) {
|
|
|
|
|
task.setValue(Task.TITLE, value);
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.NOTES)) {
|
|
|
|
|
task.setValue(Task.NOTES, value);
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.PROGRESS_PERCENTAGE)) {
|
|
|
|
|
// ignore
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.IMPORTANCE)) {
|
|
|
|
|
task.setValue(Task.IMPORTANCE, LegacyImportance.valueOf(value).ordinal());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.ESTIMATED_SECONDS)) {
|
|
|
|
|
task.setValue(Task.ESTIMATED_SECONDS, Integer.parseInt(value));
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.ELAPSED_SECONDS)) {
|
|
|
|
|
task.setValue(Task.ELAPSED_SECONDS, Integer.parseInt(value));
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.TIMER_START)) {
|
|
|
|
|
task.setValue(Task.TIMER_START,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.DEFINITE_DUE_DATE)) {
|
|
|
|
|
String preferred = xpp.getAttributeValue(null, LegacyTaskModel.PREFERRED_DUE_DATE);
|
|
|
|
|
if(preferred != null) {
|
|
|
|
|
Date preferredDate = BackupDateUtilities.getDateFromIso8601String(value);
|
|
|
|
|
upgradeNotes = "Goal Deadline: " +
|
|
|
|
|
DateUtilities.getFormattedDate(ContextManager.getContext(),
|
|
|
|
|
preferredDate);
|
|
|
|
|
}
|
|
|
|
|
task.setValue(Task.DUE_DATE,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.PREFERRED_DUE_DATE)) {
|
|
|
|
|
String definite = xpp.getAttributeValue(null, LegacyTaskModel.DEFINITE_DUE_DATE);
|
|
|
|
|
if(definite != null)
|
|
|
|
|
; // handled above
|
|
|
|
|
else
|
|
|
|
|
task.setValue(Task.DUE_DATE,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.HIDDEN_UNTIL)) {
|
|
|
|
|
task.setValue(Task.HIDE_UNTIL,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.BLOCKING_ON)) {
|
|
|
|
|
// ignore
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.POSTPONE_COUNT)) {
|
|
|
|
|
task.setValue(Task.POSTPONE_COUNT, Integer.parseInt(value));
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.NOTIFICATIONS)) {
|
|
|
|
|
task.setValue(Task.REMINDER_PERIOD, Integer.parseInt(value) * 1000L);
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.CREATION_DATE)) {
|
|
|
|
|
task.setValue(Task.CREATION_DATE,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.COMPLETION_DATE)) {
|
|
|
|
|
task.setValue(Task.COMPLETION_DATE,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.NOTIFICATION_FLAGS)) {
|
|
|
|
|
task.setValue(Task.REMINDER_FLAGS, Integer.parseInt(value));
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.LAST_NOTIFIED)) {
|
|
|
|
|
task.setValue(Task.REMINDER_LAST,
|
|
|
|
|
BackupDateUtilities.getDateFromIso8601String(value).getTime());
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals("repeat_interval")) {
|
|
|
|
|
// handled below
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals("repeat_value")) {
|
|
|
|
|
int repeatValue = Integer.parseInt(value);
|
|
|
|
|
String repeatInterval = xpp.getAttributeValue(null, "repeat_interval");
|
|
|
|
|
if(repeatValue > 0 && repeatInterval != null) {
|
|
|
|
|
LegacyRepeatInterval interval = LegacyRepeatInterval.valueOf(repeatInterval);
|
|
|
|
|
LegacyRepeatInfo repeatInfo = new LegacyRepeatInfo(interval, repeatValue);
|
|
|
|
|
RRule rrule = repeatInfo.toRRule();
|
|
|
|
|
task.setValue(Task.RECURRENCE, rrule.toIcal());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(field.equals(LegacyTaskModel.FLAGS)) {
|
|
|
|
|
if(Integer.parseInt(value) == LegacyTaskModel.FLAG_SYNC_ON_COMPLETE)
|
|
|
|
|
syncOnComplete = true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|