Merge change I574b992d

* changes:
  Adding support to list merged and abandoned changes for a project.
diff --git a/src/main/java/com/google/gerrit/client/Link.java b/src/main/java/com/google/gerrit/client/Link.java
index 4d333ea..d5fda50 100644
--- a/src/main/java/com/google/gerrit/client/Link.java
+++ b/src/main/java/com/google/gerrit/client/Link.java
@@ -28,6 +28,8 @@
 import com.google.gerrit.client.changes.AllAbandonedChangesScreen;
 import com.google.gerrit.client.changes.AllMergedChangesScreen;
 import com.google.gerrit.client.changes.AllOpenChangesScreen;
+import com.google.gerrit.client.changes.ByProjectAbandonedChangesScreen;
+import com.google.gerrit.client.changes.ByProjectMergedChangesScreen;
 import com.google.gerrit.client.changes.ByProjectOpenChangesScreen;
 import com.google.gerrit.client.changes.ChangeQueryResultsScreen;
 import com.google.gerrit.client.changes.ChangeScreen;
@@ -43,6 +45,7 @@
 import com.google.gerrit.client.reviewdb.Patch;
 import com.google.gerrit.client.reviewdb.PatchSet;
 import com.google.gerrit.client.reviewdb.Project;
+import com.google.gerrit.client.reviewdb.Change.Status;
 import com.google.gerrit.client.ui.Screen;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -108,8 +111,19 @@
     return "admin,project," + n.toString() + "," + tab;
   }
 
-  public static String toProjectOpen(final Project.NameKey proj) {
-    return "project,open," + proj.toString() + ",n,z";
+  public static String toProject(final Project.NameKey proj, Status status) {
+    switch (status) {
+      case ABANDONED:
+        return "project,abandoned," + proj.toString() + ",n,z";
+
+      case MERGED:
+        return "project,merged," + proj.toString() + ",n,z";
+
+      case NEW:
+      case SUBMITTED:
+      default:
+        return "project,open," + proj.toString() + ",n,z";
+    }
   }
 
   public static String toChangeQuery(final String query) {
@@ -195,6 +209,22 @@
         return new ByProjectOpenChangesScreen(Project.NameKey.parse(s
             .substring(0, c)), s.substring(c + 1));
       }
+
+      p = "project,merged,";
+      if (token.startsWith(p)) {
+        final String s = skip(p, token);
+        final int c = s.indexOf(',');
+        return new ByProjectMergedChangesScreen(Project.NameKey.parse(s
+            .substring(0, c)), s.substring(c + 1));
+      }
+
+      p = "project,abandoned,";
+      if (token.startsWith(p)) {
+        final String s = skip(p, token);
+        final int c = s.indexOf(',');
+        return new ByProjectAbandonedChangesScreen(Project.NameKey.parse(s
+            .substring(0, c)), s.substring(c + 1));
+      }
     }
 
     if (token.startsWith("patch,")) {
diff --git a/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java b/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java
index 0409cff..aa45522 100644
--- a/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java
+++ b/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java
@@ -15,10 +15,11 @@
 package com.google.gerrit.client.account;
 
 import com.google.gerrit.client.reviewdb.AccountProjectWatch;
+import com.google.gerrit.client.reviewdb.Change.Status;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.FancyFlexTable;
 import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
-import com.google.gerrit.client.ui.ProjectOpenLink;
+import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gwt.event.dom.client.BlurEvent;
 import com.google.gwt.event.dom.client.BlurHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -222,7 +223,7 @@
 
     void populate(final int row, final AccountProjectWatchInfo k) {
       table.setWidget(row, 1, new CheckBox());
-      table.setWidget(row, 2, new ProjectOpenLink(k.getProject().getNameKey()));
+      table.setWidget(row, 2, new ProjectLink(k.getProject().getNameKey(), Status.NEW));
       {
         final CheckBox notifyNewChanges = new CheckBox();
         notifyNewChanges.addClickHandler(new ClickHandler() {
diff --git a/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java b/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java
new file mode 100644
index 0000000..c72becc
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/changes/ByProjectAbandonedChangesScreen.java
@@ -0,0 +1,47 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.changes;
+
+import com.google.gerrit.client.reviewdb.Change;
+import com.google.gerrit.client.reviewdb.Project;
+
+
+public class ByProjectAbandonedChangesScreen extends AllSingleListScreen {
+  private final Project.NameKey projectKey;
+
+  public ByProjectAbandonedChangesScreen(final Project.NameKey proj,
+      final String positionToken) {
+    super("project,abandoned," + proj.toString(), positionToken);
+    projectKey = proj;
+  }
+
+  @Override
+  protected void onInitUI() {
+    super.onInitUI();
+    setPageTitle(Util.M.changesAbandonedInProject(projectKey.get()));
+  }
+
+  @Override
+  protected void loadPrev() {
+    Util.LIST_SVC.byProjectClosedPrev(projectKey, Change.Status.ABANDONED, pos,
+        pageSize, loadCallback());
+  }
+
+  @Override
+  protected void loadNext() {
+    Util.LIST_SVC.byProjectClosedNext(projectKey, Change.Status.ABANDONED, pos,
+        pageSize, loadCallback());
+  }
+}
diff --git a/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java b/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java
new file mode 100644
index 0000000..db8cb37
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/changes/ByProjectMergedChangesScreen.java
@@ -0,0 +1,47 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.changes;
+
+import com.google.gerrit.client.reviewdb.Change;
+import com.google.gerrit.client.reviewdb.Project;
+
+
+public class ByProjectMergedChangesScreen extends AllSingleListScreen {
+  private final Project.NameKey projectKey;
+
+  public ByProjectMergedChangesScreen(final Project.NameKey proj,
+      final String positionToken) {
+    super("project,merged," + proj.toString(), positionToken);
+    projectKey = proj;
+  }
+
+  @Override
+  protected void onInitUI() {
+    super.onInitUI();
+    setPageTitle(Util.M.changesMergedInProject(projectKey.get()));
+  }
+
+  @Override
+  protected void loadPrev() {
+    Util.LIST_SVC.byProjectClosedPrev(projectKey, Change.Status.MERGED, pos,
+        pageSize, loadCallback());
+  }
+
+  @Override
+  protected void loadNext() {
+    Util.LIST_SVC.byProjectClosedNext(projectKey, Change.Status.MERGED, pos,
+        pageSize, loadCallback());
+  }
+}
diff --git a/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java b/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
index 803ecf5..a1d08cf 100644
--- a/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
+++ b/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.client.reviewdb.Change;
 import com.google.gerrit.client.ui.AccountDashboardLink;
 import com.google.gerrit.client.ui.ChangeLink;
-import com.google.gerrit.client.ui.ProjectOpenLink;
+import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
@@ -74,7 +74,7 @@
     final Branch.NameKey dst = chg.getDest();
     table.setText(R_CHANGE_ID, 1, chg.getKey().get());
     table.setWidget(R_OWNER, 1, AccountDashboardLink.link(acc, chg.getOwner()));
-    table.setWidget(R_PROJECT, 1, new ProjectOpenLink(chg.getProject()));
+    table.setWidget(R_PROJECT, 1, new ProjectLink(chg.getProject(), chg.getStatus()));
     table.setText(R_BRANCH, 1, dst.getShortName());
     table.setText(R_UPLOADED, 1, mediumFormat(chg.getCreatedOn()));
     table.setText(R_UPDATED, 1, mediumFormat(chg.getLastUpdatedOn()));
diff --git a/src/main/java/com/google/gerrit/client/changes/ChangeListService.java b/src/main/java/com/google/gerrit/client/changes/ChangeListService.java
index 679ec2b..e5f2668 100644
--- a/src/main/java/com/google/gerrit/client/changes/ChangeListService.java
+++ b/src/main/java/com/google/gerrit/client/changes/ChangeListService.java
@@ -43,6 +43,20 @@
   void byProjectOpenNext(Project.NameKey project, String pos, int limit,
       AsyncCallback<SingleListChangeInfo> callback);
 
+  /**
+   * Get all closed changes with same status, more recent than pos, fetching at
+   * most limit rows.
+   */
+  void byProjectClosedPrev(Project.NameKey project, Change.Status status,
+      String pos, int limit, AsyncCallback<SingleListChangeInfo> callback);
+
+  /**
+   * Get all closed changes with same status, older than pos, fetching at most
+   * limit rows.
+   */
+  void byProjectClosedNext(Project.NameKey project, Change.Status status,
+      String pos, int limit, AsyncCallback<SingleListChangeInfo> callback);
+
   /** Get all closed changes more recent than pos, fetching at most limit rows. */
   void allClosedPrev(Change.Status status, String pos, int limit,
       AsyncCallback<SingleListChangeInfo> callback);
@@ -76,7 +90,7 @@
 
   /**
    * Add and/or remove changes from the set of starred changes of the caller.
-   * 
+   *
    * @param req the add and remove cluster.
    */
   @SignInRequired
diff --git a/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java b/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java
index 7ed96b7..26ffe36 100644
--- a/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java
+++ b/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java
@@ -21,6 +21,8 @@
   String changesStartedBy(String fullName);
   String changesReviewableBy(String fullName);
   String changesOpenInProject(String string);
+  String changesMergedInProject(String string);
+  String changesAbandonedInProject(String string);
 
   String changeScreenTitleId(String changeId);
   String patchSetHeader(int id);
diff --git a/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties b/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
index 7913607..8f3def1 100644
--- a/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
+++ b/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
@@ -2,6 +2,8 @@
 changesStartedBy = Started by {0}
 changesReviewableBy = Reviewable by {0}
 changesOpenInProject = Open Changes In {0}
+changesMergedInProject = Merged Changes In {0}
+changesAbandonedInProject = Abandoned Changes In {0}
 
 changeScreenTitleId = Change {0}
 patchSetHeader = Patch Set {0}
diff --git a/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 3b80e62..664f1ad 100644
--- a/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -36,7 +36,7 @@
 import com.google.gerrit.client.ui.ChangeLink;
 import com.google.gerrit.client.ui.NavigationTable;
 import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
-import com.google.gerrit.client.ui.ProjectOpenLink;
+import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
@@ -233,7 +233,7 @@
     table.setWidget(row, C_SUBJECT, new TableChangeLink(s, c));
     table.setWidget(row, C_OWNER, link(c.getOwner()));
     table.setWidget(row, C_PROJECT,
-        new ProjectOpenLink(c.getProject().getKey()));
+        new ProjectLink(c.getProject().getKey(), c.getStatus()));
     table.setText(row, C_BRANCH, c.getBranch());
     table.setText(row, C_LAST_UPDATE, shortFormat(c.getLastUpdatedOn()));
     setRowItem(row, c);
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/ChangeAccess.java b/src/main/java/com/google/gerrit/client/reviewdb/ChangeAccess.java
index 7fe8137..97bed62 100644
--- a/src/main/java/com/google/gerrit/client/reviewdb/ChangeAccess.java
+++ b/src/main/java/com/google/gerrit/client/reviewdb/ChangeAccess.java
@@ -70,6 +70,16 @@
   ResultSet<Change> byProjectOpenNext(Project.NameKey p, String sortKey,
       int limit) throws OrmException;
 
+  @Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey > ?"
+      + " ORDER BY sortKey LIMIT ?")
+  ResultSet<Change> byProjectClosedPrev(char status, Project.NameKey p,
+      String sortKey, int limit) throws OrmException;
+
+  @Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey < ?"
+      + " ORDER BY sortKey DESC LIMIT ?")
+  ResultSet<Change> byProjectClosedNext(char status, Project.NameKey p,
+      String sortKey, int limit) throws OrmException;
+
   @Query("WHERE open = false AND status = ? AND sortKey > ? ORDER BY sortKey LIMIT ?")
   ResultSet<Change> allClosedPrev(char status, String sortKey, int limit)
       throws OrmException;
diff --git a/src/main/java/com/google/gerrit/client/ui/ProjectLink.java b/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
new file mode 100644
index 0000000..d743c5f
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.ui;
+
+import com.google.gerrit.client.Link;
+import com.google.gerrit.client.changes.ByProjectAbandonedChangesScreen;
+import com.google.gerrit.client.changes.ByProjectMergedChangesScreen;
+import com.google.gerrit.client.changes.ByProjectOpenChangesScreen;
+import com.google.gerrit.client.reviewdb.Change;
+import com.google.gerrit.client.reviewdb.Project;
+import com.google.gerrit.client.reviewdb.Change.Status;
+
+/** Link to the open changes of a project. */
+public class ProjectLink extends DirectScreenLink {
+  private Project.NameKey project;
+  private Status status;
+
+  public ProjectLink(final Project.NameKey proj, Change.Status stat) {
+    this(proj.get(), proj, stat);
+  }
+
+  public ProjectLink(final String text, final Project.NameKey proj,
+      Change.Status stat) {
+    super(text, Link.toProject(proj, stat));
+    status = stat;
+    project = proj;
+  }
+
+  @Override
+  protected Screen createScreen() {
+    switch (status) {
+      case ABANDONED:
+        return new ByProjectAbandonedChangesScreen(project, "n,z");
+
+      case MERGED:
+        return new ByProjectMergedChangesScreen(project, "n,z");
+
+      case NEW:
+      case SUBMITTED:
+      default:
+        return new ByProjectOpenChangesScreen(project, "n,z");
+    }
+  }
+}
diff --git a/src/main/java/com/google/gerrit/client/ui/ProjectOpenLink.java b/src/main/java/com/google/gerrit/client/ui/ProjectOpenLink.java
deleted file mode 100644
index 1d3e214..0000000
--- a/src/main/java/com/google/gerrit/client/ui/ProjectOpenLink.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Link;
-import com.google.gerrit.client.changes.ByProjectOpenChangesScreen;
-import com.google.gerrit.client.reviewdb.Project;
-
-/** Link to the open changes of a project. */
-public class ProjectOpenLink extends DirectScreenLink {
-  private Project.NameKey project;
-
-  public ProjectOpenLink(final Project.NameKey proj) {
-    this(proj.get(), proj);
-  }
-
-  public ProjectOpenLink(final String text, final Project.NameKey proj) {
-    super(text, Link.toProjectOpen(proj));
-    project = proj;
-  }
-
-  @Override
-  protected Screen createScreen() {
-    return new ByProjectOpenChangesScreen(project, "n,z");
-  }
-}
diff --git a/src/main/java/com/google/gerrit/server/rpc/ChangeListServiceImpl.java b/src/main/java/com/google/gerrit/server/rpc/ChangeListServiceImpl.java
index fe5c30d..88b5224 100644
--- a/src/main/java/com/google/gerrit/server/rpc/ChangeListServiceImpl.java
+++ b/src/main/java/com/google/gerrit/server/rpc/ChangeListServiceImpl.java
@@ -154,6 +154,32 @@
     });
   }
 
+  public void byProjectClosedPrev(final Project.NameKey project,
+      final Change.Status s, final String pos, final int pageSize,
+      final AsyncCallback<SingleListChangeInfo> callback) {
+    run(callback, new QueryPrev(pageSize, pos) {
+      @Override
+      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
+          throws OrmException {
+        return db.changes().byProjectClosedPrev(s.getCode(), project, sortKey,
+            slim);
+      }
+    });
+  }
+
+  public void byProjectClosedNext(final Project.NameKey project,
+      final Change.Status s, final String pos, final int pageSize,
+      final AsyncCallback<SingleListChangeInfo> callback) {
+    run(callback, new QueryNext(pageSize, pos) {
+      @Override
+      ResultSet<Change> query(ReviewDb db, int slim, String sortKey)
+          throws OrmException {
+        return db.changes().byProjectClosedNext(s.getCode(), project, sortKey,
+            slim);
+      }
+    });
+  }
+
   public void allClosedPrev(final Change.Status s, final String pos,
       final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
     run(callback, new QueryPrev(pageSize, pos) {