Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaxsun McCarthy Huggan2016-05-05 00:03:04 +0000
committerJaxsun McCarthy Huggan2016-05-17 16:52:19 +0000
commit8d958cc06f60633412164e2d8fddc3ec907ae413 (patch)
treef9c0930e7862097f8df4ec56b3550f7914098347 /org.eclipse.mylyn.tasks.core/src
parentb77da49617c12b2d1a066b9f5571cba09f499785 (diff)
downloadorg.eclipse.mylyn.tasks-8d958cc06f60633412164e2d8fddc3ec907ae413.tar.gz
org.eclipse.mylyn.tasks-8d958cc06f60633412164e2d8fddc3ec907ae413.tar.xz
org.eclipse.mylyn.tasks-8d958cc06f60633412164e2d8fddc3ec907ae413.zip
493037: read task list using SAX instead of DOM
* no longer performs any migration from Mylyn 2.0 Change-Id: Ib7cf30f9e3b8a9b1c762bf43df4fd824cba472fd Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=493037 Signed-off-by: Jaxsun McCarthy Huggan <jaxsun.mccarthy@tasktop.com>
Diffstat (limited to 'org.eclipse.mylyn.tasks.core/src')
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxCategoryBuilder.java79
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxOrphanBuilder.java112
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxQueryBuilder.java108
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskBuilder.java255
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListElementBuilder.java72
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java211
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizationConstants.java129
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizer.java161
8 files changed, 997 insertions, 130 deletions
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxCategoryBuilder.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxCategoryBuilder.java
new file mode 100644
index 000000000..a50278334
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxCategoryBuilder.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.ITransferList;
+import org.eclipse.mylyn.internal.tasks.core.TaskCategory;
+import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer;
+import org.xml.sax.Attributes;
+
+import com.google.common.base.Strings;
+
+public class SaxCategoryBuilder extends SaxTaskListElementBuilder<AbstractTaskCategory> {
+
+ private AbstractTaskCategory category;
+
+ private final ITransferList taskList;
+
+ public SaxCategoryBuilder(ITransferList taskList) {
+ this.taskList = taskList;
+ }
+
+ @Override
+ public void beginItem(Attributes elementAttributes) {
+ try {
+ String name = elementAttributes.getValue(TaskListExternalizationConstants.KEY_NAME);
+ if (!Strings.isNullOrEmpty(name)) {
+ String handle = elementAttributes.getValue(TaskListExternalizationConstants.KEY_HANDLE);
+ if (Strings.isNullOrEmpty(handle)) {
+ handle = name;
+ }
+ category = taskList.getContainerForHandle(handle);
+ if (category == null) {
+ category = new TaskCategory(handle, name);
+ } else if (!UncategorizedTaskContainer.HANDLE.equals(handle)) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Category with handle \"%s\" already exists in task list", handle))); //$NON-NLS-1$
+ }
+ } else {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ "Category is missing name attribute")); //$NON-NLS-1$
+ }
+ } catch (Exception e) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Exception reading category: %s", e.getMessage()), e)); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ protected void applyAttribute(String attributeKey, String attributeValue) {
+ // do nothing categories do not have arbitrary attributes
+ }
+
+ @Override
+ public AbstractTaskCategory getItem() {
+ return category;
+ }
+
+ @Override
+ public void addToTaskList(ITransferList taskList) {
+ // don't add unmatched categories
+ if (category instanceof TaskCategory) {
+ taskList.addCategory((TaskCategory) category);
+ }
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxOrphanBuilder.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxOrphanBuilder.java
new file mode 100644
index 000000000..5a9228f31
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxOrphanBuilder.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.xml.sax.Attributes;
+
+public class SaxOrphanBuilder {
+
+ private final Document document;
+
+ private Element currentElement;
+
+ private StringBuilder currentStringContent;
+
+ public SaxOrphanBuilder() throws CoreException {
+ this.document = createDocument();
+ }
+
+ private Document createDocument() throws CoreException {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db;
+ try {
+ db = dbf.newDocumentBuilder();
+ Document document = db.newDocument();
+ Element root = document.createElement("orphans"); //$NON-NLS-1$
+ document.appendChild(root);
+ return document;
+ } catch (ParserConfigurationException e) {
+ throw new CoreException(
+ new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Failed to create document", e)); //$NON-NLS-1$
+ }
+ }
+
+ public void startElement(String localName, Attributes attributes) {
+ Element element = document.createElement(localName);
+ for (int i = 0; i < attributes.getLength(); i++) {
+ String attributeName = attributes.getLocalName(i);
+ String attributeValue = attributes.getValue(i);
+ element.setAttribute(attributeName, attributeValue);
+ }
+
+ if (currentElement != null) {
+ appendTextNode();
+ currentElement.appendChild(element);
+ }
+ currentElement = element;
+
+ currentStringContent = new StringBuilder();
+ }
+
+ public void acceptCharacters(char[] content, int start, int length) {
+ if (currentStringContent != null) {
+ currentStringContent.append(content, start, length);
+ }
+ }
+
+ public void endElement() {
+ if (currentElement != null) {
+ appendTextNode();
+ Node parentNode = currentElement.getParentNode();
+ if (parentNode instanceof Element) {
+ currentElement = (Element) parentNode;
+ currentStringContent = new StringBuilder();
+ } else {
+ currentElement = null;
+ }
+ }
+ }
+
+ public void commitOrphan() {
+ if (currentElement != null) {
+ document.getDocumentElement().appendChild(currentElement);
+ }
+ }
+
+ private void appendTextNode() {
+ if (hasStringContnet()) {
+ Text textNode = document.createTextNode(currentStringContent.toString());
+ currentElement.appendChild(textNode);
+ }
+ }
+
+ private boolean hasStringContnet() {
+ return currentStringContent != null & currentStringContent.length() > 0;
+ }
+
+ public Document getOrphans() {
+ return document;
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxQueryBuilder.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxQueryBuilder.java
new file mode 100644
index 000000000..e33b34242
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxQueryBuilder.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.ITransferList;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryModel;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery;
+import org.eclipse.mylyn.tasks.core.IRepositoryManager;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.xml.sax.Attributes;
+
+import com.google.common.base.Strings;
+
+public class SaxQueryBuilder extends SaxTaskListElementBuilder<RepositoryQuery> {
+
+ private RepositoryQuery query;
+
+ private final RepositoryModel repositoryModel;
+
+ private final IRepositoryManager repositoryManager;
+
+ public SaxQueryBuilder(RepositoryModel repositoryModel, IRepositoryManager repositoryManager) {
+ this.repositoryModel = repositoryModel;
+ this.repositoryManager = repositoryManager;
+ }
+
+ @Override
+ public void beginItem(Attributes elementAttributes) {
+ try {
+ String repositoryUrl = Strings
+ .nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_REPOSITORY_URL));
+ String connectorKind = Strings
+ .nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_CONNECTOR_KIND));
+
+ if (repositoryManager.getRepositoryConnector(connectorKind) == null) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Unable to read query, missing connector with kind \"%s\"", connectorKind))); //$NON-NLS-1$
+ return;
+ }
+
+ query = readDefaultQuery(connectorKind, repositoryUrl);
+
+ readQueryAttributes(elementAttributes);
+ } catch (Exception e) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Exception reading query: %s", e.getMessage()), e)); //$NON-NLS-1$
+ }
+ }
+
+ private RepositoryQuery readDefaultQuery(String connectorKind, String repositoryUrl) {
+ TaskRepository taskRepository = repositoryModel.getTaskRepository(connectorKind, repositoryUrl);
+ RepositoryQuery query = (RepositoryQuery) repositoryModel.createRepositoryQuery(taskRepository);
+ return query;
+ }
+
+ private void readQueryAttributes(Attributes elementAttributes) {
+ String handle = elementAttributes.getValue(TaskListExternalizationConstants.KEY_HANDLE);
+ if (!Strings.isNullOrEmpty(handle)) {
+ query.setHandleIdentifier(handle);
+ }
+
+ String label = elementAttributes.getValue(TaskListExternalizationConstants.KEY_NAME);
+ if (Strings.isNullOrEmpty(label)) { // fall back for legacy
+ label = Strings.nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_LABEL));
+ }
+ query.setSummary(label);
+
+ String queryString = Strings
+ .nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_QUERY_STRING));
+ if (Strings.isNullOrEmpty(queryString)) { // fall back for legacy
+ queryString = Strings.nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_QUERY));
+ }
+ query.setUrl(queryString);
+
+ String lastRefresh = elementAttributes.getValue(TaskListExternalizationConstants.KEY_LAST_REFRESH);
+ if (!Strings.isNullOrEmpty(lastRefresh)) {
+ query.setLastSynchronizedStamp(lastRefresh);
+ }
+ }
+
+ @Override
+ protected void applyAttribute(String attributeKey, String attributeValue) {
+ getItem().setAttribute(attributeKey, attributeValue);
+ }
+
+ @Override
+ public RepositoryQuery getItem() {
+ return query;
+ }
+
+ @Override
+ public void addToTaskList(ITransferList taskList) {
+ taskList.addQuery(query);
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskBuilder.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskBuilder.java
new file mode 100644
index 000000000..d2d7a8150
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskBuilder.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
+import org.eclipse.mylyn.internal.tasks.core.DayDateRange;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.ITransferList;
+import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector;
+import org.eclipse.mylyn.internal.tasks.core.LocalTask;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryModel;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryTaskHandleUtil;
+import org.eclipse.mylyn.internal.tasks.core.TaskActivityUtil;
+import org.eclipse.mylyn.internal.tasks.core.WeekDateRange;
+import org.eclipse.mylyn.tasks.core.IRepositoryManager;
+import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.xml.sax.Attributes;
+
+import com.google.common.base.Strings;
+
+public class SaxTaskBuilder extends SaxTaskListElementBuilder<AbstractTask> {
+
+ private AbstractTask task;
+
+ private final RepositoryModel repositoryModel;
+
+ private final IRepositoryManager repositoryManager;
+
+ public SaxTaskBuilder(RepositoryModel repositoryModel, IRepositoryManager repositoryManager) {
+ this.repositoryModel = repositoryModel;
+ this.repositoryManager = repositoryManager;
+ }
+
+ @Override
+ public void beginItem(Attributes elementAttributes) {
+ try {
+ String handle = elementAttributes.getValue(TaskListExternalizationConstants.KEY_HANDLE);
+ String taskId = elementAttributes.getValue(TaskListExternalizationConstants.KEY_TASK_ID);
+ String repositoryUrl = elementAttributes.getValue(TaskListExternalizationConstants.KEY_REPOSITORY_URL);
+ String summary = Strings
+ .nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_LABEL));
+
+ // local tasks may not have a connector kind
+ String connectorKind = Strings
+ .nullToEmpty(elementAttributes.getValue(TaskListExternalizationConstants.KEY_CONNECTOR_KIND));
+
+ if (handle != null) {
+ if (taskId == null) {
+ taskId = RepositoryTaskHandleUtil.getTaskId(handle);
+ }
+ if (repositoryUrl == null) {
+ repositoryUrl = RepositoryTaskHandleUtil.getRepositoryUrl(handle);
+ }
+ } else {
+ addError(
+ new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, "Task is missing handle attribute")); //$NON-NLS-1$
+ return;
+ }
+
+ task = createTask(connectorKind, repositoryUrl, taskId, summary);
+
+ // we have to check the task's connector kind as local tasks may not have a connector kind in XML
+ if (repositoryManager.getRepositoryConnector(task.getConnectorKind()) == null) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Unable to read task, missing connector with kind \"%s\"", connectorKind))); //$NON-NLS-1$
+ return;
+ }
+
+ readTaskInfo(task, elementAttributes);
+ } catch (Exception e) {
+ addError(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Exception reading task: %s", e.getMessage()), e)); //$NON-NLS-1$
+ }
+ }
+
+ private AbstractTask createTask(String connectorKind, String repositoryUrl, String taskId, String summary) {
+ AbstractTask task;
+ if (repositoryUrl.equals(LocalRepositoryConnector.REPOSITORY_URL)) {
+ task = new LocalTask(taskId, summary);
+ } else {
+ TaskRepository taskRepository = repositoryModel.getTaskRepository(connectorKind, repositoryUrl);
+ task = (AbstractTask) repositoryModel.createTask(taskRepository, taskId);
+ task.setSummary(summary);
+ }
+ return task;
+ }
+
+ private void readTaskInfo(AbstractTask task, Attributes elementAttributes) {
+ String priority = elementAttributes.getValue(TaskListExternalizationConstants.KEY_PRIORITY);
+ if (priority != null) {
+ task.setPriority(priority);
+ } else {
+ task.setPriority(TaskListExternalizationConstants.DEFAULT_PRIORITY);
+ }
+
+ String kind = elementAttributes.getValue(TaskListExternalizationConstants.KEY_KIND);
+ if (kind != null) {
+ task.setTaskKind(kind);
+ }
+
+ String active = elementAttributes.getValue(TaskListExternalizationConstants.KEY_ACTIVE);
+ task.setActive(Boolean.valueOf(active));
+
+ String url = elementAttributes.getValue(TaskListExternalizationConstants.KEY_ISSUEURL);
+ task.setUrl(Strings.nullToEmpty(url));
+
+ String notes = elementAttributes.getValue(TaskListExternalizationConstants.KEY_NOTES);
+ task.setNotes(Strings.nullToEmpty(notes));
+
+ String estimationString = elementAttributes.getValue(TaskListExternalizationConstants.KEY_TIME_ESTIMATED);
+ if (estimationString != null) {
+ try {
+ int estimate = Integer.parseInt(estimationString);
+ task.setEstimatedTimeHours(estimate);
+ } catch (Exception e) {
+ task.setEstimatedTimeHours(0);
+ }
+ } else {
+ task.setEstimatedTimeHours(0);
+ }
+
+ String completionDate = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_END);
+ if (completionDate != null) {
+ task.setCompletionDate(getDateFromString(completionDate));
+ }
+
+ String creationDate = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_CREATION);
+ if (creationDate != null) {
+ task.setCreationDate(getDateFromString(creationDate));
+ }
+
+ String modificationDate = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_MODIFICATION);
+ if (modificationDate != null) {
+ task.setModificationDate(getDateFromString(modificationDate));
+ }
+
+ String dueDate = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_DUE);
+ if (dueDate != null) {
+ task.setDueDate(getDateFromString(dueDate));
+ }
+
+ // Scheduled date range (3.0)
+ String scheduledStart = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_SCHEDULED_START);
+ String scheduledEnd = elementAttributes.getValue(TaskListExternalizationConstants.KEY_DATE_SCHEDULED_END);
+ if (scheduledStart != null && scheduledEnd != null) {
+ Date startDate = getDateFromString(scheduledStart);
+ Date endDate = getDateFromString(scheduledEnd);
+ if (startDate != null && endDate != null && startDate.compareTo(endDate) <= 0) {
+ Calendar calStart = TaskActivityUtil.getCalendar();
+ calStart.setTime(startDate);
+ Calendar calEnd = TaskActivityUtil.getCalendar();
+ calEnd.setTime(endDate);
+ if (DayDateRange.isDayRange(calStart, calEnd)) {
+ task.setScheduledForDate(new DayDateRange(calStart, calEnd));
+ } else if (WeekDateRange.isWeekRange(calStart, calEnd)) {
+ task.setScheduledForDate(new WeekDateRange(calStart, calEnd));
+ } else {
+ // Neither week nor day found, default to today
+ task.setScheduledForDate(TaskActivityUtil.getDayOf(new Date()));
+ }
+ }
+ }
+
+ String reminded = elementAttributes.getValue(TaskListExternalizationConstants.KEY_REMINDED);
+ if (reminded != null) {
+ task.setReminded(Boolean.valueOf(reminded));
+ }
+
+ String markReadPending = elementAttributes.getValue(TaskListExternalizationConstants.KEY_MARK_READ_PENDING);
+ if (markReadPending != null) {
+ task.setMarkReadPending(Boolean.valueOf(markReadPending));
+ }
+
+ String owner = elementAttributes.getValue(TaskListExternalizationConstants.KEY_OWNER);
+ if (owner != null) {
+ task.setOwner(owner);
+ }
+
+ String ownerId = elementAttributes.getValue(TaskListExternalizationConstants.KEY_OWNER_ID);
+ if (ownerId != null) {
+ task.setOwnerId(ownerId);
+ }
+
+ String notified = elementAttributes.getValue(TaskListExternalizationConstants.KEY_NOTIFIED_INCOMING);
+ task.setNotified(Boolean.valueOf(notified));
+
+ String syncStateString = elementAttributes.getValue(TaskListExternalizationConstants.KEY_SYNC_STATE);
+ if (syncStateString != null) {
+ try {
+ SynchronizationState state = SynchronizationState.valueOf(syncStateString);
+ task.setSynchronizationState(state);
+ } catch (IllegalArgumentException e) {
+ // invalid sync state, ignore
+ addError(new Status(IStatus.OK, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Invalid synchronization state \"%s\"", syncStateString))); //$NON-NLS-1$
+ }
+ }
+
+ String key = elementAttributes.getValue(TaskListExternalizationConstants.KEY_KEY);
+ if (key != null) {
+ task.setTaskKey(key);
+ }
+
+ task.setSynchronizing(false);
+ }
+
+ private Date getDateFromString(String dateString) {
+ Date date = null;
+ if (Strings.isNullOrEmpty(dateString)) {
+ return null;
+ }
+ SimpleDateFormat format = new SimpleDateFormat(TaskListExternalizationConstants.IN_DATE_FORMAT, Locale.ENGLISH);
+ try {
+ date = format.parse(dateString);
+ } catch (ParseException e) {
+ addError(new Status(IStatus.OK, ITasksCoreConstants.ID_PLUGIN,
+ String.format("Could not parse date \"%s\"", dateString), e)); //$NON-NLS-1$
+ }
+ return date;
+ }
+
+ @Override
+ protected void applyAttribute(String attributeKey, String attributeValue) {
+ getItem().setAttribute(attributeKey, attributeValue);
+ }
+
+ @Override
+ public AbstractTask getItem() {
+ return task;
+ }
+
+ @Override
+ public void addToTaskList(ITransferList taskList) {
+ taskList.addTask(task);
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListElementBuilder.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListElementBuilder.java
new file mode 100644
index 000000000..6b0fdcd53
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListElementBuilder.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.ITransferList;
+import org.eclipse.mylyn.tasks.core.IRepositoryElement;
+import org.xml.sax.Attributes;
+
+public abstract class SaxTaskListElementBuilder<T extends IRepositoryElement> {
+
+ private String currentAttributeKey;
+
+ private StringBuilder currentAttributeValue;
+
+ private final MultiStatus errors;
+
+ protected SaxTaskListElementBuilder() {
+ this.errors = new MultiStatus(ITasksCoreConstants.ID_PLUGIN, IStatus.OK, null, null);
+ }
+
+ public abstract void beginItem(Attributes elementAttributes);
+
+ protected abstract void applyAttribute(String attributeKey, String attributeValue);
+
+ public abstract T getItem();
+
+ public abstract void addToTaskList(ITransferList taskList);
+
+ public void startAttribute(Attributes elementAttributes) {
+ currentAttributeKey = elementAttributes.getValue(TaskListExternalizationConstants.KEY_KEY);
+ currentAttributeValue = new StringBuilder();
+ }
+
+ public void acceptAttributeValueContent(char[] content, int start, int length) {
+ if (isAcceptingAttributeValues()) {
+ currentAttributeValue.append(content, start, length);
+ }
+ }
+
+ public void endAttribute() {
+ if (isAcceptingAttributeValues()) {
+ applyAttribute(currentAttributeKey, currentAttributeValue.toString());
+ }
+ currentAttributeKey = null;
+ currentAttributeValue = null;
+ }
+
+ public boolean isAcceptingAttributeValues() {
+ return currentAttributeKey != null && currentAttributeValue != null;
+ }
+
+ protected void addError(IStatus status) {
+ errors.add(status);
+ }
+
+ public IStatus getErrors() {
+ return errors;
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java
new file mode 100644
index 000000000..394d02ec7
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import java.util.Collection;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTaskContainer;
+import org.eclipse.mylyn.internal.tasks.core.ITransferList;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryModel;
+import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery;
+import org.eclipse.mylyn.tasks.core.IRepositoryElement;
+import org.eclipse.mylyn.tasks.core.IRepositoryManager;
+import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+public class SaxTaskListHandler extends DefaultHandler {
+
+ private final ITransferList taskList;
+
+ private final RepositoryModel repositoryModel;
+
+ private final IRepositoryManager repositoryManager;
+
+ private final Multimap<AbstractTask, String> subTasks;
+
+ private final Multimap<RepositoryQuery, String> queryResults;
+
+ private final Multimap<AbstractTaskCategory, String> categorizedTasks;
+
+ private SaxTaskListElementBuilder<? extends IRepositoryElement> currentBuilder;
+
+ private final SaxOrphanBuilder orphanBuilder;
+
+ public SaxTaskListHandler(ITransferList taskList, RepositoryModel repositoryModel,
+ IRepositoryManager repositoryManager) throws CoreException {
+ this.taskList = taskList;
+ this.repositoryModel = repositoryModel;
+ this.repositoryManager = repositoryManager;
+
+ this.subTasks = HashMultimap.create();
+ this.queryResults = HashMultimap.create();
+ this.categorizedTasks = HashMultimap.create();
+
+ this.orphanBuilder = new SaxOrphanBuilder();
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ switch (localName) {
+ case TaskListExternalizationConstants.NODE_TASK:
+ checkState(currentBuilder == null, "Cannot begin reading a task while reading another task list element."); //$NON-NLS-1$
+
+ currentBuilder = new SaxTaskBuilder(repositoryModel, repositoryManager);
+ currentBuilder.beginItem(attributes);
+
+ break;
+ case TaskListExternalizationConstants.NODE_QUERY:
+ checkState(currentBuilder == null, "Cannot begin reading a query while reading another task list element."); //$NON-NLS-1$
+
+ currentBuilder = new SaxQueryBuilder(repositoryModel, repositoryManager);
+ currentBuilder.beginItem(attributes);
+
+ break;
+ case TaskListExternalizationConstants.NODE_CATEGORY:
+ checkState(currentBuilder == null,
+ "Cannot begin reading a category while reading another task list element."); //$NON-NLS-1$
+
+ currentBuilder = new SaxCategoryBuilder(taskList);
+ currentBuilder.beginItem(attributes);
+
+ break;
+ case TaskListExternalizationConstants.NODE_ATTRIBUTE:
+ if (isOK(currentBuilder) && !currentBuilder.isAcceptingAttributeValues()) {
+ currentBuilder.startAttribute(attributes);
+ }
+
+ break;
+ case TaskListExternalizationConstants.NODE_SUB_TASK:
+ checkState(currentBuilder instanceof SaxTaskBuilder, "Cannot read a sub task hit unless reading a task"); //$NON-NLS-1$
+
+ recordHit(attributes, subTasks, (SaxTaskBuilder) currentBuilder);
+
+ break;
+ case TaskListExternalizationConstants.NODE_QUERY_HIT:
+ checkState(currentBuilder instanceof SaxQueryBuilder, "Cannot read a query hit unless reading a query"); //$NON-NLS-1$
+
+ recordHit(attributes, queryResults, (SaxQueryBuilder) currentBuilder);
+
+ break;
+ case TaskListExternalizationConstants.NODE_TASK_REFERENCE:
+ checkState(currentBuilder instanceof SaxCategoryBuilder,
+ "Cannot read a category hit unless reading a category"); //$NON-NLS-1$
+
+ recordHit(attributes, categorizedTasks, (SaxCategoryBuilder) currentBuilder);
+
+ break;
+ default:
+ break;
+ }
+
+ // don't attempt to make the root element an orphan
+ if (!TaskListExternalizationConstants.NODE_TASK_LIST.equals(localName)) {
+ orphanBuilder.startElement(localName, attributes);
+ }
+ }
+
+ @Override
+ public void characters(char ch[], int start, int length) throws SAXException {
+ if (isOK(currentBuilder) && currentBuilder.isAcceptingAttributeValues()) {
+ currentBuilder.acceptAttributeValueContent(ch, start, length);
+ }
+ orphanBuilder.acceptCharacters(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ switch (localName) {
+ case TaskListExternalizationConstants.NODE_TASK:
+ case TaskListExternalizationConstants.NODE_QUERY:
+ case TaskListExternalizationConstants.NODE_CATEGORY:
+ commitCurrentTopLevelElement();
+ currentBuilder = null;
+
+ break;
+ case TaskListExternalizationConstants.NODE_ATTRIBUTE:
+ if (isOK(currentBuilder) && currentBuilder.isAcceptingAttributeValues()) {
+ currentBuilder.endAttribute();
+ }
+
+ break;
+ case TaskListExternalizationConstants.NODE_TASK_LIST:
+ applyContainmentToTaskList(subTasks);
+ applyContainmentToTaskList(queryResults);
+ applyContainmentToTaskList(categorizedTasks);
+
+ break;
+ default:
+ break;
+ }
+
+ orphanBuilder.endElement();
+
+ }
+
+ private <T extends IRepositoryElement> void recordHit(Attributes attributes, Multimap<T, String> hitMap,
+ SaxTaskListElementBuilder<T> builder) {
+ String handle = attributes.getValue(TaskListExternalizationConstants.KEY_HANDLE);
+ if (!Strings.isNullOrEmpty(handle) && isOK(builder)) {
+ hitMap.put(builder.getItem(), handle);
+ }
+ }
+
+ private void commitCurrentTopLevelElement() throws SAXException {
+ checkState(currentBuilder != null,
+ "Cannot finish reading a task list element without a corresponding builder."); //$NON-NLS-1$
+
+ if (isOK(currentBuilder)) {
+ currentBuilder.addToTaskList(taskList);
+ } else {
+ if (!currentBuilder.getErrors().isOK()) {
+ StatusHandler.log(currentBuilder.getErrors());
+ }
+ orphanBuilder.commitOrphan();
+ }
+ }
+
+ private <T extends AbstractTaskContainer> void applyContainmentToTaskList(Multimap<T, String> containment) {
+ for (T container : containment.keySet()) {
+ Collection<String> handles = containment.get(container);
+ for (String handle : handles) {
+ AbstractTask subTask = taskList.getTask(handle);
+ if (subTask != null) {
+ taskList.addTask(subTask, container);
+ }
+ }
+ }
+ }
+
+ private boolean isOK(SaxTaskListElementBuilder<?> builder) {
+ return builder != null && builder.getErrors().isOK() && builder.getItem() != null;
+ }
+
+ public Document getOrphans() {
+ return orphanBuilder.getOrphans();
+ }
+
+ private void checkState(boolean condition, String message) throws SAXException {
+ if (!condition) {
+ throw new SAXException(message);
+ }
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizationConstants.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizationConstants.java
new file mode 100644
index 000000000..f3f037da8
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizationConstants.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.tasks.core.externalization;
+
+import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel;
+
+public class TaskListExternalizationConstants {
+ static final String DEFAULT_PRIORITY = PriorityLevel.P3.toString();
+
+ static final String OUT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.S Z"; //$NON-NLS-1$
+
+ static final String IN_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.S z"; //$NON-NLS-1$
+
+ static final String KEY_NOTIFIED_INCOMING = "NotifiedIncoming"; //$NON-NLS-1$
+
+ static final String KEY_NAME = "Name"; //$NON-NLS-1$
+
+ static final String KEY_LABEL = "Label"; //$NON-NLS-1$
+
+ static final String KEY_QUERY = "Query"; //$NON-NLS-1$
+
+ static final String KEY_QUERY_STRING = "QueryString"; //$NON-NLS-1$
+
+ static final String KEY_HANDLE = "Handle"; //$NON-NLS-1$
+
+ static final String KEY_REPOSITORY_URL = "RepositoryUrl"; //$NON-NLS-1$
+
+ static final String KEY_CATEGORY = "Category"; //$NON-NLS-1$
+
+ static final String VAL_ROOT = "Root"; //$NON-NLS-1$
+
+ static final String KEY_SUBTASK = "SubTask"; //$NON-NLS-1$
+
+ static final String KEY_KIND = "Kind"; //$NON-NLS-1$
+
+ static final String KEY_TASK_CATEGORY = "Task" + KEY_CATEGORY; //$NON-NLS-1$
+
+ static final String KEY_LINK = "Link"; //$NON-NLS-1$
+
+ static final String KEY_PLAN = "Plan"; //$NON-NLS-1$
+
+ static final String KEY_TIME_ESTIMATED = "Estimated"; //$NON-NLS-1$
+
+ static final String KEY_ISSUEURL = "IssueURL"; //$NON-NLS-1$
+
+ static final String KEY_NOTES = "Notes"; //$NON-NLS-1$
+
+ static final String KEY_ACTIVE = "Active"; //$NON-NLS-1$
+
+ static final String KEY_PRIORITY = "Priority"; //$NON-NLS-1$
+
+ static final String KEY_PATH = "Path"; //$NON-NLS-1$
+
+ static final String VAL_FALSE = "false"; //$NON-NLS-1$
+
+ static final String VAL_TRUE = "true"; //$NON-NLS-1$
+
+ static final String KEY_DATE_END = "EndDate"; //$NON-NLS-1$
+
+ static final String KEY_QUERY_HIT = "QueryHit"; //$NON-NLS-1$
+
+ static final String KEY_TASK_REFERENCE = "TaskReference"; //$NON-NLS-1$
+
+ static final String KEY_DATE_CREATION = "CreationDate"; //$NON-NLS-1$
+
+ static final String KEY_DATE_REMINDER = "ReminderDate"; //$NON-NLS-1$
+
+ static final String KEY_DATE_SCHEDULED_START = "ScheduledStartDate"; //$NON-NLS-1$
+
+ static final String KEY_DATE_SCHEDULED_END = "ScheduledEndDate"; //$NON-NLS-1$
+
+ static final String KEY_DATE_MODIFICATION = "ModificationDate"; //$NON-NLS-1$
+
+ static final String KEY_DATE_DUE = "DueDate"; //$NON-NLS-1$
+
+ static final String KEY_REMINDED = "Reminded"; //$NON-NLS-1$
+
+ static final String KEY_FLOATING = "Floating"; //$NON-NLS-1$
+
+ /**
+ * This element holds the date stamp recorded upon last transition to a synchronized state.
+ */
+ static final String KEY_LAST_MOD_DATE = "LastModified"; //$NON-NLS-1$
+
+ static final String KEY_DIRTY = "Dirty"; //$NON-NLS-1$
+
+ static final String KEY_SYNC_STATE = "offlineSyncState"; //$NON-NLS-1$
+
+ static final String KEY_OWNER = "Owner"; //$NON-NLS-1$
+
+ static final String KEY_OWNER_ID = "OwnerId"; //$NON-NLS-1$
+
+ static final String KEY_MARK_READ_PENDING = "MarkReadPending"; //$NON-NLS-1$
+
+ static final String KEY_STALE = "Stale"; //$NON-NLS-1$
+
+ static final String KEY_CONNECTOR_KIND = "ConnectorKind"; //$NON-NLS-1$
+
+ static final String KEY_TASK_ID = "TaskId"; //$NON-NLS-1$
+
+ static final String KEY_LAST_REFRESH = "LastRefreshTimeStamp"; //$NON-NLS-1$
+
+ static final String KEY_KEY = "Key"; //$NON-NLS-1$
+
+ static final String NODE_TASK_LIST = "TaskList"; //$NON-NLS-1$
+
+ static final String NODE_TASK = "Task"; //$NON-NLS-1$
+
+ static final String NODE_SUB_TASK = "SubTask"; //$NON-NLS-1$
+
+ static final String NODE_QUERY = "Query"; //$NON-NLS-1$
+
+ static final String NODE_QUERY_HIT = "QueryHit"; //$NON-NLS-1$
+
+ static final String NODE_CATEGORY = "TaskCategory"; //$NON-NLS-1$
+
+ static final String NODE_TASK_REFERENCE = "TaskReference"; //$NON-NLS-1$
+
+ static final String NODE_ATTRIBUTE = "Attribute"; //$NON-NLS-1$
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizer.java
index 0b9af2961..3ef523cf7 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizer.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/TaskListExternalizer.java
@@ -19,10 +19,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@@ -48,12 +45,16 @@ import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
import org.eclipse.mylyn.internal.tasks.core.ITransferList;
import org.eclipse.mylyn.internal.tasks.core.RepositoryModel;
import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery;
+import org.eclipse.mylyn.internal.tasks.core.XmlReaderUtil;
import org.eclipse.mylyn.tasks.core.AbstractTaskListMigrator;
import org.eclipse.mylyn.tasks.core.IRepositoryManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
/**
* @author Mik Kersten
@@ -76,28 +77,18 @@ public class TaskListExternalizer {
// Mylyn 3.0
private static final String VALUE_VERSION = "2.0"; //$NON-NLS-1$
- // Mylyn 2.3.2
- //private static final String VALUE_VERSION_1_0_1 = "1.0.1";
-
- private static final String VALUE_VERSION_1_0_0 = "1.0.0"; //$NON-NLS-1$
-
private final DelegatingTaskExternalizer delegatingExternalizer;
- private final List<Node> orphanedNodes = new ArrayList<Node>();
+ private final RepositoryModel repositoryModel;
- private Document orphanedDocument;
+ private final IRepositoryManager repositoryManager;
- private String readVersion = ""; //$NON-NLS-1$
+ private Document orphanDocument;
public TaskListExternalizer(RepositoryModel repositoryModel, IRepositoryManager repositoryManager) {
+ this.repositoryModel = repositoryModel;
+ this.repositoryManager = repositoryManager;
this.delegatingExternalizer = new DelegatingTaskExternalizer(repositoryModel, repositoryManager);
- try {
- this.orphanedDocument = createDocument();
- } catch (CoreException e) {
- this.orphanedDocument = null;
- StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
- "Failed to create document for orphaned nodes", e)); //$NON-NLS-1$
- }
}
public void initialize(List<AbstractTaskListMigrator> migrators) {
@@ -155,10 +146,14 @@ public class TaskListExternalizer {
}
// Persist orphaned tasks...
- for (Node node : orphanedNodes) {
- Node tempNode = doc.importNode(node, true);
- if (tempNode != null) {
- root.appendChild(tempNode);
+ if (orphanDocument != null) {
+ NodeList orphans = orphanDocument.getDocumentElement().getChildNodes();
+ for (int i = 0; i < orphans.getLength(); i++) {
+ Node node = orphans.item(i);
+ Node tempNode = doc.importNode(node, true);
+ if (tempNode != null) {
+ root.appendChild(tempNode);
+ }
}
}
@@ -189,8 +184,8 @@ public class TaskListExternalizer {
db = dbf.newDocumentBuilder();
return db.newDocument();
} catch (ParserConfigurationException e) {
- throw new CoreException(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
- "Failed to create document", e)); //$NON-NLS-1$
+ throw new CoreException(
+ new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Failed to create document", e)); //$NON-NLS-1$
}
}
@@ -204,106 +199,23 @@ public class TaskListExternalizer {
"Task list file contains no data \"" + inFile.getAbsolutePath() + "\"")); //$NON-NLS-1$ //$NON-NLS-2$
}
- delegatingExternalizer.reset();
- orphanedNodes.clear();
- try {
- this.orphanedDocument = createDocument();
- } catch (CoreException e) {
- this.orphanedDocument = null;
- StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
- "Failed to create document for orphaned nodes", e)); //$NON-NLS-1$
- }
-
- Document doc = openTaskList(inFile);
- Element root = doc.getDocumentElement();
- readVersion = root.getAttribute(ATTRIBUTE_VERSION);
- if (readVersion.equals(VALUE_VERSION_1_0_0)) {
- throw new CoreException(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Task list version \"" //$NON-NLS-1$
- + readVersion + "\" not supported")); //$NON-NLS-1$
- }
-
- NodeList list = root.getChildNodes();
-
- // read tasks
- Map<AbstractTask, NodeList> tasksWithSubtasks = new HashMap<AbstractTask, NodeList>();
- for (int i = 0; i < list.getLength(); i++) {
- Node child = list.item(i);
- if (!child.getNodeName().endsWith(DelegatingTaskExternalizer.KEY_CATEGORY)
- && !child.getNodeName().endsWith(DelegatingTaskExternalizer.KEY_QUERY)) {
- AbstractTask task = delegatingExternalizer.readTask(child, null, null);
- if (task != null) {
- taskList.addTask(task);
- if (child.getChildNodes() != null && child.getChildNodes().getLength() > 0) {
- tasksWithSubtasks.put(task, child.getChildNodes());
- }
- } else {
- addOrphan(child);
- }
- }
- }
- // create subtask hierarchy
- for (AbstractTask task : tasksWithSubtasks.keySet()) {
- NodeList nodes = tasksWithSubtasks.get(task);
- delegatingExternalizer.readTaskReferences(task, nodes, taskList);
- }
-
- // read queries
- for (int i = 0; i < list.getLength(); i++) {
- Node child = list.item(i);
- if (child.getNodeName().endsWith(DelegatingTaskExternalizer.KEY_QUERY)) {
- RepositoryQuery query = delegatingExternalizer.readQuery(child);
- if (query != null) {
- taskList.addQuery(query);
- if (child.getChildNodes() != null && child.getChildNodes().getLength() > 0) {
- delegatingExternalizer.readTaskReferences(query, child.getChildNodes(), taskList);
- }
- } else {
- addOrphan(child);
- }
- }
- }
-
- // Read Categories
- for (int i = 0; i < list.getLength(); i++) {
- Node child = list.item(i);
- if (child.getNodeName().endsWith(DelegatingTaskExternalizer.KEY_CATEGORY)) {
- delegatingExternalizer.readCategory(child, taskList);
- }
- }
-
- // Legacy migration for task nodes that have the old Category handle on the element
- Map<AbstractTask, String> legacyParentCategoryMap = delegatingExternalizer.getLegacyParentCategoryMap();
- if (legacyParentCategoryMap.size() > 0) {
- for (AbstractTask task : legacyParentCategoryMap.keySet()) {
- AbstractTaskCategory category = taskList.getContainerForHandle(legacyParentCategoryMap.get(task));
- if (category != null) {
- taskList.addTask(task, category);
- }
- }
- }
-
-// if (delegatingExternalizer.getErrorStatus() != null) {
-// StatusHandler.log(delegatingExternalizer.getErrorStatus());
-// }
- }
-
- private void addOrphan(Node child) {
- // copy node to separate document to avoid retaining entire dom
- if (orphanedDocument != null) {
- orphanedNodes.add(orphanedDocument.importNode(child, true));
- } else {
- orphanedNodes.add(child);
+ try (InputStream taskListFile = openTaskList(inFile)) {
+ XMLReader reader = XmlReaderUtil.createXmlReader();
+ SaxTaskListHandler handler = new SaxTaskListHandler(taskList, repositoryModel, repositoryManager);
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(taskListFile));
+ this.orphanDocument = handler.getOrphans();
+ } catch (SAXException | IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, e.getMessage(), e));
}
}
/**
- * Opens the specified XML file and parses it into a DOM Document. Filename - the name of the file to open Return -
- * the Document built from the XML file Throws - XMLException if the file cannot be parsed as XML - IOException if
- * the file cannot be opened
- *
+ * Opens the specified XML file
+ *
* @throws CoreException
*/
- private Document openTaskList(File inputFile) throws CoreException {
+ private InputStream openTaskList(File inputFile) throws CoreException {
InputStream in = null;
try {
if (inputFile.getName().endsWith(ITasksCoreConstants.FILE_EXTENSION)) {
@@ -323,20 +235,9 @@ public class TaskListExternalizer {
in = new FileInputStream(inputFile);
}
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- return builder.parse(in);
+ return in;
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, ERROR_TASKLIST_READ, e));
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
- "Failed to close task list", e)); //$NON-NLS-1$
- }
- }
}
}

Back to the top