Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Davis2015-11-20 23:42:17 +0000
committerSam Davis2016-01-23 00:59:49 +0000
commit27d4ded07550dbc873407d291b3fcbadf377786a (patch)
tree5a7c9aabbce4c5dcf6d5e429ea5a183706d40536
parente5647f87f2d289148a4e5aa13ecb67d8f7546301 (diff)
downloadorg.eclipse.mylyn.tasks-27d4ded07550dbc873407d291b3fcbadf377786a.tar.gz
org.eclipse.mylyn.tasks-27d4ded07550dbc873407d291b3fcbadf377786a.tar.xz
org.eclipse.mylyn.tasks-27d4ded07550dbc873407d291b3fcbadf377786a.zip
485380: [api] connectors can search by task key
Change-Id: I512052246726ff51c1490b8b9f205c443fc8a562 Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=485380
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java117
-rw-r--r--org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJobTest.java33
-rw-r--r--org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJob.java45
3 files changed, 151 insertions, 44 deletions
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java
index 7603904a6..23fbb213a 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java
@@ -105,7 +105,7 @@ import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
* <li>{@link #canSynchronizeTask(TaskRepository, ITask)} returns <code>false</code> so full task data is never
* retrieved
* </ul>
- *
+ *
* @author Mik Kersten
* @author Rob Elves
* @author Shawn Minto
@@ -118,7 +118,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns true, if the connector provides a wizard for creating new tasks.
- *
+ *
* @since 2.0
*/
// TODO move this to ConnectorUi.hasNewTaskWizard()
@@ -126,14 +126,14 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns true, if the connector supports retrieval of tasks based on String keys.
- *
+ *
* @since 2.0
*/
public abstract boolean canCreateTaskFromKey(@NonNull TaskRepository repository);
/**
* Returns true, if the connector supports retrieval of task history for <code>task</code>.
- *
+ *
* @see #getHistory(TaskRepository, ITask, IProgressMonitor)
* @since 3.6
*/
@@ -143,7 +143,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns true, if the connector supports querying the repository.
- *
+ *
* @since 3.0
* @see #performQuery(TaskRepository, IRepositoryQuery, TaskDataCollector, ISynchronizationSession,
* IProgressMonitor)
@@ -154,7 +154,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns true, if the connectors support retrieving full task data for <code>task</code>.
- *
+ *
* @since 3.0
* @see #getTaskData(TaskRepository, String, IProgressMonitor)
*/
@@ -164,7 +164,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns true, if the connector supports deletion of <code>task</code> which is part of <code>repository</code>.
- *
+ *
* @since 3.3
*/
public boolean canDeleteTask(@NonNull TaskRepository repository, @NonNull ITask task) {
@@ -174,7 +174,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Return true, if the connector supports creation of task repositories. The default default implementation returns
* true.
- *
+ *
* @since 3.4
*/
public boolean canCreateRepository() {
@@ -183,7 +183,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns the unique kind of the repository, e.g. "bugzilla".
- *
+ *
* @since 2.0
*/
@NonNull
@@ -191,7 +191,7 @@ public abstract class AbstractRepositoryConnector {
/**
* The connector's summary i.e. "JIRA (supports 3.3.1 and later)"
- *
+ *
* @since 2.0
*/
@NonNull
@@ -203,7 +203,7 @@ public abstract class AbstractRepositoryConnector {
* Implementations typically match the task identifier based on repository specific patterns. For a Bugzilla task
* URL for example the implementation would match on <code>bugs.cgi</code> and return the repository specific
* portion of the URL: &quot;<i>http://bugs/</i><b>bugs.cgi?bugid=</b>123&quot;.
- *
+ *
* @return a task identifier or <code>null</code>, if <code>taskUrl</code> is not recognized
* @see #getTaskData(TaskRepository, String, IProgressMonitor)
*/
@@ -215,7 +215,7 @@ public abstract class AbstractRepositoryConnector {
* <p>
* The default implementations returns the substring of the text returned by {@link #getLabel()} up to the first
* occurrence of <em>(</em> or a space.
- *
+ *
* @since 2.3
*/
@Nullable
@@ -242,7 +242,7 @@ public abstract class AbstractRepositoryConnector {
* Returns the attachment handler. The method is expected to always return the same instance.
* <p>
* The default implementation returns <code>null</code>.
- *
+ *
* @return the attachment handler, or null, if attachments are not supported
* @since 3.0
*/
@@ -253,7 +253,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns the full task data. The method is expected to always return the same instance.
- *
+ *
* @param repository
* the task repository matching this connector
* @param taskIdOrKey
@@ -270,10 +270,43 @@ public abstract class AbstractRepositoryConnector {
@NonNull IProgressMonitor monitor) throws CoreException;
/**
+ * Specifies whether or not this connector supports
+ * {@link #searchByTaskKey(TaskRepository, String, IProgressMonitor) searching} the given repository by task key.
+ *
+ * @param repository
+ * @throws CoreException
+ * if the repository is invalid
+ * @since 3.19
+ */
+ public boolean supportsSearchByTaskKey(@NonNull TaskRepository repository) throws CoreException {
+ return false;
+ }
+
+ /**
+ * Searches the given repository for a task with the given task key. The returned <code>TaskData</code> may be
+ * partial.
+ * <p>
+ * This is an optional operation that is useful for connectors that cannot map from the
+ * {@link #getBrowserUrl(TaskRepository, IRepositoryElement) browser URL} to a task ID.
+ *
+ * @return the matching <code>TaskData</code> or <code>null</code> if no matching task was found.
+ * @throws CoreException
+ * if the search fails or the repository is invalid
+ * @throws UnsupportedOperationException
+ * if searching by task key is not {@link #supportsSearchByTaskKey(TaskRepository) supported}
+ * @since 3.19
+ */
+ @Nullable
+ public TaskData searchByTaskKey(@NonNull TaskRepository repository, @NonNull String taskKey,
+ @NonNull IProgressMonitor monitor) throws CoreException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Returns the task data handler. The method is expected to always return the same instance.
* <p>
* The default implementation returns <code>null</code>.
- *
+ *
* @return the task data handler, or null, task data submission is not supported
* @since 3.0
*/
@@ -289,7 +322,7 @@ public abstract class AbstractRepositoryConnector {
* <p>
* Implementations typically match the task identifier based on repository specific patterns such as
* &quot;http://bugs/<b>bugs.cgibugid=123</b>&quot;.
- *
+ *
* @return a task identifier or <code>null</code>, if <code>taskUrl</code> is not recognized
* @see #getTaskData(TaskRepository, String, IProgressMonitor)
* @since 2.0
@@ -310,7 +343,7 @@ public abstract class AbstractRepositoryConnector {
* tasks.
* <p>
* Implementations typically scan <code>comment</code> for repository specific patterns such as KEY-123 for JIRA.
- *
+ *
* @return null, if the method is not supported; an array of task identifiers otherwise
* @since 2.0
*/
@@ -322,7 +355,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns a mapping for {@link TaskData}. The mapping maps the connector specific representation to the standard
* schema defined in {@link ITaskMapping}.
- *
+ *
* @since 3.0
*/
@NonNull
@@ -336,7 +369,7 @@ public abstract class AbstractRepositoryConnector {
* For subtasks implementations are expected to return relations creates by {@link TaskRelation#subtask(String)}.
* <p>
* The default implementation returns <code>null</code>.
- *
+ *
* @return a list of relations or null if <code>taskData</code> does not have relations or if task relations are not
* supported
* @since 3.0
@@ -349,7 +382,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns a task URL for the task referenced by <code>taskIdOrKey</code> in the repository referenced by
* <code>repositoryUrl</code>.
- *
+ *
* @return a task URL or null if the connector does not support task URLs
* @see #getTaskIdFromTaskUrl(String)
* @see #getRepositoryUrlFromTaskUrl(String)
@@ -362,7 +395,7 @@ public abstract class AbstractRepositoryConnector {
* Returns a URL for <code>element</code> that contains authentication information such as a session ID.
* <p>
* Returns <code>null</code> by default. Clients may override.
- *
+ *
* @param repository
* the repository for <code>element</code>
* @param element
@@ -380,7 +413,7 @@ public abstract class AbstractRepositoryConnector {
* Returns a browsable URL for <code>element</code>.
* <p>
* Returns <code>null</code> by default. Clients may override.
- *
+ *
* @param repository
* the repository for <code>element</code>
* @param element
@@ -398,7 +431,7 @@ public abstract class AbstractRepositoryConnector {
* <code>task</code>.
* <p>
* See {@link AbstractRepositoryConnector} for more details how this method interacts with other methods.
- *
+ *
* @since 3.0
* @see #updateTaskFromTaskData(TaskRepository, ITask, TaskData)
*/
@@ -410,7 +443,7 @@ public abstract class AbstractRepositoryConnector {
* repository which is the common case and default.
* <p>
* The default implementation returns <code>false</code>.
- *
+ *
* @since 3.0
*/
public boolean hasLocalCompletionState(@NonNull TaskRepository repository, @NonNull ITask task) {
@@ -421,7 +454,7 @@ public abstract class AbstractRepositoryConnector {
* Returns <code>true</code>, if <code>task</code> has a due date that is managed on the repository.
* <p>
* The default implementation returns <code>false</code>.
- *
+ *
* @since 3.0
*/
public boolean hasRepositoryDueDate(@NonNull TaskRepository repository, @NonNull ITask task,
@@ -433,7 +466,7 @@ public abstract class AbstractRepositoryConnector {
* Returns <code>true</code> to indication that the repository configuration is stale and requires update
* <p>
* The default implementation returns <code>true</code> every 24 hours.
- *
+ *
* @return true to indicate that the repository configuration is stale and requires update
* @since 3.0
*/
@@ -450,7 +483,7 @@ public abstract class AbstractRepositoryConnector {
* Returns true, if users can manage create repositories for this connector.
* <p>
* The default implementation returns true.
- *
+ *
* @since 2.0
*/
public boolean isUserManaged() {
@@ -464,7 +497,7 @@ public abstract class AbstractRepositoryConnector {
* Implementors must complete executing <code>query</code> before returning from this method.
* <p>
* See {@link AbstractRepositoryConnector} for more details how this method interacts with other methods.
- *
+ *
* @param repository
* task repository to run query against
* @param query
@@ -487,20 +520,20 @@ public abstract class AbstractRepositoryConnector {
/**
* Delete the task from the server
- *
+ *
* @throws UnsupportedOperationException
* if this is not implemented by the connector
* @since 3.3
*/
@NonNull
- public IStatus deleteTask(@NonNull TaskRepository repository, @NonNull ITask task,
- @NonNull IProgressMonitor monitor) throws CoreException {
+ public IStatus deleteTask(@NonNull TaskRepository repository, @NonNull ITask task, @NonNull IProgressMonitor monitor)
+ throws CoreException {
throw new UnsupportedOperationException();
}
/**
* Hook into the synchronization process.
- *
+ *
* @since 3.0
*/
public void postSynchronization(@NonNull ISynchronizationSession event, @NonNull IProgressMonitor monitor)
@@ -516,7 +549,7 @@ public abstract class AbstractRepositoryConnector {
* Hook into the synchronization process.
* <p>
* See {@link AbstractRepositoryConnector} for more details how this method interacts with other methods.
- *
+ *
* @since 3.0
*/
public void preSynchronization(@NonNull ISynchronizationSession event, @NonNull IProgressMonitor monitor)
@@ -532,7 +565,7 @@ public abstract class AbstractRepositoryConnector {
* Updates the local repository configuration cache (e.g. products and components). Connectors are encouraged to
* implement {@link #updateRepositoryConfiguration(TaskRepository, ITask, IProgressMonitor)} in addition this
* method.
- *
+ *
* @param repository
* the repository to update configuration for
* @since 3.0
@@ -544,7 +577,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Updates the local repository configuration cache (e.g. products and components). The default implementation
* invokes {@link #updateRepositoryConfiguration(TaskRepository, IProgressMonitor)}.
- *
+ *
* @param repository
* the repository to update configuration for
* @param task
@@ -562,7 +595,7 @@ public abstract class AbstractRepositoryConnector {
* used to map common attributes.
* <p>
* See {@link AbstractRepositoryConnector} for more details how this method interacts with other methods.
- *
+ *
* @see #hasTaskChanged(TaskRepository, ITask, TaskData)
* @see TaskMapper#applyTo(ITask)
* @since 3.0
@@ -574,7 +607,7 @@ public abstract class AbstractRepositoryConnector {
* Called when a new task is created, before it is opened in a task editor. Connectors should override this method
* if they need information from the {@link TaskData} to determine kind labels or other information that should be
* displayed in a new task editor.
- *
+ *
* @since 3.5
*/
public void updateNewTaskFromTaskData(@NonNull TaskRepository taskRepository, @NonNull ITask task,
@@ -586,7 +619,7 @@ public abstract class AbstractRepositoryConnector {
* is submitted to the repository. Implementers may override to implement custom migration rules.
* <p>
* Does nothing by default.
- *
+ *
* @param event
* provides additional details
* @since 3.4
@@ -596,7 +629,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Returns if the user using the repository is the owner of the task. Subclasses may override.
- *
+ *
* @param repository
* repository task is associated with
* @param task
@@ -611,7 +644,7 @@ public abstract class AbstractRepositoryConnector {
/**
* Retrieves the history for <code>task</code>. Throws {@link UnsupportedOperationException} by default.
- *
+ *
* @param repository
* the repository
* @param task
@@ -635,7 +668,7 @@ public abstract class AbstractRepositoryConnector {
* requires connecting to the repository.
* <p>
* Throws {@link UnsupportedOperationException} if not implemented by clients.
- *
+ *
* @param repository
* the repository
* @param monitor
@@ -654,7 +687,7 @@ public abstract class AbstractRepositoryConnector {
* Set the category of the {@code repository} to the default TaskRepository.CATEGORY_BUGS.
* <p>
* Subclasses may override.
- *
+ *
* @param repository
* the repository
* @since 3.11
diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJobTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJobTest.java
new file mode 100644
index 000000000..f06c9c476
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJobTest.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.ui;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.junit.Test;
+
+public class OpenRepositoryTaskJobTest {
+
+ @Test
+ public void setsNameFromTaskId() {
+ assertEquals("Opening repository task 123", new OpenRepositoryTaskJob("kind", "http://mock", "123",
+ "http://mock/123", null).getName());
+ }
+
+ @Test
+ public void setsNameFromTaskKey() {
+ assertEquals("Opening repository task 123", new OpenRepositoryTaskJob(
+ new TaskRepository("kind", "http://mock"), "123", "http://mock/123", null).getName());
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJob.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJob.java
index baffbe8a6..a7ae7f4e9 100644
--- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJob.java
+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/OpenRepositoryTaskJob.java
@@ -55,11 +55,36 @@ public class OpenRepositoryTaskJob extends Job {
private final long timestamp;
+ private String taskKey;
+
+ private TaskRepository repository;
+
+ /**
+ * Creates a job that searches for a task with the given task <i>key</i> and opens it if found.
+ */
+ public OpenRepositoryTaskJob(TaskRepository repository, String taskKey, String taskUrl, IWorkbenchPage page) {
+ super(MessageFormat.format(Messages.OpenRepositoryTaskJob_Opening_repository_task_X, taskKey));
+ this.repositoryKind = repository.getConnectorKind();
+ this.taskId = null;
+ this.repositoryUrl = repository.getRepositoryUrl();
+ this.taskUrl = taskUrl;
+ this.timestamp = 0;
+ this.repository = repository;
+ this.taskKey = taskKey;
+ }
+
+ /**
+ * Creates a job that fetches a task with the given task id and opens it.
+ */
public OpenRepositoryTaskJob(String repositoryKind, String repositoryUrl, String taskId, String taskUrl,
IWorkbenchPage page) {
this(repositoryKind, repositoryUrl, taskId, taskUrl, 0, page);
}
+ /**
+ * Creates a job that fetches a task with the given task id and opens it, expanding all comments made after the
+ * given timestamp.
+ */
public OpenRepositoryTaskJob(String repositoryKind, String repositoryUrl, String taskId, String taskUrl,
long timestamp, IWorkbenchPage page) {
super(MessageFormat.format(Messages.OpenRepositoryTaskJob_Opening_repository_task_X, taskId));
@@ -87,7 +112,9 @@ public class OpenRepositoryTaskJob extends Job {
@Override
public IStatus run(IProgressMonitor monitor) {
monitor.beginTask(Messages.OpenRepositoryTaskJob_Opening_Remote_Task, 10);
- final TaskRepository repository = TasksUi.getRepositoryManager().getRepository(repositoryKind, repositoryUrl);
+ if (repository == null) {
+ repository = TasksUi.getRepositoryManager().getRepository(repositoryKind, repositoryUrl);
+ }
if (repository == null) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
@@ -109,7 +136,7 @@ public class OpenRepositoryTaskJob extends Job {
AbstractRepositoryConnector connector = TasksUi.getRepositoryManager().getRepositoryConnector(repositoryKind);
try {
- final TaskData taskData = connector.getTaskData(repository, taskId, monitor);
+ final TaskData taskData = getTaskData(connector, monitor);
if (taskData != null) {
task = TasksUi.getRepositoryModel().createTask(repository, taskData.getTaskId());
TasksUiPlugin.getTaskDataManager().putUpdatedTaskData(task, taskData, true);
@@ -161,4 +188,18 @@ public class OpenRepositoryTaskJob extends Job {
return Status.OK_STATUS;
}
+ TaskData getTaskData(AbstractRepositoryConnector connector, IProgressMonitor monitor) throws CoreException {
+ if (taskId != null) {
+ return connector.getTaskData(repository, taskId, monitor);
+ } else if (taskKey != null && connector.supportsSearchByTaskKey(repository)) {
+ TaskData searchTaskData = connector.searchByTaskKey(repository, taskKey, monitor);
+ if (searchTaskData.isPartial()) {
+ return connector.getTaskData(repository, searchTaskData.getTaskId(), monitor);
+ } else {
+ return searchTaskData;
+ }
+ }
+ return null;
+ }
+
}

Back to the top