Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrandon Dong2016-05-19 20:11:51 +0000
committerGerrit Code Review @ Eclipse.org2016-06-08 18:38:38 +0000
commitee58f27b5dd6f493a23240024655e8d37293356d (patch)
treef28c5eb41307f594f80a785c02688d1aee04df9a
parentc7b61a4748ba0ca0687fef5563165c01cfde0dc3 (diff)
downloadorg.eclipse.mylyn.tasks-ee58f27b5dd6f493a23240024655e8d37293356d.tar.gz
org.eclipse.mylyn.tasks-ee58f27b5dd6f493a23240024655e8d37293356d.tar.xz
org.eclipse.mylyn.tasks-ee58f27b5dd6f493a23240024655e8d37293356d.zip
494568: support refactoring task ids
Change-Id: I32f749d32f072bb05045e4749717309df8f4cb86 Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=495066 Signed-off-by: Brandon Dong <brandon.dong@tasktop.com>
-rw-r--r--org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskActivityManager.java41
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskList.java49
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataManager.java21
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataState.java12
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/Messages.java31
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/RefactorTaskIdsOperation.java93
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/TaskListOperation.java74
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/messages.properties3
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/context/AbstractTaskContextStore.java23
-rw-r--r--org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskActivityManagerTest.java25
-rw-r--r--org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskListTest.java99
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskListModifyOperation.java52
13 files changed, 447 insertions, 77 deletions
diff --git a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF
index 3aa2fbf69..f876ffa5f 100644
--- a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF
@@ -18,6 +18,7 @@ Export-Package: org.eclipse.mylyn.internal.tasks.core;x-friends:="org.eclipse.my
org.eclipse.mylyn.internal.tasks.core.context;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs",
org.eclipse.mylyn.internal.tasks.core.data;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs",
org.eclipse.mylyn.internal.tasks.core.externalization;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs",
+ org.eclipse.mylyn.internal.tasks.core.operations;x-friends:="org.eclipse.mylyn.tasks.ui",
org.eclipse.mylyn.internal.tasks.core.sync;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs",
org.eclipse.mylyn.internal.tasks.core.util;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs",
org.eclipse.mylyn.tasks.core,
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskActivityManager.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskActivityManager.java
index 99c302836..038209bec 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskActivityManager.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskActivityManager.java
@@ -62,12 +62,15 @@ public class TaskActivityManager implements ITaskActivityManager2 {
private final Set<ITask> allDueTasks = new HashSet<ITask>();
- private final SortedMap<DateRange, Set<ITask>> scheduledTasks = Collections.synchronizedSortedMap(new TreeMap<DateRange, Set<ITask>>());
+ private final SortedMap<DateRange, Set<ITask>> scheduledTasks = Collections
+ .synchronizedSortedMap(new TreeMap<DateRange, Set<ITask>>());
- private final SortedMap<Calendar, Set<ITask>> dueTasks = Collections.synchronizedSortedMap(new TreeMap<Calendar, Set<ITask>>());
+ private final SortedMap<Calendar, Set<ITask>> dueTasks = Collections
+ .synchronizedSortedMap(new TreeMap<Calendar, Set<ITask>>());
// Map of Calendar (hour) to Tasks active during that hour
- private final SortedMap<Calendar, Set<AbstractTask>> activeTasks = Collections.synchronizedSortedMap(new TreeMap<Calendar, Set<AbstractTask>>());
+ private final SortedMap<Calendar, Set<AbstractTask>> activeTasks = Collections
+ .synchronizedSortedMap(new TreeMap<Calendar, Set<AbstractTask>>());
// For a given task maps Calendar Hour to duration of time spent (milliseconds) with task active
private final Map<AbstractTask, SortedMap<Calendar, Long>> taskElapsedTimeMap = new ConcurrentHashMap<AbstractTask, SortedMap<Calendar, Long>>();
@@ -118,7 +121,8 @@ public class TaskActivityManager implements ITaskActivityManager2 {
listenersInitialized = true;
IExtensionRegistry registry = Platform.getExtensionRegistry();
- IExtensionPoint listenerExtensionPoint = registry.getExtensionPoint(TaskActivityManager.ID_EXTENSION_TASK_ACTIVATION_LISTENERS);
+ IExtensionPoint listenerExtensionPoint = registry
+ .getExtensionPoint(TaskActivityManager.ID_EXTENSION_TASK_ACTIVATION_LISTENERS);
IExtension[] listenerExtensions = listenerExtensionPoint.getExtensions();
for (IExtension extension : listenerExtensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
@@ -129,18 +133,15 @@ public class TaskActivityManager implements ITaskActivityManager2 {
if (object instanceof ITaskActivationListener) {
addActivationListener((ITaskActivationListener) object);
} else {
- StatusHandler.log(new Status(
- IStatus.ERROR,
- ITasksCoreConstants.ID_PLUGIN,
- NLS.bind(
- "Unexpected error registering listener contributed by {0}: ''{1}'' does not extend expected class", //$NON-NLS-1$
- element.getContributor().getName(), object.getClass()
- .getCanonicalName())));
+ StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, NLS.bind(
+ "Unexpected error registering listener contributed by {0}: ''{1}'' does not extend expected class", //$NON-NLS-1$
+ element.getContributor().getName(), object.getClass().getCanonicalName())));
}
} catch (Throwable e) {
- StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, NLS.bind(
- "Unexpected error registering listener contributed by {0}", //$NON-NLS-1$
- element.getContributor().getName()), e));
+ StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
+ NLS.bind("Unexpected error registering listener contributed by {0}", //$NON-NLS-1$
+ element.getContributor().getName()),
+ e));
}
}
}
@@ -689,6 +690,18 @@ public class TaskActivityManager implements ITaskActivityManager2 {
taskList.notifyElementChanged(task);
}
+ public void moveActivity(ITask oldTask, AbstractTask newTask) {
+ setDueDate(newTask, oldTask.getDueDate());
+ if (oldTask instanceof AbstractTask) {
+ setScheduledFor(newTask, ((AbstractTask) oldTask).getScheduledForDate());
+ }
+ if (oldTask.isActive()) {
+ activateTask(newTask);
+ }
+ removeDueTask(oldTask);
+ removeScheduledTask(oldTask);
+ }
+
/**
* @return if a repository task, will only return true if the user is a
*/
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskList.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskList.java
index 28ba83a1a..72190ee2e 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskList.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskList.java
@@ -568,6 +568,55 @@ public class TaskList implements ITaskList, ITransferList {
}
}
+ public AbstractTask refactorTaskId(ITask oldTask, String newTaskId) {
+ TaskTask newTask = new TaskTask(oldTask.getConnectorKind(), oldTask.getRepositoryUrl(), newTaskId);
+
+ newTask.setSummary(oldTask.getSummary());
+ newTask.setPriority(oldTask.getPriority());
+ newTask.setSynchronizationState(oldTask.getSynchronizationState());
+ newTask.setCompletionDate(oldTask.getCompletionDate());
+ newTask.setCreationDate(oldTask.getCreationDate());
+ newTask.setModificationDate(oldTask.getModificationDate());
+ newTask.setTaskKind(oldTask.getTaskKind());
+ newTask.setOwnerId(oldTask.getOwnerId());
+ newTask.setOwner(oldTask.getOwner());
+ newTask.setTaskKey(oldTask.getTaskKey());
+ if (oldTask instanceof AbstractTask) {
+ AbstractTask task = (AbstractTask) oldTask;
+ newTask.setSynchronizing(task.isSynchronizing());
+ newTask.setMarkReadPending(task.isMarkReadPending());
+ newTask.setNotified(task.isNotified());
+ newTask.setChanged(task.isChanged());
+ newTask.setReminded(task.isReminded());
+ newTask.setStatus(task.getStatus());
+ newTask.setNotes(task.getNotes());
+ newTask.setEstimatedTimeHours(task.getEstimatedTimeHours());
+ addTaskContainers(task, newTask);
+ }
+ Map<String, String> attributeMap = oldTask.getAttributes();
+ for (String key : attributeMap.keySet()) {
+ newTask.setAttribute(key, attributeMap.get(key));
+ }
+
+ deleteTask(oldTask);
+ return newTask;
+ }
+
+ private void addTaskContainers(AbstractTask oldTask, AbstractTask newTask) {
+ Set<AbstractTaskContainer> containers = oldTask.getParentContainers();
+ if (containers.isEmpty()
+ || (containers.size() == 1 && containers.iterator().next() instanceof UnmatchedTaskContainer)) {
+ addTask(newTask);
+ } else {
+ for (AbstractTaskContainer container : containers) {
+ addTask(newTask, container);
+ }
+ }
+ for (ITask subtask : oldTask.getChildren()) {
+ addTask(subtask, newTask);
+ }
+ }
+
public void removeChangeListener(ITaskListChangeListener listener) {
changeListeners.remove(listener);
}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataManager.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataManager.java
index 39a46aca0..710239789 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataManager.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataManager.java
@@ -618,4 +618,25 @@ public class TaskDataManager implements ITaskDataManager {
}
});
}
+
+ public void refactorTaskId(final AbstractTask task, final ITask newTask) throws CoreException {
+ final String kind = task.getConnectorKind();
+ taskList.run(new ITaskListRunnable() {
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ File file = getMigratedFile(task, kind);
+ if (file.exists()) {
+ TaskDataState oldState = taskDataStore.getTaskDataState(file);
+ if (oldState != null) {
+ File newFile = getFile(task.getRepositoryUrl(), newTask, kind);
+ TaskDataState newState = new TaskDataState(oldState.getConnectorKind(), task.getRepositoryUrl(),
+ newTask.getTaskId());
+ newState.merge(oldState);
+ taskDataStore.putTaskData(ensurePathExists(newFile), newState);
+ taskDataStore.deleteTaskData(file);
+ }
+ }
+ }
+
+ });
+ }
}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataState.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataState.java
index 576776405..9cca8ae93 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataState.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataState.java
@@ -197,9 +197,9 @@ public class TaskDataState implements ITaskDataWorkingCopy {
}
public void merge(TaskDataState oldState) {
- setEditsData(createCopy(oldState.getEditsData()));
- setLocalTaskData(createCopy(oldState.getLocalData()));
- setRepositoryData(createCopy(oldState.getRepositoryData()));
+ setEditsData(createCopy(oldState.getEditsData(), getTaskId()));
+ setLocalTaskData(createCopy(oldState.getLocalData(), getTaskId()));
+ setRepositoryData(createCopy(oldState.getRepositoryData(), getTaskId()));
}
public void changeAttributeValues(ListMultimap<TaskAttribute, String> newValues) {
@@ -221,11 +221,15 @@ public class TaskDataState implements ITaskDataWorkingCopy {
}
public static TaskData createCopy(TaskData oldData) {
+ return createCopy(oldData, oldData.getTaskId());
+ }
+
+ private static TaskData createCopy(TaskData oldData, String newTaskId) {
if (oldData == null) {
return null;
}
TaskData newData = new TaskData(oldData.getAttributeMapper(), oldData.getConnectorKind(),
- oldData.getRepositoryUrl(), oldData.getTaskId());
+ oldData.getRepositoryUrl(), newTaskId);
newData.setVersion(oldData.getVersion());
for (TaskAttribute child : oldData.getRoot().getAttributes().values()) {
newData.getRoot().deepAddCopy(child);
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/Messages.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/Messages.java
new file mode 100644
index 000000000..3061d939b
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/Messages.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.operations;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.mylyn.internal.tasks.core.operations.messages"; //$NON-NLS-1$
+
+ public static String RefactorTaskIdsOperation_FailedTaskCount;
+
+ public static String RefactorTaskIdsOperation_TaskDataRefactorError;
+
+ public static String RefactorTaskIdsOperation_UpdateTaskId;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/RefactorTaskIdsOperation.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/RefactorTaskIdsOperation.java
new file mode 100644
index 000000000..2e997e657
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/RefactorTaskIdsOperation.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.operations;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
+import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.TaskActivityManager;
+import org.eclipse.mylyn.internal.tasks.core.TaskList;
+import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager;
+import org.eclipse.mylyn.tasks.core.ITask;
+import org.eclipse.mylyn.tasks.core.context.AbstractTaskContextStore;
+import org.eclipse.osgi.util.NLS;
+
+public class RefactorTaskIdsOperation extends TaskListOperation {
+
+ private final Map<ITask, String> newTaskIdMap;
+
+ private final TaskActivityManager activityManager;
+
+ private final AbstractTaskContextStore contextStore;
+
+ private final TaskDataManager taskDataManager;
+
+ public RefactorTaskIdsOperation(Map<ITask, String> newTaskIdMap, TaskList taskList,
+ TaskActivityManager activityManager, AbstractTaskContextStore contextStore,
+ TaskDataManager taskDataManager) {
+ super(ITasksCoreConstants.ROOT_SCHEDULING_RULE, taskList);
+ this.newTaskIdMap = newTaskIdMap;
+ this.activityManager = activityManager;
+ this.contextStore = contextStore;
+ this.taskDataManager = taskDataManager;
+ }
+
+ @Override
+ protected void operations(IProgressMonitor monitor)
+ throws CoreException, InvocationTargetException, InterruptedException {
+ try {
+ monitor.beginTask(Messages.RefactorTaskIdsOperation_UpdateTaskId, newTaskIdMap.size() * 2);
+ Map<ITask, ITask> map = new HashMap<>();
+ MultiStatus status = new MultiStatus(ITasksCoreConstants.ID_PLUGIN, IStatus.OK, null, null);
+
+ for (ITask task : newTaskIdMap.keySet()) {
+ AbstractTask newTask = getTaskList().refactorTaskId(task, newTaskIdMap.get(task));
+ map.put(task, newTask);
+
+ activityManager.moveActivity(task, newTask);
+ if (task instanceof AbstractTask) {
+ try {
+ taskDataManager.refactorTaskId((AbstractTask) task, newTask);
+ } catch (CoreException e) {
+ status.add(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN,
+ NLS.bind(Messages.RefactorTaskIdsOperation_TaskDataRefactorError, task), e));
+ }
+ }
+ monitor.worked(1);
+ }
+
+ contextStore.moveContext(map);
+ monitor.worked(newTaskIdMap.size());
+ handleFailedMigrations(status);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private void handleFailedMigrations(MultiStatus status) throws CoreException {
+ if (!status.isOK()) {
+ MultiStatus errorStatus = new MultiStatus(ITasksCoreConstants.ID_PLUGIN, IStatus.ERROR,
+ NLS.bind(Messages.RefactorTaskIdsOperation_FailedTaskCount, status.getChildren().length), null);
+ errorStatus.merge(status);
+ throw new CoreException(errorStatus);
+ }
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/TaskListOperation.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/TaskListOperation.java
new file mode 100644
index 000000000..42a73f20b
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/TaskListOperation.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.operations;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.mylyn.internal.tasks.core.ITaskListRunnable;
+import org.eclipse.mylyn.internal.tasks.core.TaskList;
+
+public abstract class TaskListOperation {
+
+ private final ISchedulingRule rule;
+
+ private final TaskList taskList;
+
+ public TaskListOperation(TaskList taskList) {
+ this(null, taskList);
+ }
+
+ public TaskListOperation(ISchedulingRule rule, TaskList taskList) {
+ this.rule = rule;
+ this.taskList = taskList;
+ }
+
+ protected abstract void operations(IProgressMonitor monitor)
+ throws CoreException, InvocationTargetException, InterruptedException;
+
+ final public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ final InvocationTargetException[] ite = new InvocationTargetException[1];
+ try {
+ ITaskListRunnable runnable = new ITaskListRunnable() {
+
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ Job.getJobManager().beginRule(rule, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
+ operations(monitor);
+ } catch (InvocationTargetException e) {
+ ite[0] = e;
+ } catch (InterruptedException e) {
+ throw new OperationCanceledException(e.getMessage());
+ } finally {
+ Job.getJobManager().endRule(rule);
+ }
+ }
+ };
+ getTaskList().run(runnable, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ }
+
+ if (ite[0] != null) {
+ throw ite[0];
+ }
+ }
+
+ protected TaskList getTaskList() {
+ return taskList;
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/messages.properties b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/messages.properties
new file mode 100644
index 000000000..6b30524b1
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/operations/messages.properties
@@ -0,0 +1,3 @@
+RefactorTaskIdsOperation_FailedTaskCount={0} tasks failed to migrate
+RefactorTaskIdsOperation_TaskDataRefactorError=Error while migrating task data for {0}
+RefactorTaskIdsOperation_UpdateTaskId=Task ID Update
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/context/AbstractTaskContextStore.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/context/AbstractTaskContextStore.java
index 458e57592..1b93105e4 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/context/AbstractTaskContextStore.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/context/AbstractTaskContextStore.java
@@ -12,6 +12,7 @@
package org.eclipse.mylyn.tasks.core.context;
import java.io.File;
+import java.util.Map;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.mylyn.tasks.core.ITask;
@@ -19,7 +20,7 @@ import org.eclipse.mylyn.tasks.core.TaskRepository;
/**
* A store for persisting task contexts.
- *
+ *
* @author Steffen Pingel
* @since 3.7
*/
@@ -27,7 +28,7 @@ public abstract class AbstractTaskContextStore {
/**
* Clears the context of <code>task</code>.
- *
+ *
* @since 3.7
*/
public abstract void clearContext(ITask task);
@@ -35,7 +36,7 @@ public abstract class AbstractTaskContextStore {
/**
* Copies the context from <code>sourceTask</code> to <code>destinationTask</code>. Creates a new context if a
* <code>sourceTask</code> does not have a context.
- *
+ *
* @return result of the copy operation
* @since 3.7
*/
@@ -43,14 +44,14 @@ public abstract class AbstractTaskContextStore {
/**
* Deletes the context of <code>task</code>.
- *
+ *
* @since 3.7
*/
public abstract void deleteContext(ITask task);
/**
* Return the location of the context for <code>task</code>.
- *
+ *
* @return null, if context for <code>task</code> does not exist
* @since 3.7
*/
@@ -69,7 +70,7 @@ public abstract class AbstractTaskContextStore {
/**
* Moves the context from <code>sourceTask</code> to <code>destinationTask</code>. Creates a new context if a
* <code>sourceTask</code> does not have a context.
- *
+ *
* @return result of the move operation
* @since 3.7
*/
@@ -94,9 +95,17 @@ public abstract class AbstractTaskContextStore {
/**
* Sets the location of task file.
- *
+ *
* @since 3.7
*/
public abstract void setDirectory(File directory);
+ /**
+ * Moves the context from tasks in the keyset of <code>tasks</code> to their corresponding values.
+ *
+ * @since 3.20
+ */
+ public void moveContext(Map<ITask, ITask> tasks) {
+ }
+
}
diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskActivityManagerTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskActivityManagerTest.java
index 09ff011da..11acb414d 100644
--- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskActivityManagerTest.java
+++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskActivityManagerTest.java
@@ -13,10 +13,9 @@
package org.eclipse.mylyn.tasks.tests;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Date;
-import junit.framework.TestCase;
-
import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
import org.eclipse.mylyn.commons.net.AuthenticationType;
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
@@ -32,6 +31,8 @@ import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector;
import org.eclipse.mylyn.tasks.tests.connector.MockTask;
+import junit.framework.TestCase;
+
/**
* @author Shawn Minto
* @author Robert Elves
@@ -172,6 +173,7 @@ public class TaskActivityManagerTest extends TestCase {
protected void setUp() throws Exception {
taskActivityManager = TasksUiPlugin.getTaskActivityManager();
taskActivityManager.deactivateActiveTask();
+ taskActivityManager.clear();
taskList = TasksUiPlugin.getTaskList();
TaskTestUtil.resetTaskListAndRepositories();
@@ -393,6 +395,25 @@ public class TaskActivityManagerTest extends TestCase {
assertNull(taskActivityManager.getActiveTask());
}
+ public void testMoveActivity() {
+ initializeTasks();
+ Calendar end = TaskActivityUtil.getNextWeek().getEndDate();
+ Calendar start = TaskActivityUtil.getCalendar();
+ start.setTimeInMillis(end.getTimeInMillis());
+ TaskActivityUtil.snapStartOfDay(start);
+ taskActivityManager.setScheduledFor(task1, new DateRange(start, end));
+ taskActivityManager.setDueDate(task1, new Date(start.getTimeInMillis() + 1));
+ assertEquals(Collections.singleton(task1), taskActivityManager.getScheduledTasks(start, end));
+ assertEquals(Collections.singleton(task1), taskActivityManager.getDueTasks(start, end));
+ taskActivityManager.activateTask(task1);
+
+ taskActivityManager.moveActivity(task1, task2);
+ assertEquals(Collections.singleton(task2), taskActivityManager.getScheduledTasks(start, end));
+ assertEquals(Collections.singleton(task2), taskActivityManager.getDueTasks(start, end));
+ assertTrue(task2.isActive());
+ assertEquals(task2, taskActivityManager.getActiveTask());
+ }
+
private void initializeTasks() {
task1 = new LocalTask("task1", "description1");
task2 = new LocalTask("task2", "description2");
diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskListTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskListTest.java
index fedeb6c19..d9625d99b 100644
--- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskListTest.java
+++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/TaskListTest.java
@@ -13,8 +13,6 @@ package org.eclipse.mylyn.tasks.tests;
import java.util.Set;
-import junit.framework.TestCase;
-
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskContainer;
@@ -22,12 +20,15 @@ import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector;
import org.eclipse.mylyn.internal.tasks.core.LocalTask;
import org.eclipse.mylyn.internal.tasks.core.TaskCategory;
import org.eclipse.mylyn.internal.tasks.core.TaskList;
+import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITaskContainer;
import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector;
import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryQuery;
import org.eclipse.mylyn.tasks.tests.connector.MockTask;
+import junit.framework.TestCase;
+
/**
* @author Mik Kersten
* @author Rob Elves
@@ -458,6 +459,100 @@ public class TaskListTest extends TestCase {
assertEquals(0, taskList.getDefaultCategory().getChildren().size());
}
+ public void testRefactorSingleTask() {
+ AbstractTask task = new LocalTask("1", "label");
+ taskList.addTask(task);
+ taskList.refactorTaskId(task, "2");
+ assertEquals(1, taskList.getAllTasks().size());
+ assertEquals(1, taskList.getDefaultCategory().getChildren().size());
+ assertEquals(new LocalTask("2", "label"), taskList.getAllTasks().iterator().next());
+ }
+
+ public void testRefactorSingleTaskInUnmatched() {
+ String repositoryUrl = "http://somewhere.com";
+ MockTask task = new MockTask(repositoryUrl, "1");
+ UnmatchedTaskContainer unmatched = new UnmatchedTaskContainer(task.getConnectorKind(), repositoryUrl);
+ taskList.addUnmatchedContainer(unmatched);
+ taskList.addTask(task);
+ taskList.refactorTaskId(task, "2");
+ assertEquals(1, taskList.getAllTasks().size());
+ assertEquals(1, unmatched.getChildren().size());
+ assertEquals(new MockTask(repositoryUrl, "2"), taskList.getAllTasks().iterator().next());
+ assertEquals(new MockTask(repositoryUrl, "2"), unmatched.getChildren().iterator().next());
+ }
+
+ public void testRefactorSingleTaskKeepsProperties() {
+ AbstractTask task = new LocalTask("1", "label");
+ taskList.addTask(task);
+ taskList.refactorTaskId(task, "2");
+ assertEquals(1, taskList.getAllTasks().size());
+ AbstractTask refactoredTask = taskList.getAllTasks().iterator().next();
+ assertEquals(new LocalTask("2", "label"), refactoredTask);
+ assertEquals(task.getRepositoryUrl(), refactoredTask.getRepositoryUrl());
+ assertEquals(task.getConnectorKind(), refactoredTask.getConnectorKind());
+ assertEquals(task.getAttributes(), refactoredTask.getAttributes());
+ assertEquals(task.getSummary(), refactoredTask.getSummary());
+ assertEquals(task.getPriority(), refactoredTask.getPriority());
+ }
+
+ public void testRefactorTaskInQuery() {
+ MockRepositoryQuery query = new MockRepositoryQuery("query");
+ taskList.addQuery(query);
+ MockTask task = new MockTask("1");
+ taskList.addTask(task, query);
+ taskList.refactorTaskId(task, "2");
+ assertEquals(1, taskList.getAllTasks().size());
+ assertEquals(0, taskList.getDefaultCategory().getChildren().size());
+ assertEquals(1, query.getChildren().size());
+ assertEquals(new MockTask("2"), query.getChildren().iterator().next());
+ assertEquals(new MockTask("2"), taskList.getAllTasks().iterator().next());
+ }
+
+ public void testRefactorTaskInCategory() {
+ TaskCategory category = new TaskCategory("category");
+ taskList.addCategory(category);
+ MockTask task = new MockTask("1");
+ taskList.addTask(task, category);
+ taskList.refactorTaskId(task, "2");
+ assertEquals(1, taskList.getAllTasks().size());
+ assertEquals(0, taskList.getDefaultCategory().getChildren().size());
+ assertEquals(1, category.getChildren().size());
+ assertEquals(new MockTask("2"), category.getChildren().iterator().next());
+ assertEquals(new MockTask("2"), taskList.getAllTasks().iterator().next());
+ }
+
+ public void testRefactorTaskWithSubtask() {
+ AbstractTask task = new LocalTask("1", "label");
+ AbstractTask subtask = new LocalTask("2", "subtask");
+ taskList.addTask(task);
+ taskList.addTask(subtask, task);
+ taskList.refactorTaskId(task, "3");
+ assertEquals(2, taskList.getAllTasks().size());
+ assertEquals(1, taskList.getDefaultCategory().getChildren().size());
+ assertEquals(1, subtask.getParentContainers().size());
+ AbstractTaskContainer refactoredTask = subtask.getParentContainers().iterator().next();
+ assertEquals(new LocalTask("3", "label"), refactoredTask);
+ assertTrue(taskList.getAllTasks().contains(refactoredTask));
+ assertEquals(1, refactoredTask.getChildren().size());
+ assertEquals(subtask, refactoredTask.getChildren().iterator().next());
+ }
+
+ public void testRefactorTaskWithParent() {
+ AbstractTask task = new LocalTask("1", "label");
+ AbstractTask parent = new LocalTask("2", "parent");
+ taskList.addTask(parent);
+ taskList.addTask(task, parent);
+ taskList.refactorTaskId(task, "3");
+ assertEquals(2, taskList.getAllTasks().size());
+ assertEquals(1, taskList.getDefaultCategory().getChildren().size());
+ assertEquals(1, parent.getChildren().size());
+ AbstractTask refactoredTask = (AbstractTask) parent.getChildren().iterator().next();
+ assertEquals(new LocalTask("3", "label"), refactoredTask);
+ assertTrue(taskList.getAllTasks().contains(refactoredTask));
+ assertEquals(1, refactoredTask.getParentContainers().size());
+ assertEquals(parent, refactoredTask.getParentContainers().iterator().next());
+ }
+
public void testgetQueriesAndHitsForHandle() {
MockTask hit1 = new MockTask("1");
MockTask hit2 = new MockTask("2");
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskListModifyOperation.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskListModifyOperation.java
index 95359f02f..e68466343 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskListModifyOperation.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskListModifyOperation.java
@@ -11,68 +11,24 @@
package org.eclipse.mylyn.internal.tasks.ui;
-import java.lang.reflect.InvocationTargetException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.mylyn.internal.tasks.core.ITaskListRunnable;
-import org.eclipse.mylyn.internal.tasks.core.TaskList;
+import org.eclipse.mylyn.internal.tasks.core.operations.TaskListOperation;
/**
* Use to perform atomic operations on the task list i.e. open/restore
- *
+ *
* @author Rob Elves
* @since 3.0
*/
-public abstract class TaskListModifyOperation implements IRunnableWithProgress {
-
- ISchedulingRule rule;
+public abstract class TaskListModifyOperation extends TaskListOperation implements IRunnableWithProgress {
public TaskListModifyOperation() {
this(null);
}
public TaskListModifyOperation(ISchedulingRule rule) {
- this.rule = rule;
+ super(rule, TasksUiPlugin.getTaskList());
}
- protected abstract void operations(IProgressMonitor monitor) throws CoreException, InvocationTargetException,
- InterruptedException;
-
- final public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- final InvocationTargetException[] ite = new InvocationTargetException[1];
- try {
- ITaskListRunnable runnable = new ITaskListRunnable() {
-
- public void execute(IProgressMonitor monitor) throws CoreException {
- try {
- Job.getJobManager().beginRule(rule, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
- operations(monitor);
- } catch (InvocationTargetException e) {
- ite[0] = e;
- } catch (InterruptedException e) {
- throw new OperationCanceledException(e.getMessage());
- } finally {
- Job.getJobManager().endRule(rule);
- }
- }
- };
- getTaskList().run(runnable, monitor);
- } catch (CoreException e) {
- throw new InvocationTargetException(e);
- }
-
- if (ite[0] != null) {
- throw ite[0];
- }
- }
-
- protected TaskList getTaskList() {
- return TasksUiPlugin.getTaskList();
- }
}

Back to the top