Merge "Add REST api to get the most current report"
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 4c7029a..583577c 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
@@ -18,16 +18,23 @@
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
-import com.google.inject.Singleton;
 
 import com.googlesource.gerrit.plugins.verifystatus.common.VerificationInfo;
 
+import org.apache.commons.lang.builder.CompareToBuilder;
+import org.kohsuke.args4j.Option;
+
 import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
-@Singleton
 public class GetVerifications implements RestReadView<RevisionResource> {
   private final SchemaFactory<CiDb> schemaFactory;
 
@@ -36,24 +43,67 @@
     this.schemaFactory = schemaFactory;
   }
 
+  @Option(name = "--current", aliases = {"-c"},
+      usage = "List only the current report")
+  private boolean current;
+
   @Override
   public Map<String, VerificationInfo> apply(RevisionResource rsrc)
       throws IOException, OrmException {
-    Map<String, VerificationInfo> out = Maps.newHashMap();
+    Map<String, VerificationInfo> out = Maps.newLinkedHashMap();
     try (CiDb db = schemaFactory.open()) {
-      for (PatchSetVerification v : db.patchSetVerifications()
-          .byPatchSet(rsrc.getPatchSet().getId())) {
-        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);
+      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 (current) {
+        Map<String, Timestamp> reported = new HashMap<>();
+        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);
+          }
+        }
+      } else {
+        // show all reports
+        for (PatchSetVerification v : jobs) {
+          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);
+        }
       }
     }
     return out;
diff --git a/src/main/resources/Documentation/rest-api-changes.md b/src/main/resources/Documentation/rest-api-changes.md
index e10f965..051b6bf 100644
--- a/src/main/resources/Documentation/rest-api-changes.md
+++ b/src/main/resources/Documentation/rest-api-changes.md
@@ -23,7 +23,7 @@
 #### Request
 
 ```
-  GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/verifications HTTP/1.0
+  GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/@PLUGIN@~verifications HTTP/1.0
 ```
 
 #### Response
@@ -70,6 +70,55 @@
   }
 ```
 
+### <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.
+
+Assuming "HPE CI" and "ACME CI" published multiple reports to Gerrit.
+Retrieve the most current report(s) by each reporter:
+
+#### Request
+
+```
+  GET /changes/100/revisions/1/@PLUGIN@~verifications/?current HTTP/1.0
+```
+
+#### Response
+
+```
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  {
+    "5081c5e5-e101-43eb-8e59-4e197f22a0d0"": {
+      "name": "gate-horizon-pep8",
+      "url": "https://ci.host.com/jobs/gate-horizon-pep8/2711",
+      "value": -1,
+      "reporter": "HPE CI",
+      "comment": "Failed",
+      "category": "check",
+      "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",
+      "value": 1,
+      "abstain": true,
+      "reporter": "Acme CI",
+      "comment": "Informational only",
+      "category": "check",
+      "duration": "7m 40s"
+      "granted": "15 Mar 2016 08:30:16"
+    }
+  }
+```
+
 ### <a id="post-verify"> Post Verify
 
 __POST__ /changes/{change-id}/revisions/{revision-id}/@PLUGIN@~verifications