446091: make task list assigned to me filter work for Gerrit

Change-Id: I7c5431cb46c493c6d189310e91a6f83e91139161
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=446091
diff --git a/org.eclipse.mylyn.gerrit.core.tests/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandlerTest.java b/org.eclipse.mylyn.gerrit.core.tests/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandlerTest.java
index 13a2d3e..f341e0a 100644
--- a/org.eclipse.mylyn.gerrit.core.tests/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandlerTest.java
+++ b/org.eclipse.mylyn.gerrit.core.tests/src/org/eclipse/mylyn/internal/gerrit/core/GerritTaskDataHandlerTest.java
@@ -14,10 +14,31 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import java.sql.Timestamp;
+import java.util.Collections;
+
+import org.eclipse.mylyn.internal.gerrit.core.client.GerritChange;
+import org.eclipse.mylyn.internal.gerrit.core.client.GerritConfiguration;
+import org.eclipse.mylyn.internal.gerrit.core.client.compat.GerritConfigX;
+import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritPerson;
+import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritQueryResult;
 import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
 import org.eclipse.mylyn.tasks.core.data.TaskData;
 import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.google.gerrit.common.data.AccountInfo;
+import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.Account.Id;
+import com.google.gerrit.reviewdb.Branch.NameKey;
+import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Change.Key;
+import com.google.gerrit.reviewdb.Project;
 
 /**
  * @author Steffen Pingel
@@ -43,4 +64,75 @@
 				.getAttribute(GerritTaskSchema.getDefault().UPLOADED.getKey()));
 	}
 
+	@Test
+	public void testUpdatePartialTaskData() {
+		GerritConnector connector = mock(GerritConnector.class, Mockito.RETURNS_DEEP_STUBS);
+		GerritConfiguration config = createMockConfig();
+		when(connector.getConfiguration(any(TaskRepository.class))).thenReturn(config);
+		GerritTaskDataHandler handler = new GerritTaskDataHandler(connector);
+		TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://repository"); //$NON-NLS-1$
+		TaskData data = handler.createTaskData(repository, "1", null); //$NON-NLS-1$
+		handler.updatePartialTaskData(repository, data, createMockQueryResult("Joel K. User"));
+		assertAssignee(data, "joel.user@mylyn.org", "Joel K. User");
+
+		handler.updatePartialTaskData(repository, data, createMockQueryResult("Jacob F. User"));
+		assertAssignee(data, "Jacob F. User", "Jacob F. User");
+
+		handler.updatePartialTaskData(repository, data, createMockQueryResult(null));
+		assertAssignee(data, "Anonymous", "Anonymous");
+	}
+
+	@Test
+	public void testUpdateTaskData() {
+		GerritTaskDataHandler handler = new GerritTaskDataHandler(new GerritConnector());
+		TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "http://repository"); //$NON-NLS-1$
+		TaskData data = handler.createTaskData(repository, "1", null); //$NON-NLS-1$
+		handler.updateTaskData(repository, data, createMockGerritChange(), false, null);
+		assertAssignee(data, "joel.user@mylyn.org", "Joel K. User");
+	}
+
+	private void assertAssignee(TaskData data, String id, String name) {
+		TaskAttribute assigneeAttribute = data.getRoot().getAttribute(TaskAttribute.USER_ASSIGNED);
+		assertEquals(id, assigneeAttribute.getValue());
+		assertEquals(name, data.getAttributeMapper().getValueLabel(assigneeAttribute));
+	}
+
+	private GerritConfiguration createMockConfig() {
+		Account account = new Account(new Id(1));
+		account.setFullName("Joel K. User");
+		account.setPreferredEmail("joel.user@mylyn.org");
+		GerritConfiguration value = new GerritConfiguration(new GerritConfigX(), Collections.<Project> emptyList(),
+				account);
+		return value;
+	}
+
+	private GerritQueryResult createMockQueryResult(String userName) {
+		GerritQueryResult queryResult = mock(GerritQueryResult.class, Mockito.RETURNS_SMART_NULLS);
+		when(queryResult.getReviewLabel()).thenReturn(null);
+		when(queryResult.getUpdated()).thenReturn(new Timestamp(1));
+		if (userName == null) {
+			when(queryResult.getOwner()).thenReturn(null);
+		} else {
+			GerritPerson person = mock(GerritPerson.class);
+			when(person.getName()).thenReturn(userName);
+			when(queryResult.getOwner()).thenReturn(person);
+		}
+		return queryResult;
+	}
+
+	private GerritChange createMockGerritChange() {
+		AccountInfo accountInfo = mock(AccountInfo.class);
+		when(accountInfo.getFullName()).thenReturn("Joel K. User");
+		when(accountInfo.getPreferredEmail()).thenReturn("joel.user@mylyn.org");
+		GerritChange change = mock(GerritChange.class, Mockito.RETURNS_DEEP_STUBS);
+		when(change.getChangeDetail().getAccounts().get(any(Id.class))).thenReturn(accountInfo);
+		when(change.getChangeDetail().getChange()).thenReturn(mockChange());
+		return change;
+	}
+
+	private Change mockChange() {
+		return new Change(new Key("1"), new Change.Id(1), new Id(1), new NameKey(new Project.NameKey("parent"),
+				"branch"));
+	}
+
 }
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 debc4e9..b6f10cb 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
@@ -275,7 +275,7 @@
 				for (GerritQueryResult changeInfo : result) {
 					TaskData taskData = taskDataHandler.createPartialTaskData(repository,
 							Integer.toString(changeInfo.getNumber()), monitor);
-					taskDataHandler.updateTaskData(repository, taskData, changeInfo);
+					taskDataHandler.updatePartialTaskData(repository, taskData, changeInfo);
 					if (monitor.isCanceled()) {
 						break;
 					}
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 0e286c3..b7f0e7c 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
@@ -22,6 +22,7 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.mylyn.internal.gerrit.core.client.GerritChange;
 import org.eclipse.mylyn.internal.gerrit.core.client.GerritClient;
+import org.eclipse.mylyn.internal.gerrit.core.client.GerritConfiguration;
 import org.eclipse.mylyn.internal.gerrit.core.client.GerritException;
 import org.eclipse.mylyn.internal.gerrit.core.client.compat.ChangeDetailX;
 import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritPerson;
@@ -221,9 +222,14 @@
 		Change change = changeDetail.getChange();
 		AccountInfo owner = changeDetail.getAccounts().get(change.getOwner());
 
-		updateTaskData(repository, data, new GerritQueryResult(new ChangeInfo(change)));
+		updatePartialTaskData(repository, data, new GerritQueryResult(new ChangeInfo(change)));
 		setAttributeValue(data, schema.BRANCH, change.getDest().get());
-		setAttributeValue(data, schema.OWNER, GerritUtil.getUserLabel(owner));
+		String userId = GerritUtil.getUserId(owner);
+		String userLabel = GerritUtil.getUserLabel(owner);
+		TaskAttribute ownerAttribute = setAttributeValue(data, schema.OWNER, userId);
+		if (ownerAttribute != null) {
+			ownerAttribute.putOption(userId, userLabel);
+		}
 		setAttributeValue(data, schema.UPLOADED, dateToString(((ChangeDetailX) changeDetail).getDateCreated()));
 		setAttributeValue(data, schema.UPDATED, dateToString(((ChangeDetailX) changeDetail).getLastModified()));
 		setAttributeValue(data, schema.DESCRIPTION, changeDetail.getDescription());
@@ -299,27 +305,39 @@
 		}
 	}
 
-	public void updateTaskData(TaskRepository repository, TaskData data, GerritQueryResult changeInfo) {
+	public void updatePartialTaskData(TaskRepository repository, TaskData data, GerritQueryResult queryResult) {
 		GerritQueryResultSchema schema = GerritQueryResultSchema.getDefault();
-		setAttributeValue(data, schema.KEY, shortenChangeId(changeInfo.getId()));
-		setAttributeValue(data, schema.PROJECT, changeInfo.getProject());
-		setAttributeValue(data, schema.SUMMARY, changeInfo.getSubject());
-		setAttributeValue(data, schema.STATUS, changeInfo.getStatus());
+		setAttributeValue(data, schema.KEY, shortenChangeId(queryResult.getId()));
+		setAttributeValue(data, schema.PROJECT, queryResult.getProject());
+		setAttributeValue(data, schema.SUMMARY, queryResult.getSubject());
+		setAttributeValue(data, schema.STATUS, queryResult.getStatus());
 		setAttributeValue(data, schema.URL, connector.getTaskUrl(repository.getUrl(), data.getTaskId()));
-		setAttributeValue(data, schema.UPDATED, dateToString(changeInfo.getUpdated()));
-		setAttributeValue(data, schema.CHANGE_ID, changeInfo.getId());
-		if (GerritConnector.isClosed(changeInfo.getStatus())) {
-			setAttributeValue(data, schema.COMPLETED, dateToString(changeInfo.getUpdated()));
+		setAttributeValue(data, schema.UPDATED, dateToString(queryResult.getUpdated()));
+		setAttributeValue(data, schema.CHANGE_ID, queryResult.getId());
+		if (GerritConnector.isClosed(queryResult.getStatus())) {
+			setAttributeValue(data, schema.COMPLETED, dateToString(queryResult.getUpdated()));
 		}
 
-		// Add fields for the Gerrit Dashboard viewer entries
-		GerritPerson owner = changeInfo.getOwner();
-		setAttributeValue(data, schema.OWNER, (owner != null) ? owner.getName() : ANONYMOUS);
-		setAttributeValue(data, schema.BRANCH, changeInfo.getBranch());
-		setAttributeValue(data, schema.IS_STARRED, (changeInfo.isStarred() ? Boolean.TRUE : Boolean.FALSE).toString());
-		setAttributeValue(data, schema.TOPIC, changeInfo.getTopic());
+		GerritPerson owner = queryResult.getOwner();
+		if (owner != null) {
+			String fullName = getFullNameFromAccount(repository);
+			if (fullName != null && fullName.equals(owner.getName())) {
+				// populate ITask.ownerId so that My Tasks filter works 
+				String preferredEmail = getPreferredEmailFromAccount(repository);
+				TaskAttribute ownerAttribute = setAttributeValue(data, schema.OWNER, preferredEmail);
+				ownerAttribute.putOption(preferredEmail, fullName);
+			} else {
+				// we don't have the owner id and it could be expensive to include it in the query results
+				setAttributeValue(data, schema.OWNER, owner.getName());
+			}
+		} else {
+			setAttributeValue(data, schema.OWNER, ANONYMOUS);
+		}
+		setAttributeValue(data, schema.BRANCH, queryResult.getBranch());
+		setAttributeValue(data, schema.IS_STARRED, (queryResult.isStarred() ? Boolean.TRUE : Boolean.FALSE).toString());
+		setAttributeValue(data, schema.TOPIC, queryResult.getTopic());
 
-		GerritReviewLabel reviewLabel = changeInfo.getReviewLabel();
+		GerritReviewLabel reviewLabel = queryResult.getReviewLabel();
 		if (reviewLabel != null) {
 			if (reviewLabel.getVerifyStatus() != null) {
 				setAttributeValue(data, schema.VERIFY_STATE, reviewLabel.getVerifyStatus().getStatus());
@@ -330,6 +348,22 @@
 		}
 	}
 
+	private String getFullNameFromAccount(TaskRepository repository) {
+		GerritConfiguration config = connector.getConfiguration(repository);
+		if (config != null && config.getAccount() != null) {
+			return config.getAccount().getFullName();
+		}
+		return null;
+	}
+
+	private String getPreferredEmailFromAccount(TaskRepository repository) {
+		GerritConfiguration config = connector.getConfiguration(repository);
+		if (config != null && config.getAccount() != null) {
+			return config.getAccount().getPreferredEmail();
+		}
+		return null;
+	}
+
 	private String shortenChangeId(String changeId) {
 		changeId = GerritUtil.toChangeId(changeId);
 		return changeId.substring(0, Math.min(9, changeId.length()));
diff --git a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritUtil.java b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritUtil.java
index c351ac2..10ebd9f 100644
--- a/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritUtil.java
+++ b/org.eclipse.mylyn.gerrit.core/src/org/eclipse/mylyn/internal/gerrit/core/GerritUtil.java
@@ -37,6 +37,16 @@
  */
 public class GerritUtil {
 
+	public static String getUserId(AccountInfo user) {
+		if (user == null) {
+			return Messages.GerritUtil_Anonymous;
+		}
+		if (user.getPreferredEmail() != null) {
+			return user.getPreferredEmail();
+		}
+		return Messages.GerritUtil_Unknown;
+	}
+
 	public static String getUserLabel(AccountInfo user) {
 		if (user == null) {
 			return Messages.GerritUtil_Anonymous;
diff --git a/org.eclipse.mylyn.gerrit.dashboard.core/src/org/eclipse/mylyn/gerrit/dashboard/core/GerritTask.java b/org.eclipse.mylyn.gerrit.dashboard.core/src/org/eclipse/mylyn/gerrit/dashboard/core/GerritTask.java
index a8ea71c..b17661e 100644
--- a/org.eclipse.mylyn.gerrit.dashboard.core/src/org/eclipse/mylyn/gerrit/dashboard/core/GerritTask.java
+++ b/org.eclipse.mylyn.gerrit.dashboard.core/src/org/eclipse/mylyn/gerrit/dashboard/core/GerritTask.java
@@ -152,7 +152,7 @@
 		setAttribute(SUBJECT, getValue(attributes.get(SUBJECT)));
 		setAttribute(STATUS, getValue(attributes.get(STATUS)));
 
-		setAttribute(OWNER, getValue(attributes.get(OWNER)));
+		setAttribute(OWNER, taskData.getAttributeMapper().getValueLabel(attributes.get(OWNER)));
 		setAttribute(PROJECT, getValue(attributes.get(PROJECT)));
 		setAttribute(BRANCH, getValue(attributes.get(BRANCH)));
 		setAttribute(TOPIC, getValue(attributes.get(TOPIC)));
@@ -286,10 +286,10 @@
 		buffer.append(Messages.GerritTask_project).append(getAttribute(GerritTask.PROJECT)).append('\n');
 		buffer.append(Messages.GerritTask_branch).append(getAttribute(GerritTask.BRANCH)).append('\n');
 		buffer.append(Messages.GerritTask_topic).append(getAttribute(GerritTask.TOPIC)).append('\n');
-		buffer.append(Messages.GerritTask_updated).append(getAttributeAsDate(GerritTask.DATE_MODIFICATION)).append('\n');
-		buffer.append(Messages.GerritTask_star)
-				.append(getAttribute(GerritTask.IS_STARRED))
-				.append(", CRVW = ") //$NON-NLS-1$
+		buffer.append(Messages.GerritTask_updated)
+				.append(getAttributeAsDate(GerritTask.DATE_MODIFICATION))
+				.append('\n');
+		buffer.append(Messages.GerritTask_star).append(getAttribute(GerritTask.IS_STARRED)).append(", CRVW = ") //$NON-NLS-1$
 				.append(getAttribute(GerritTask.REVIEW_STATE))
 				.append(", VRIF = ") //$NON-NLS-1$
 				.append(getAttribute(GerritTask.VERIFY_STATE))
diff --git a/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPageTest.java b/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPageTest.java
index 5e66a51..64aa92a 100644
--- a/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPageTest.java
+++ b/org.eclipse.mylyn.gerrit.ui.tests/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPageTest.java
@@ -27,6 +27,7 @@
 import org.eclipse.mylyn.internal.gerrit.core.GerritQueryResultSchema;
 import org.eclipse.mylyn.internal.gerrit.ui.editor.GerritTaskEditorPage.GerritAttributePart;
 import org.eclipse.mylyn.internal.tasks.core.TaskTask;
+import org.eclipse.mylyn.internal.tasks.ui.editors.PersonAttributeEditor;
 import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart;
 import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorNewCommentPart;
 import org.eclipse.mylyn.tasks.core.TaskRepository;
@@ -59,18 +60,20 @@
 		public TestGerritTaskEditorPage() {
 			super(mock(TaskEditor.class));
 			model = mock(TaskDataModel.class);
-			TaskAttributeMapper mapper = mock(TaskAttributeMapper.class);
-			TaskData taskData = new TaskData(mapper, GerritConnector.CONNECTOR_KIND, "mock", "mock");
+			TaskRepository repository = new TaskRepository(GerritConnector.CONNECTOR_KIND, "mock");
+			TaskData taskData = new TaskData(new TaskAttributeMapper(repository), GerritConnector.CONNECTOR_KIND,
+					"mock", "mock");
 			taskData.getRoot().createAttribute(GerritQueryResultSchema.getDefault().BRANCH.getKey());
 			taskData.getRoot().createAttribute(GerritQueryResultSchema.getDefault().PROJECT.getKey());
 			taskData.getRoot().createAttribute(GerritQueryResultSchema.getDefault().STATUS.getKey());
 			when(model.getTaskData()).thenReturn(taskData);
+			when(model.getTaskRepository()).thenReturn(repository);
 
 			IEditorSite editorSite = mock(IEditorSite.class);
 			IHandlerService service = mock(IHandlerService.class);
 			when(editorSite.getService(IHandlerService.class)).thenReturn(service);
-			TaskEditorInput taskEditorInput = new TaskEditorInput(new TaskRepository(GerritConnector.CONNECTOR_KIND,
-					"mock"), new TaskTask(GerritConnector.CONNECTOR_KIND, "mock", "mock"));
+			TaskEditorInput taskEditorInput = new TaskEditorInput(repository, new TaskTask(
+					GerritConnector.CONNECTOR_KIND, "mock", "mock"));
 			when(getTaskEditor().getTaskEditorInput()).thenReturn(taskEditorInput);
 			init(editorSite, taskEditorInput);
 		}
@@ -148,4 +151,24 @@
 			}
 		});
 	}
+
+	public void testCreatePersonAttribute() throws Exception {
+		TaskAttribute assigneeAttribute = page.getModel()
+				.getTaskData()
+				.getRoot()
+				.createAttribute(TaskAttribute.USER_ASSIGNED);
+		assigneeAttribute.getMetaData().setReadOnly(true);
+		PersonAttributeEditor editor = (PersonAttributeEditor) page.createAttributeEditorFactory().createEditor(
+				TaskAttribute.TYPE_PERSON, assigneeAttribute);
+		assertTrue(editor.isReadOnly());
+
+		assigneeAttribute.setValue("joel.user");
+		assertEquals("joel.user", editor.getValue());
+
+		assigneeAttribute.putOption("joel.user", "Joel K. User");
+		assertEquals("Joel K. User", editor.getValue());
+
+		editor.setReadOnly(false);
+		assertEquals("joel.user", editor.getValue());
+	}
 }
diff --git a/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPage.java b/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPage.java
index e73595a..41d25ab 100644
--- a/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPage.java
+++ b/org.eclipse.mylyn.gerrit.ui/src/org/eclipse/mylyn/internal/gerrit/ui/editor/GerritTaskEditorPage.java
@@ -18,6 +18,7 @@
 import org.eclipse.mylyn.internal.gerrit.core.GerritConnector;
 import org.eclipse.mylyn.internal.gerrit.core.GerritQueryResultSchema;
 import org.eclipse.mylyn.internal.gerrit.core.GerritTaskSchema;
+import org.eclipse.mylyn.internal.tasks.ui.editors.PersonAttributeEditor;
 import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttributePart;
 import org.eclipse.mylyn.reviews.ui.spi.editor.AbstractReviewTaskEditorPage;
 import org.eclipse.mylyn.reviews.ui.spi.editor.ReviewDetailSection;
@@ -77,6 +78,18 @@
 					AbstractAttributeEditor editor = super.createEditor(type, taskAttribute);
 					editor.setLayoutHint(new LayoutHint(RowSpan.SINGLE, ColumnSpan.MULTIPLE));
 					return editor;
+				} else if (TaskAttribute.TYPE_PERSON.equals(type)) {
+					return new PersonAttributeEditor(getModel(), taskAttribute) {
+						@Override
+						public String getValue() {
+							if (isReadOnly()) {
+								// "label <id>" format doesn't fit in attributes section so just return label
+								return getModel().getTaskData().getAttributeMapper().getValueLabel(getTaskAttribute());
+							} else {
+								return getTaskAttribute().getValue();
+							}
+						}
+					};
 				}
 				return super.createEditor(type, taskAttribute);
 			}