Merge "Split ChangeUpdate#setAssignee into set/remove"
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java
index 7b7de76..d1ec9e6 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java
@@ -42,6 +42,7 @@
 import org.eclipse.jgit.util.FS;
 
 import java.io.File;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -81,7 +82,8 @@
           testDesc.getAnnotation(GerritConfigs.class));
     }
 
-    private static boolean has(Class annotation, Class<?> clazz) {
+    private static boolean has(
+        Class<? extends Annotation> annotation, Class<?> clazz) {
       for (; clazz != null; clazz = clazz.getSuperclass()) {
         if (clazz.getAnnotation(annotation) != null) {
           return true;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index 43d4441..795ec6a 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -96,6 +96,10 @@
     return toChangeQuery(op("owner", fullname) + " " + status(status));
   }
 
+  public static String toAssigneeQuery(String fullname) {
+    return toChangeQuery(op("assignee", fullname));
+  }
+
   public static String toCustomDashboard(final String params) {
     return "/dashboard/?" + params;
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index 32e30d4..30f33f1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -32,6 +32,8 @@
   String branchTableDeleteButton();
   String branchTablePrevNextLinks();
   String cAPPROVAL();
+  String cASSIGNEE();
+  String cASSIGNEDTOME();
   String cLastUpdate();
   String cOWNER();
   String cSIZE();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
index 053e7e0c..eacff7b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
@@ -315,7 +315,7 @@
       CheckBox checkBox = new CheckBox();
       table.setWidget(row, 1, checkBox);
       checkBox.setEnabled(enabled);
-      table.setWidget(row, 2, new AccountLinkPanel(i));
+      table.setWidget(row, 2, AccountLinkPanel.create(i));
       table.setText(row, 3, i.email());
 
       final FlexCellFormatter fmt = table.getFlexCellFormatter();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 89421b6..1c3026c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -37,6 +37,7 @@
   String changeTableColumnSize();
   String changeTableColumnStatus();
   String changeTableColumnOwner();
+  String changeTableColumnAssignee();
   String changeTableColumnProject();
   String changeTableColumnBranch();
   String changeTableColumnLastUpdate();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 8dd307c..01921de 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -18,6 +18,7 @@
 changeTableColumnSize = Size
 changeTableColumnStatus = Status
 changeTableColumnOwner = Owner
+changeTableColumnAssignee = Assignee
 changeTableColumnProject = Project
 changeTableColumnBranch = Branch
 changeTableColumnLastUpdate = Updated
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 9c78955..b195b66 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -49,6 +49,7 @@
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 public class ChangeTable extends NavigationTable<ChangeInfo> {
@@ -63,11 +64,12 @@
   private static final int C_SUBJECT = 3;
   private static final int C_STATUS = 4;
   private static final int C_OWNER = 5;
-  private static final int C_PROJECT = 6;
-  private static final int C_BRANCH = 7;
-  private static final int C_LAST_UPDATE = 8;
-  private static final int C_SIZE = 9;
-  private static final int BASE_COLUMNS = 10;
+  private static final int C_ASSIGNEE = 6;
+  private static final int C_PROJECT = 7;
+  private static final int C_BRANCH = 8;
+  private static final int C_LAST_UPDATE = 9;
+  private static final int C_SIZE = 10;
+  private static final int BASE_COLUMNS = 11;
 
   private final List<Section> sections;
   private int columns;
@@ -90,6 +92,7 @@
     table.setText(0, C_SUBJECT, Util.C.changeTableColumnSubject());
     table.setText(0, C_STATUS, Util.C.changeTableColumnStatus());
     table.setText(0, C_OWNER, Util.C.changeTableColumnOwner());
+    table.setText(0, C_ASSIGNEE, Util.C.changeTableColumnAssignee());
     table.setText(0, C_PROJECT, Util.C.changeTableColumnProject());
     table.setText(0, C_BRANCH, Util.C.changeTableColumnBranch());
     table.setText(0, C_LAST_UPDATE, Util.C.changeTableColumnLastUpdate());
@@ -163,6 +166,7 @@
     fmt.addStyleName(row, C_SUBJECT, Gerrit.RESOURCES.css().cSUBJECT());
     fmt.addStyleName(row, C_STATUS, Gerrit.RESOURCES.css().cSTATUS());
     fmt.addStyleName(row, C_OWNER, Gerrit.RESOURCES.css().cOWNER());
+    fmt.addStyleName(row, C_ASSIGNEE, Gerrit.RESOURCES.css().cASSIGNEE());
     fmt.addStyleName(row, C_LAST_UPDATE, Gerrit.RESOURCES.css().cLastUpdate());
     fmt.addStyleName(row, C_SIZE, Gerrit.RESOURCES.css().cSIZE());
 
@@ -232,11 +236,24 @@
     }
 
     if (c.owner() != null) {
-      table.setWidget(row, C_OWNER, new AccountLinkPanel(c.owner(), status));
+      table.setWidget(row, C_OWNER,
+          AccountLinkPanel.withStatus(c.owner(), status));
     } else {
       table.setText(row, C_OWNER, "");
     }
 
+    if (c.assignee() != null) {
+      table.setWidget(row, C_ASSIGNEE,
+          AccountLinkPanel.forAssignee(c.assignee()));
+      if (Objects.equals(c.assignee().getId(),
+          Gerrit.getUserAccount().getId())) {
+        table.getRowFormatter().addStyleName(row,
+            Gerrit.RESOURCES.css().cASSIGNEDTOME());
+      }
+    } else {
+      table.setText(row, C_ASSIGNEE, "");
+    }
+
     table.setWidget(row, C_PROJECT, new ProjectLink(c.projectNameKey()));
     table.setWidget(row, C_BRANCH, new BranchLink(c.projectNameKey(), c
         .status(), c.branch(), c.topic()));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 4190672..4076296 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -449,6 +449,11 @@
   white-space: nowrap;
 }
 
+.changeTable .cASSIGNEDTOME {
+  background: #ffe9d6 !important;
+}
+
+.changeTable .cASSIGNEE,
 .changeTable .cOWNER,
 .changeTable .cSTATUS {
   white-space: nowrap;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
index eb3b1ff..dd9f369 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
@@ -22,30 +22,44 @@
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.user.client.ui.FlowPanel;
 
+import java.util.function.Function;
+
 /** Link to any user's account dashboard. */
 public class AccountLinkPanel extends FlowPanel {
-  public AccountLinkPanel(AccountInfo info) {
-    this(info, Change.Status.NEW);
+  public static AccountLinkPanel create(AccountInfo ai) {
+    return withStatus(ai, Change.Status.NEW);
   }
 
-  public AccountLinkPanel(AccountInfo info, Change.Status status) {
+  public static AccountLinkPanel withStatus(AccountInfo ai,
+      Change.Status status) {
+    return new AccountLinkPanel(
+        ai, name -> PageLinks.toAccountQuery(name, status));
+  }
+
+  public static AccountLinkPanel forAssignee(AccountInfo ai) {
+    return new AccountLinkPanel(ai, PageLinks::toAssigneeQuery);
+  }
+
+  private AccountLinkPanel(AccountInfo ai,
+      Function<String, String> nameToQuery) {
     addStyleName(Gerrit.RESOURCES.css().accountLinkPanel());
 
     InlineHyperlink l =
-        new InlineHyperlink(FormatUtil.name(info), PageLinks.toAccountQuery(
-            owner(info), status)) {
-      @Override
-      public void go() {
-        Gerrit.display(getTargetHistoryToken());
-      }
-    };
-    l.setTitle(FormatUtil.nameEmail(info));
+        new InlineHyperlink(
+            FormatUtil.name(ai),
+            nameToQuery.apply(name(ai))) {
+          @Override
+          public void go() {
+            Gerrit.display(getTargetHistoryToken());
+          }
+        };
+    l.setTitle(FormatUtil.nameEmail(ai));
 
-    add(new AvatarImage(info));
+    add(new AvatarImage(ai));
     add(l);
   }
 
-  public static String owner(AccountInfo ai) {
+  private static String name(AccountInfo ai) {
     if (ai.email() != null) {
       return ai.email();
     } else if (ai.name() != null) {