Merge branch 'stable-2.16'

* stable-2.16:
  Format Java files with google-java-format
  ChangeUpdatedListener: Extract PluginConfig to a local variable
  Remove unneeded finals
  Support adding reviewers in batch mode

Change-Id: I0699a0b5e3a0b44d28de9b45e8a263587a9cbb81
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ChangeUpdatedListener.java b/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ChangeUpdatedListener.java
index 37cb344..037ceb1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ChangeUpdatedListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ChangeUpdatedListener.java
@@ -20,6 +20,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.PluginConfig;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.events.Event;
 import com.google.gerrit.server.events.EventListener;
@@ -54,14 +55,14 @@
 
   @Inject
   ChangeUpdatedListener(
-      final ReviewersByBlame.Factory reviewersByBlameFactory,
-      final GitRepositoryManager repoManager,
-      final WorkQueue workQueue,
-      final IdentifiedUser.GenericFactory identifiedUserFactory,
-      final ThreadLocalRequestContext tl,
-      final PluginConfigFactory cfg,
-      final ChangeData.Factory changeDataFactory,
-      final @PluginName String pluginName) {
+      ReviewersByBlame.Factory reviewersByBlameFactory,
+      GitRepositoryManager repoManager,
+      WorkQueue workQueue,
+      IdentifiedUser.GenericFactory identifiedUserFactory,
+      ThreadLocalRequestContext tl,
+      PluginConfigFactory cfg,
+      ChangeData.Factory changeDataFactory,
+      @PluginName String pluginName) {
     this.reviewersByBlameFactory = reviewersByBlameFactory;
     this.repoManager = repoManager;
     this.workQueue = workQueue;
@@ -84,15 +85,10 @@
     String ignoreSubjectRegEx;
     String ignoreFileRegEx;
     try {
-      maxReviewers =
-          cfg.getFromProjectConfigWithInheritance(projectName, pluginName)
-              .getInt("maxReviewers", 3);
-      ignoreSubjectRegEx =
-          cfg.getFromProjectConfigWithInheritance(projectName, pluginName)
-              .getString("ignoreSubjectRegEx", "");
-      ignoreFileRegEx =
-          cfg.getFromProjectConfigWithInheritance(projectName, pluginName)
-              .getString("ignoreFileRegEx", "");
+      PluginConfig projectConfig = cfg.getFromProjectConfigWithInheritance(projectName, pluginName);
+      maxReviewers = projectConfig.getInt("maxReviewers", 3);
+      ignoreSubjectRegEx = projectConfig.getString("ignoreSubjectRegEx", "");
+      ignoreFileRegEx = projectConfig.getString("ignoreFileRegEx", "");
     } catch (NoSuchProjectException x) {
       log.error(x.getMessage(), x);
       return;
@@ -104,7 +100,7 @@
     try (Repository git = repoManager.openRepository(projectName);
         RevWalk rw = new RevWalk(git)) {
       Change.Id changeId = Change.id(e.change.get().number);
-      final ChangeData cd = changeDataFactory.create(projectName, changeId);
+      ChangeData cd = changeDataFactory.create(projectName, changeId);
       if (cd == null) {
         log.warn(
             "Change with id: '{}' on project key: '{}' not found.",
@@ -112,7 +108,7 @@
             projectName.toString());
         return;
       }
-      final Change change = cd.change();
+      Change change = cd.change();
       PatchSet.Id psId = PatchSet.id(changeId, e.patchSet.get().number);
       PatchSet ps = cd.patchSet(psId);
       if (ps == null) {
@@ -120,13 +116,13 @@
         return;
       }
 
-      final RevCommit commit = rw.parseCommit(ObjectId.fromString(e.patchSet.get().revision));
+      RevCommit commit = rw.parseCommit(ObjectId.fromString(e.patchSet.get().revision));
 
       if (!ignoreSubjectRegEx.isEmpty() && commit.getShortMessage().matches(ignoreSubjectRegEx)) {
         return;
       }
 
-      final Runnable task =
+      Runnable task =
           reviewersByBlameFactory.create(commit, change, ps, maxReviewers, git, ignoreFileRegEx);
 
       workQueue
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ReviewersByBlame.java b/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ReviewersByBlame.java
index 2bf2061..89b8450 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ReviewersByBlame.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewersbyblame/ReviewersByBlame.java
@@ -17,7 +17,9 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Ordering;
 import com.google.common.collect.Sets;
+import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Patch.ChangeType;
@@ -25,17 +27,14 @@
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.Emails;
-import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.patch.PatchListEntry;
 import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.restapi.change.ChangesCollection;
-import com.google.gerrit.server.restapi.change.PostReviewers;
 import com.google.inject.Inject;
-import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
@@ -65,8 +64,7 @@
   private final Emails emails;
   private final AccountCache accountCache;
   private final PatchListCache patchListCache;
-  private final Provider<PostReviewers> reviewersProvider;
-  private final ChangesCollection changes;
+  private final GerritApi gApi;
 
   public interface Factory {
     ReviewersByBlame create(
@@ -80,22 +78,20 @@
 
   @Inject
   public ReviewersByBlame(
-      final Emails emails,
-      final AccountCache accountCache,
-      final ChangesCollection changes,
-      final Provider<PostReviewers> reviewersProvider,
-      final PatchListCache patchListCache,
-      @Assisted final RevCommit commit,
-      @Assisted final Change change,
-      @Assisted final PatchSet ps,
-      @Assisted final int maxReviewers,
-      @Assisted final Repository repo,
-      @Assisted final String ignoreFileRegEx) {
+      Emails emails,
+      AccountCache accountCache,
+      PatchListCache patchListCache,
+      GerritApi gApi,
+      @Assisted RevCommit commit,
+      @Assisted Change change,
+      @Assisted PatchSet ps,
+      @Assisted int maxReviewers,
+      @Assisted Repository repo,
+      @Assisted String ignoreFileRegEx) {
     this.emails = emails;
     this.accountCache = accountCache;
-    this.changes = changes;
-    this.reviewersProvider = reviewersProvider;
     this.patchListCache = patchListCache;
+    this.gApi = gApi;
     this.commit = commit;
     this.change = change;
     this.ps = ps;
@@ -140,13 +136,14 @@
    */
   private void addReviewers(Set<Account.Id> topReviewers, Change change) {
     try {
-      ChangeResource changeResource = changes.parse(change.getId());
-      PostReviewers post = reviewersProvider.get();
-      for (Account.Id accountId : topReviewers) {
-        AddReviewerInput input = new AddReviewerInput();
-        input.reviewer = accountId.toString();
-        post.apply(changeResource, input);
+      ReviewInput in = new ReviewInput();
+      in.reviewers = new ArrayList<>(topReviewers.size());
+      for (Account.Id account : topReviewers) {
+        AddReviewerInput addReviewerInput = new AddReviewerInput();
+        addReviewerInput.reviewer = account.toString();
+        in.reviewers.add(addReviewerInput);
       }
+      gApi.changes().id(change.getChangeId()).current().review(in);
     } catch (Exception ex) {
       log.error("Couldn't add reviewers to the change", ex);
     }
@@ -160,7 +157,7 @@
    * @param reviewers A set of reviewers with their weight mapped to their {@link Account}
    * @return Reviewers that are best matches for this change, empty if none, never <code>null</code>
    */
-  private Set<Account.Id> findTopReviewers(final Map<Account, Integer> reviewers) {
+  private Set<Account.Id> findTopReviewers(Map<Account, Integer> reviewers) {
     Set<Account.Id> topReviewers = Sets.newHashSet();
     List<Entry<Account, Integer>> entries =
         Ordering.from(
@@ -185,8 +182,7 @@
    * @param blameResult Result of blame computation
    * @return a set of all possible reviewers, empty if none, never <code>null</code>
    */
-  private Map<Account, Integer> getReviewersForPatch(
-      final List<Edit> edits, final BlameResult blameResult) {
+  private Map<Account, Integer> getReviewersForPatch(List<Edit> edits, BlameResult blameResult) {
     Map<Account, Integer> reviewers = Maps.newHashMap();
     for (Edit edit : edits) {
       for (int i = edit.getBeginA(); i < edit.getEndA(); i++) {
@@ -220,7 +216,7 @@
    * @param parent Parent {@link RevCommit}
    * @return Result of blame computation, null if the computation fails
    */
-  private BlameResult computeBlame(final PatchListEntry entry, final RevCommit parent) {
+  private BlameResult computeBlame(PatchListEntry entry, RevCommit parent) {
     BlameCommand blameCommand = new BlameCommand(repo);
     blameCommand.setStartCommit(parent);
     blameCommand.setFilePath(entry.getNewName());