Add sort and filter options to REST endpoint

Allow users to sort and filter jobs when using the verification GET
REST endpoint. Refactor job panels to use these new options.

Change-Id: I449156c03c87611b2568820d28a69fb669c8d77e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsDropDownPanel.java b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsDropDownPanel.java
index 953761e..b50d189 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsDropDownPanel.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsDropDownPanel.java
@@ -48,7 +48,8 @@
         panel.getObject(GerritUiExtensionPoint.Key.REVISION_INFO).cast();
     new RestApi("changes").id(change.id()).view("revisions").id(rev.id())
         .view(Plugin.get().getPluginName(), "verifications")
-        .addParameter("current", true)
+        .addParameter("sort", "REPORTER")
+        .addParameter("filter", "CURRENT")
         .get(new AsyncCallback<NativeMap<VerificationInfo>>() {
           @Override
           public void onSuccess(NativeMap<VerificationInfo> result) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsPanel.java b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsPanel.java
index 8341f6b..a8e9909 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsPanel.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/client/JobsPanel.java
@@ -47,7 +47,8 @@
         panel.getObject(GerritUiExtensionPoint.Key.REVISION_INFO).cast();
     new RestApi("changes").id(change.id()).view("revisions").id(rev.id())
         .view(Plugin.get().getPluginName(), "verifications")
-        .addParameter("current", true)
+        .addParameter("sort", "REPORTER")
+        .addParameter("filter", "CURRENT")
         .get(new AsyncCallback<NativeMap<VerificationInfo>>() {
           @Override
           public void onSuccess(NativeMap<VerificationInfo> result) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/server/GetVerifications.java b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/server/GetVerifications.java
index 583577c..e900a3a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/verifystatus/server/GetVerifications.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/verifystatus/server/GetVerifications.java
@@ -31,7 +31,6 @@
 import java.sql.Timestamp;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -43,9 +42,20 @@
     this.schemaFactory = schemaFactory;
   }
 
-  @Option(name = "--current", aliases = {"-c"},
-      usage = "List only the current report")
-  private boolean current;
+  private String sort;
+  private String filter;
+
+  @Option(name = "--sort", aliases = {"-s"}, metaVar = "SORT",
+      usage = "Sort the list by an entry")
+  public void setSort(String sort) {
+    this.sort = sort.toUpperCase();
+  }
+
+  @Option(name = "--filter", aliases = {"-f"}, metaVar = "FILTER",
+      usage = "filter the results")
+  public void setFilter(String filter) {
+    this.filter = filter.toUpperCase();
+  }
 
   @Override
   public Map<String, VerificationInfo> apply(RevisionResource rsrc)
@@ -55,40 +65,73 @@
       ResultSet<PatchSetVerification> rs =
           db.patchSetVerifications().byPatchSet(rsrc.getPatchSet().getId());
       List<PatchSetVerification> jobs = rs.toList();
-      // sort the jobs list by reporter (acending) then reported date (decending)
-      Collections.sort(jobs, new Comparator<PatchSetVerification>() {
-        @Override
-        public int compare(PatchSetVerification a, PatchSetVerification b) {
-          return new CompareToBuilder()
-              .append(a.getReporter(),b.getReporter())
-              .append(b.getGranted(),a.getGranted())
-              .toComparison();
+      if (sort != null && !sort.isEmpty()) {
+        // sort the jobs list by reporter (ascending) then reported date (descending)
+        if (sort.equals("REPORTER")) {
+          Collections.sort(jobs, new Comparator<PatchSetVerification>() {
+            @Override
+            public int compare(PatchSetVerification a, PatchSetVerification b) {
+              return new CompareToBuilder()
+                  .append(a.getReporter(),b.getReporter())
+                  .append(b.getGranted(),a.getGranted())
+                  .toComparison();
+            }
+          });
+        } else if (sort.equals("NAME")) {
+          // sort the jobs list by name (ascending) then reported date (descending)
+          Collections.sort(jobs, new Comparator<PatchSetVerification>() {
+            @Override
+            public int compare(PatchSetVerification a, PatchSetVerification b) {
+              return new CompareToBuilder()
+                  .append(a.getName(),b.getName())
+                  .append(b.getGranted(),a.getGranted())
+                  .toComparison();
+            }
+          });
         }
-      });
+      }
 
-      if (current) {
-        Map<String, Timestamp> reported = new HashMap<>();
-        for (PatchSetVerification v : jobs) {
-          if (!reported.containsKey(v.getReporter())) {
-            reported.put(v.getReporter(), v.getGranted());
+      if (filter != null && !filter.isEmpty()) {
+        if (filter.equals("CURRENT") ) {
+          Map<String, Timestamp> reported = Maps.newHashMap();
+          for (PatchSetVerification v : jobs) {
+            if (!reported.containsKey(v.getReporter())) {
+              reported.put(v.getReporter(), v.getGranted());
+            }
           }
-        }
-        for (PatchSetVerification v : jobs) {
-          Timestamp ts = v.getGranted();
-          if (reported.values().contains(ts)) {
-            VerificationInfo info = new VerificationInfo();
-            info.value = v.getValue();
-            info.abstain = v.getAbstain();
-            info.url = v.getUrl();
-            info.name = v.getName();
-            info.reporter = v.getReporter();
-            info.comment = v.getComment();
-            info.granted = v.getGranted();
-            info.category = v.getCategory();
-            info.duration = v.getDuration();
-            out.put(v.getJobId().get(), info);
+          for (PatchSetVerification v : jobs) {
+            Timestamp ts = v.getGranted();
+            if (reported.values().contains(ts)) {
+              VerificationInfo info = new VerificationInfo();
+              info.value = v.getValue();
+              info.abstain = v.getAbstain();
+              info.url = v.getUrl();
+              info.name = v.getName();
+              info.reporter = v.getReporter();
+              info.comment = v.getComment();
+              info.granted = v.getGranted();
+              info.category = v.getCategory();
+              info.duration = v.getDuration();
+              out.put(v.getJobId().get(), info);
+            }
           }
-        }
+        } else if (filter.equals("FAILED") ) {
+            for (PatchSetVerification v : jobs) {
+              if (v.getValue() < 0) {
+                VerificationInfo info = new VerificationInfo();
+                info.value = v.getValue();
+                info.abstain = v.getAbstain();
+                info.url = v.getUrl();
+                info.name = v.getName();
+                info.reporter = v.getReporter();
+                info.comment = v.getComment();
+                info.granted = v.getGranted();
+                info.category = v.getCategory();
+                info.duration = v.getDuration();
+                out.put(v.getJobId().get(), info);
+              }
+            }
+          }
       } else {
         // show all reports
         for (PatchSetVerification v : jobs) {
diff --git a/src/main/resources/Documentation/rest-api-changes.md b/src/main/resources/Documentation/rest-api-changes.md
index 91123ca..2012f92 100644
--- a/src/main/resources/Documentation/rest-api-changes.md
+++ b/src/main/resources/Documentation/rest-api-changes.md
@@ -73,9 +73,32 @@
 ### <a id="verification-options"> Verification Options
 Verifications Options
 
-Current(c)::
-Limit the results to the most current list of reports that were reported by
-each reporter.
+Sort(s)::
+Sort the results by a field.
+
+|Field Name |Description|
+|:----------|:----------|
+|NAME       |Sort job name in ascending order|
+|REPORTER   |Sort reporter in ascending order|
+
+*__Note__: Fields are also sorted by the time the job was saved in descending
+order. 
+
+#### Request
+
+```
+  GET /changes/100/revisions/1/@PLUGIN@~verifications/?sort=REPORTER HTTP/1.0
+```
+
+
+Filter(f)::
+
+|Field Name |Description|
+|:----------|:----------|
+|CURRENT    |Limit the results to the most current list of reports|
+|FAILED     |Limit the results to only failed jobs|
+
+#### Example
 
 Assuming "Jenkins Check" and "ACME CI" published multiple reports to Gerrit.
 Retrieve the most current report(s) by each reporter:
@@ -83,7 +106,7 @@
 #### Request
 
 ```
-  GET /changes/100/revisions/1/@PLUGIN@~verifications/?current HTTP/1.0
+  GET /changes/100/revisions/1/@PLUGIN@~verifications/?sort=REPORTER&filter=CURRENT HTTP/1.0
 ```
 
 #### Response
@@ -95,16 +118,6 @@
 
   )]}'
   {
-    "5081c5e5-e101-43eb-8e59-4e197f22a0d0"": {
-      "name": "gate-horizon-pep8",
-      "url": "https://ci.host.com/jobs/gate-horizon-pep8/2711",
-      "value": -1,
-      "reporter": "Jenkins Check",
-      "comment": "Failed",
-      "category": "cloud server",
-      "duration": "3m 10s"
-      "granted": "15 Mar 2016 08:10:41",
-    },
     "2a359a73-31e7-4f81-b295-ae0e20615da6": {
       "name": "gate-horizon-python27",
       "url": "https://ci.host.com/jobs/gate-horizon-python27/1711",
@@ -115,6 +128,16 @@
       "category": "third party",
       "duration": "7m 40s"
       "granted": "15 Mar 2016 08:30:16"
+    },
+    "5081c5e5-e101-43eb-8e59-4e197f22a0d0"": {
+      "name": "gate-horizon-pep8",
+      "url": "https://ci.host.com/jobs/gate-horizon-pep8/2711",
+      "value": -1,
+      "reporter": "Jenkins Check",
+      "comment": "Failed",
+      "category": "cloud server",
+      "duration": "3m 10s"
+      "granted": "15 Mar 2016 08:10:41",
     }
   }
 ```