diff options
author | Blaine Lewis | 2015-09-19 00:31:28 +0000 |
---|---|---|
committer | Sam Davis | 2015-12-10 18:03:20 +0000 |
commit | 03a47c7ebc66e39a2526e453b541b7f5daba5790 (patch) | |
tree | e0abc5e117cd980f22b1dc05c7d991edf0b99d74 | |
parent | 625b620692d84e60d6645dcc2a1c2efb709cec66 (diff) | |
download | org.eclipse.mylyn.reviews-03a47c7ebc66e39a2526e453b541b7f5daba5790.tar.gz org.eclipse.mylyn.reviews-03a47c7ebc66e39a2526e453b541b7f5daba5790.tar.xz org.eclipse.mylyn.reviews-03a47c7ebc66e39a2526e453b541b7f5daba5790.zip |
477635: Implemented functionality to capture a mapping between tasks and
any related reviews using the task-id in the summary of a field.
Change-Id: If76a2db1304c5f4925981227ee80b602a370097c
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=477635
Signed-off-by: Ratstache <landonbutterworth@gmail.com>
Signed-off-by: Blaine Lewis <Blaine1@ualberta.ca>
8 files changed, 467 insertions, 11 deletions
diff --git a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritConnector.java b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritConnector.java index 38074ec24..dcd264093 100644 --- a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritConnector.java +++ b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritConnector.java @@ -50,6 +50,7 @@ import org.eclipse.mylyn.internal.gerrit.core.client.JSonSupport; import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritQueryResult; import org.eclipse.mylyn.reviews.core.model.ReviewStatus; import org.eclipse.mylyn.reviews.core.spi.ReviewsConnector; +import org.eclipse.mylyn.reviews.internal.core.ReviewsCoreConstants; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITaskMapping; @@ -68,7 +69,7 @@ import com.google.gwtorm.server.StandardKeyEncoder; /** * The Gerrit connector core. - * + * * @author Mikael Kober * @author Thomas Westling * @author Sascha Scholz @@ -301,7 +302,8 @@ public class GerritConnector extends ReviewsConnector { } @Override - public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor) throws CoreException { + public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor) + throws CoreException { try { getClient(repository).refreshConfig(monitor); } catch (GerritException e) { @@ -309,6 +311,7 @@ public class GerritConnector extends ReviewsConnector { } } + @SuppressWarnings("restriction") @Override public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) { Date oldModificationDate = task.getModificationDate(); @@ -325,6 +328,11 @@ public class GerritConnector extends ReviewsConnector { if (taskData.isPartial()) { task.setModificationDate(oldModificationDate); } + + task.setAttribute(ReviewsCoreConstants.CODE_REVIEW, + taskData.getRoot().getAttribute(GerritTaskSchema.getDefault().REVIEW_STATE.getKey()).getValue()); + task.setAttribute(ReviewsCoreConstants.VERIFIED, + taskData.getRoot().getAttribute(GerritTaskSchema.getDefault().VERIFY_STATE.getKey()).getValue()); } public GerritSystemInfo validate(TaskRepository repository, IProgressMonitor monitor) throws CoreException { @@ -437,8 +445,8 @@ public class GerritConnector extends ReviewsConnector { JSonSupport support = new JSonSupport(); return support.toJson(config); } catch (Exception e) { - StatusHandler.log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, - "Failed to serialize configuration", e)); //$NON-NLS-1$ + StatusHandler + .log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, "Failed to serialize configuration", e)); //$NON-NLS-1$ return null; } } @@ -474,7 +482,8 @@ public class GerritConnector extends ReviewsConnector { return toStatus(repository, qualifier, (Exception) cause); } } else if (e instanceof GerritException && e.getMessage() != null) { - return createErrorStatus(repository, NLS.bind("{0}Gerrit connection issue: {1}", qualifier, e.getMessage())); //$NON-NLS-1$ + return createErrorStatus(repository, + NLS.bind("{0}Gerrit connection issue: {1}", qualifier, e.getMessage())); //$NON-NLS-1$ } String message = NLS.bind("{0}Unexpected error while connecting to Gerrit: {1}", qualifier, e.getMessage()); //$NON-NLS-1$ if (repository != null) { diff --git a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandler.java b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandler.java index 1323cbd1a..f2d25bb5c 100644 --- a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandler.java +++ b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandler.java @@ -151,6 +151,7 @@ public class GerritTaskDataHandler extends AbstractTaskDataHandler { if (!monitor.isCanceled()) { updateTaskData(repository, taskData, gerritChange, !anonymous, id); } + return taskData; } catch (GerritException e) { throw connector.toCoreException(repository, NLS.bind("Problem retrieving task data for task: {0}", taskId), //$NON-NLS-1$ @@ -162,11 +163,11 @@ public class GerritTaskDataHandler extends AbstractTaskDataHandler { private RemoteEmfConsumer<IRepository, IReview, String, GerritChange, String, Date> updateModelData( TaskRepository repository, TaskData taskData, ReviewObserver reviewObserver, IProgressMonitor monitor) - throws CoreException { + throws CoreException { GerritClient client = connector.getClient(repository); GerritRemoteFactoryProvider factoryProvider = (GerritRemoteFactoryProvider) client.getFactoryProvider(); - RemoteEmfConsumer<IRepository, IReview, String, GerritChange, String, Date> consumer = factoryProvider.getReviewFactory() - .getConsumerForLocalKey(factoryProvider.getRoot(), taskData.getTaskId()); + RemoteEmfConsumer<IRepository, IReview, String, GerritChange, String, Date> consumer = factoryProvider + .getReviewFactory().getConsumerForLocalKey(factoryProvider.getRoot(), taskData.getTaskId()); consumer.addObserver(reviewObserver); if (!consumer.isRetrieving()) { @@ -212,7 +213,7 @@ public class GerritTaskDataHandler extends AbstractTaskDataHandler { /** * Get account id for repository - * + * * @param client * @param repository * @param monitor diff --git a/org.eclipse.mylyn.reviews.core.tests/META-INF/MANIFEST.MF b/org.eclipse.mylyn.reviews.core.tests/META-INF/MANIFEST.MF index fbf85ebf5..3cee7e52c 100644 --- a/org.eclipse.mylyn.reviews.core.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.reviews.core.tests/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: org.junit;bundle-version="4.5.0", org.eclipse.mylyn.commons.net, org.apache.commons.logging, org.apache.commons.io, - org.eclipse.core.net + org.eclipse.core.net, + com.google.guava Export-Package: org.eclipse.mylyn.reviews.core.model;x-internal:=true, org.eclipse.mylyn.reviews.core.spi.remote;x-internal:=true, diff --git a/org.eclipse.mylyn.reviews.core.tests/src/org/eclipse/mylyn/reviews/core/internal/TaskReviewMappingStoreTest.java b/org.eclipse.mylyn.reviews.core.tests/src/org/eclipse/mylyn/reviews/core/internal/TaskReviewMappingStoreTest.java new file mode 100644 index 000000000..0bfecb08e --- /dev/null +++ b/org.eclipse.mylyn.reviews.core.tests/src/org/eclipse/mylyn/reviews/core/internal/TaskReviewMappingStoreTest.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2015 Blaine Lewis + * 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: + * Blaine Lewis + *******************************************************************************/ + +package org.eclipse.mylyn.reviews.core.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collection; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta; +import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta.Kind; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; +import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager; +import org.eclipse.mylyn.reviews.core.spi.ReviewsConnector; +import org.eclipse.mylyn.reviews.internal.core.TaskReviewsMappingsStore; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Matchers; + +import com.google.common.collect.ImmutableSet; + +@SuppressWarnings("restriction") +public class TaskReviewMappingStoreTest { + + final String taskUrl1 = "https://bugs.eclipse.org/bugs/show_bug.cgi?id=477635"; + + final String taskUrl2 = "https://bugs.eclipse.org/bugs/show_bug.cgi?id=345343"; + + final String notATaskUrl = "www.hello.com"; + + final ITask task1 = mock(ITask.class); + + final ITask task2 = mock(ITask.class); + + final String reviewUrl1 = "https://git.eclipse.org/r/#/c/56269/"; + + final String reviewUrl2 = "https://git.eclipse.org/r/#/c/43534/"; + + final String reviewUrlNoTask = "https://git.eclipse.org/r/#/c/12333/"; + + final String descriptionWithTaskUrl1 = "477635: [UCOSP] contribute reviews section to task editor showing" + + " associated reviews Change-Id: I3a38d375688aad7be36bfd58c3311d692eb51ed Task-Url: " + taskUrl1 + + " Signed-off-by: Blaine Lewis <Blaine1@ualberta.ca>"; + + final String descriptionWithTaskUrl2 = "477635: [UCOSP] contribute reviews section to task editor showing" + + " associated reviews Change-Id: I3a38d375688aad7be36bfd58c3311d692eb51ed Task-Url: " + taskUrl2 + + " Signed-off-by: Blaine Lewis <Blaine1@ualberta.ca>"; + + final String descriptionWithNoTaskUrl = "477635: [UCOSP] contribute reviews section to task editor showing" + + " associated reviews Change-Id: I3a38d375688aad7be36bfd58c3311d692eb51ed " + + " Signed-off-by: Blaine Lewis <Blaine1@ualberta.ca>"; + + final String descriptionWithNotATaskUrl = "477635: [UCOSP] contribute reviews section to task editor showing" + + " associated reviews Change-Id: I3a38d375688aad7be36bfd58c3311d692eb51ed " + notATaskUrl + + " Signed-off-by: Blaine Lewis <Blaine1@ualberta.ca>"; + + final ITask review1 = mock(ITask.class); + + final ITask review2 = mock(ITask.class); + + final ITask reviewNoTask = mock(ITask.class); + + private TaskDataManager taskDataManager; + + @Before + public void setup() { + + when(review1.getUrl()).thenReturn(reviewUrl1); + when(review2.getUrl()).thenReturn(reviewUrl2); + when(reviewNoTask.getUrl()).thenReturn(reviewUrlNoTask); + when(task1.getUrl()).thenReturn(taskUrl1); + when(task2.getUrl()).thenReturn(taskUrl2); + when(task1.getTaskId()).thenReturn("1"); + when(task1.getTaskId()).thenReturn("2"); + when(review1.getTaskId()).thenReturn("3"); + when(review2.getTaskId()).thenReturn("4"); + when(reviewNoTask.getTaskId()).thenReturn("5"); + + } + + public TaskReviewsMappingsStore getEmptyTaskReviewStore() { + TaskRepositoryManager repositoryManager = mock(TaskRepositoryManager.class); + ReviewsConnector connector = mock(ReviewsConnector.class); + + taskDataManager = mock(TaskDataManager.class); + + when(repositoryManager.getConnectorForRepositoryTaskUrl(Matchers.anyString())).thenReturn(connector); + when(repositoryManager.getRepositoryConnector(Matchers.anyString())).thenReturn(connector); + + TaskReviewsMappingsStore taskReviewsMappingStore = new TaskReviewsMappingsStore(taskDataManager, + repositoryManager); + return taskReviewsMappingStore; + } + + public void addReviewData(ITask review, String description) throws CoreException { + TaskData reviewData = new TaskData(new TaskAttributeMapper(new TaskRepository("", "")), "", review.getUrl(), + review.getTaskId()); + + reviewData.getRoot().createMappedAttribute(TaskAttribute.DESCRIPTION).setValue(description); + + when(taskDataManager.getTaskData(review)).thenReturn(reviewData); + } + + @Test + public void testAdd() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1).equals(taskUrl1)); + } + + @Test + public void testAddTwice() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + + Collection<String> reviewUrls = taskReviewsMappingStore.getReviewUrls(taskUrl1); + + assertTrue(reviewUrls.contains(reviewUrl1)); + assertTrue(reviewUrls.size() == 1); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1).equals(taskUrl1)); + } + + @Test + public void testAddMultiple() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + addReviewData(review2, descriptionWithTaskUrl2); + + TaskContainerDelta delta1 = new TaskContainerDelta(review1, Kind.ADDED); + TaskContainerDelta delta2 = new TaskContainerDelta(review2, Kind.ADDED); + + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta1, delta2)); + + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1).equals(taskUrl1)); + + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl2).contains(reviewUrl2)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl2).equals(taskUrl2)); + } + + @Test + public void testRemove() throws CoreException { + + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + + delta = new TaskContainerDelta(review1, Kind.DELETED); + + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertFalse(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1) == null); + } + + @Test + public void testUpdate() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + + addReviewData(review1, descriptionWithTaskUrl2); + + delta = new TaskContainerDelta(review1, Kind.CONTENT); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertFalse(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl2).contains(reviewUrl1)); + + } + + @Test + public void testUpdateNoTask() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithTaskUrl1); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertTrue(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + + addReviewData(review1, descriptionWithNoTaskUrl); + + delta = new TaskContainerDelta(review1, Kind.CONTENT); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertFalse(taskReviewsMappingStore.getReviewUrls(taskUrl1).contains(reviewUrl1)); + } + + @Test + public void testAddNoTask() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithNoTaskUrl); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1) == null); + } + + @Test + public void testAddANonTaskUrl() throws CoreException { + TaskReviewsMappingsStore taskReviewsMappingStore = getEmptyTaskReviewStore(); + addReviewData(review1, descriptionWithNotATaskUrl); + + TaskContainerDelta delta = new TaskContainerDelta(review1, Kind.ADDED); + taskReviewsMappingStore.containersChanged(ImmutableSet.of(delta)); + assertTrue(taskReviewsMappingStore.getTaskUrl(reviewUrl1) == null); + } + +} diff --git a/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/ReviewsCoreConstants.java b/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/ReviewsCoreConstants.java index f88a836c4..6f4466695 100644 --- a/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/ReviewsCoreConstants.java +++ b/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/ReviewsCoreConstants.java @@ -14,4 +14,8 @@ package org.eclipse.mylyn.reviews.internal.core; public interface ReviewsCoreConstants { public static final String PLUGIN_ID = "org.eclipse.mylyn.reviews.core"; //$NON-NLS-1$ + + public static final String CODE_REVIEW = "CODE_REVIEW"; //$NON-NLS-1$ + + public static final String VERIFIED = "VERIFIED"; //$NON-NLS-1$ } diff --git a/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/TaskReviewsMappingsStore.java b/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/TaskReviewsMappingsStore.java new file mode 100644 index 000000000..24d01be70 --- /dev/null +++ b/org.eclipse.mylyn.reviews.core/src/org/eclipse/mylyn/reviews/internal/core/TaskReviewsMappingsStore.java @@ -0,0 +1,176 @@ +package org.eclipse.mylyn.reviews.internal.core; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.internal.tasks.core.ITaskListChangeListener; +import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; +import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager; +import org.eclipse.mylyn.reviews.core.spi.ReviewsConnector; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.IRepositoryElement; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskData; + +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +/** + * This class is used by review connectors to provide a mapping from tasks to reviews. These mappings are used by + * TaskEditorReviewPart to give a table of the reviews pertaining to a task. The class is limited as it maps one task to + * many reviews. It is however possible (albeit strange) to have multiple tasks for one review. This is a limitation by + * design. + * + * @author Blaine Lewis + */ + +@SuppressWarnings("restriction") +public class TaskReviewsMappingsStore implements ITaskListChangeListener { + + private final SetMultimap<String, String> taskReviewsMap; + + private final TaskRepositoryManager repositoryManager; + + private final TaskDataManager taskDataManager; + + public TaskReviewsMappingsStore(TaskDataManager taskDataManager, TaskRepositoryManager repositoryManager) { + //BUG: This class is actually really volatile at the moment we have no + // collision rules for if we serialize and deserialize at the same time. + + this.repositoryManager = repositoryManager; + this.taskDataManager = taskDataManager; + taskReviewsMap = Multimaps.synchronizedSetMultimap(LinkedHashMultimap.<String, String> create()); + } + + /* + * Updates or adds a mapping given a reviewUrl and a taskDescription. If no URL is found in the description we do nothing. + */ + private void updateMapping(String reviewUrl, String reviewDescription) { + String oldTaskUrl = getTaskUrl(reviewUrl); + String newTaskUrl = this.extractTaskUrl(reviewDescription); + + if (newTaskUrl == null && oldTaskUrl != null) { + taskReviewsMap.remove(oldTaskUrl, reviewUrl); + } else if (newTaskUrl != null) { + if (oldTaskUrl != null && !oldTaskUrl.equals(newTaskUrl)) { + taskReviewsMap.remove(oldTaskUrl, reviewUrl); + } + if (newTaskUrl != null) { + taskReviewsMap.put(newTaskUrl, reviewUrl); + } + } + } + + public Collection<String> getReviewUrls(String taskUrl) { + return taskReviewsMap.get(taskUrl); + } + + /* + * This method of extracting URLs is deficient because if we have "(www.helloworld.com)" it will be + * a valid URL. This is difficult to format though so we won't handle that case. + */ + private String extractTaskUrl(String description) { + + for (String token : description.split("\\s+")) { //$NON-NLS-1$ + if (token.contains("://")) { //$NON-NLS-1$ + + try { + @SuppressWarnings("unused") + URL url = new URL(token); + + AbstractRepositoryConnector connector = repositoryManager.getConnectorForRepositoryTaskUrl(token); + + if (connector != null) { + return token; + } + } catch (MalformedURLException e) { + //Do nothing, this is expected behavior when there is no URL + } + } + } + + return null; + } + + public String getTaskUrl(String reviewUrlToFind) { + for (Entry<String, String> mapping : taskReviewsMap.entries()) { + int index = mapping.getValue().indexOf(reviewUrlToFind); + + if (index != -1) { + return mapping.getKey(); + } + } + + return null; + } + + @Override + public void containersChanged(Set<TaskContainerDelta> containers) { + + for (TaskContainerDelta delta : containers) { + IRepositoryElement reviewRepoElement = delta.getElement(); + + if (!(reviewRepoElement instanceof ITask)) { + return; + } + + ITask review = (ITask) reviewRepoElement; + + AbstractRepositoryConnector connector = repositoryManager.getRepositoryConnector(review.getConnectorKind()); + + if (review != null && connector instanceof ReviewsConnector) { + + try { + String reviewUrl = review.getUrl(); + + switch (delta.getKind()) { + case DELETED: + deleteMappingsTo(reviewUrl); + break; + case ADDED: + case CONTENT: + TaskData taskData = taskDataManager.getTaskData(review); + + if (taskData == null) { + continue; + } + + TaskAttribute attr = taskData.getRoot().getMappedAttribute(TaskAttribute.DESCRIPTION); + + if (attr == null) { + continue; + } + String reviewDescription = attr.getValue(); + + updateMapping(reviewUrl, reviewDescription); + break; + } + } catch (CoreException e) { + StatusHandler.log( + new Status(IStatus.ERROR, ReviewsCoreConstants.PLUGIN_ID, "Error getting taskData.", e)); //$NON-NLS-1$ + + } + } + } + } + + private void deleteMappingsTo(String reviewUrl) { + String taskUrl = getTaskUrl(reviewUrl); + if (taskUrl != null) { + Set<String> reviews = taskReviewsMap.get(taskUrl); + if (reviews != null) { + reviews.remove(reviewUrl); + } + } + } +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.reviews.ui/plugin.xml b/org.eclipse.mylyn.reviews.ui/plugin.xml index e1fb64e68..72b7828ce 100644 --- a/org.eclipse.mylyn.reviews.ui/plugin.xml +++ b/org.eclipse.mylyn.reviews.ui/plugin.xml @@ -147,7 +147,6 @@ visibleInUI="true"> </commonFilter> </extension> - <!-- <extension point="org.eclipse.ui.workbench.texteditor.rulerColumns"> <column id="org.eclipse.mylyn.reviews.ui.editor.AnnotationRuler" name="Review Comments" diff --git a/org.eclipse.mylyn.reviews.ui/src/org/eclipse/mylyn/internal/reviews/ui/ReviewsUiPlugin.java b/org.eclipse.mylyn.reviews.ui/src/org/eclipse/mylyn/internal/reviews/ui/ReviewsUiPlugin.java index 226a80d16..663854f57 100644 --- a/org.eclipse.mylyn.reviews.ui/src/org/eclipse/mylyn/internal/reviews/ui/ReviewsUiPlugin.java +++ b/org.eclipse.mylyn.reviews.ui/src/org/eclipse/mylyn/internal/reviews/ui/ReviewsUiPlugin.java @@ -10,12 +10,19 @@ *********************************************************************/ package org.eclipse.mylyn.internal.reviews.ui; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.reviews.internal.core.TaskReviewsMappingsStore; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.ui.progress.UIJob; import org.osgi.framework.BundleContext; /** * @author Steffen Pingel */ +@SuppressWarnings("restriction") public class ReviewsUiPlugin extends AbstractUIPlugin { public static final String PLUGIN_ID = "org.eclipse.mylyn.reviews.ui"; //$NON-NLS-1$ @@ -24,6 +31,10 @@ public class ReviewsUiPlugin extends AbstractUIPlugin { private ActiveReviewManager reviewManager; + private TaskReviewsMappingsStore taskReviewsMappingStore; + + private final String INITIALIZE_TASK_REVIEW_MAPPING_STORE_JOB = "initialize task review mapping store job"; //$NON-NLS-1$ + public ReviewsUiPlugin() { } @@ -32,6 +43,19 @@ public class ReviewsUiPlugin extends AbstractUIPlugin { super.start(context); plugin = this; reviewManager = new ActiveReviewManager(); + + //We need to schedule initialization otherwise TasksUiPlugin hasn't finished initialization. + UIJob job = new UIJob(INITIALIZE_TASK_REVIEW_MAPPING_STORE_JOB) { + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + taskReviewsMappingStore = new TaskReviewsMappingsStore(TasksUiPlugin.getTaskDataManager(), + TasksUiPlugin.getRepositoryManager()); + + TasksUiPlugin.getTaskList().addChangeListener(taskReviewsMappingStore); + return Status.OK_STATUS; + } + }; + job.schedule(); } @Override @@ -47,4 +71,8 @@ public class ReviewsUiPlugin extends AbstractUIPlugin { public ActiveReviewManager getReviewManager() { return reviewManager; } + + public TaskReviewsMappingsStore getTaskReviewsMappingStore() { + return taskReviewsMappingStore; + } } |