diff options
author | Brandon Dong | 2016-05-19 20:11:51 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-06-08 18:38:38 +0000 |
commit | ee58f27b5dd6f493a23240024655e8d37293356d (patch) | |
tree | f28c5eb41307f594f80a785c02688d1aee04df9a | |
parent | c7b61a4748ba0ca0687fef5563165c01cfde0dc3 (diff) | |
download | org.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>
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(); - } } |