Include project object during group name suggestion

GroupBackend implementers should have more information about context in
which group name suggestion should occurs. Our context here is project
to which we user want to add new access configuration. Project name and
parent project name could narrow list of possible suggestions.

Change-Id: I1349f00c3999843925750c195a218b0ea0614951
Signed-off-by: Dariusz Luksza <dariusz@luksza.org>
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
index 559c270..22546a7 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
@@ -201,8 +201,9 @@
 
   private List<GroupReference> suggestAccountGroup(
       @Nullable final ProjectControl projectControl, final String query, final int limit) {
-    final int n = limit <= 0 ? 10 : Math.min(limit, 10);
-    return Lists.newArrayList(Iterables.limit(groupBackend.suggest(query), n));
+    return Lists.newArrayList(Iterables.limit(
+        groupBackend.suggest(query, projectControl),
+        limit <= 0 ? 10 : Math.min(limit, 10)));
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackend.java
index b4e770f..34db967 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackend.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackend.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.extensions.annotations.ExtensionPoint;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.project.ProjectControl;
 
 import java.util.Collection;
 
@@ -44,7 +45,9 @@
   GroupDescription.Basic get(AccountGroup.UUID uuid);
 
   /** @return suggestions for the group name sorted by name. */
-  Collection<GroupReference> suggest(String name);
+  Collection<GroupReference> suggest(
+      String name,
+      @Nullable ProjectControl project);
 
   /** @return the group membership checker for the backend. */
   GroupMembership membershipsOf(IdentifiedUser user);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackends.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackends.java
index cdbb0e4..f7e0634 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackends.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupBackends.java
@@ -16,6 +16,8 @@
 
 import com.google.common.collect.Iterables;
 import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.project.ProjectControl;
 
 import java.util.Collection;
 import java.util.Comparator;
@@ -36,7 +38,7 @@
   };
 
   /**
-   * Runs {@link GroupBackend#suggest(String)} and filters the result to return
+   * Runs {@link GroupBackend#suggest(String, Project)} and filters the result to return
    * the best suggestion, or null if one does not exist.
    *
    * @param groupBackend the group backend
@@ -44,9 +46,23 @@
    * @return the best single GroupReference suggestion
    */
   @Nullable
-  public static GroupReference findBestSuggestion(
-      GroupBackend groupBackend, String name) {
-    Collection<GroupReference> refs = groupBackend.suggest(name);
+  public static GroupReference findBestSuggestion(GroupBackend groupBackend,
+      String name) {
+    return findBestSuggestion(groupBackend, name, null);
+  }
+  /**
+   * Runs {@link GroupBackend#suggest(String, Project)} and filters the result to return
+   * the best suggestion, or null if one does not exist.
+   *
+   * @param groupBackend the group backend
+   * @param name the name for which to suggest groups
+   * @param project the project for which to suggest groups
+   * @return the best single GroupReference suggestion
+   */
+  @Nullable
+  public static GroupReference findBestSuggestion(GroupBackend groupBackend,
+      String name, @Nullable ProjectControl project) {
+    Collection<GroupReference> refs = groupBackend.suggest(name, project);
     if (refs.size() == 1) {
       return Iterables.getOnlyElement(refs);
     }
@@ -60,7 +76,7 @@
   }
 
   /**
-   * Runs {@link GroupBackend#suggest(String)} and filters the result to return
+   * Runs {@link GroupBackend#suggest(String, Project)} and filters the result to return
    * the exact suggestion, or null if one does not exist.
    *
    * @param groupBackend the group backend
@@ -70,7 +86,22 @@
   @Nullable
   public static GroupReference findExactSuggestion(
       GroupBackend groupBackend, String name) {
-    Collection<GroupReference> refs = groupBackend.suggest(name);
+    return findExactSuggestion(groupBackend, name, null);
+  }
+
+  /**
+   * Runs {@link GroupBackend#suggest(String, Project)} and filters the result to return
+   * the exact suggestion, or null if one does not exist.
+   *
+   * @param groupBackend the group backend
+   * @param name the name for which to suggest groups
+   * @param project the project for which to suggest groups
+   * @return the exact single GroupReference suggestion
+   */
+  @Nullable
+  public static GroupReference findExactSuggestion(
+      GroupBackend groupBackend, String name, ProjectControl project) {
+    Collection<GroupReference> refs = groupBackend.suggest(name, project);
     for (GroupReference ref : refs) {
       if (isExactSuggestion(ref, name)) {
         return ref;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/InternalGroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/InternalGroupBackend.java
index d06db4d..a70f942 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/InternalGroupBackend.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/InternalGroupBackend.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.project.ProjectControl;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -71,7 +72,8 @@
   }
 
   @Override
-  public Collection<GroupReference> suggest(final String name) {
+  public Collection<GroupReference> suggest(final String name,
+      final ProjectControl project) {
     Iterable<AccountGroup> filtered = Iterables.filter(groupCache.all(),
         new Predicate<AccountGroup>() {
           @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java
index d9c9257..046dfa5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.project.ProjectControl;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -82,10 +83,10 @@
   }
 
   @Override
-  public Collection<GroupReference> suggest(String name) {
+  public Collection<GroupReference> suggest(String name, ProjectControl project) {
     Set<GroupReference> groups = Sets.newTreeSet(GROUP_REF_NAME_COMPARATOR);
     for (GroupBackend g : backends) {
-      groups.addAll(g.suggest(name));
+      groups.addAll(g.suggest(name, project));
     }
     return groups;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
index 2cf372b..97a0309 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.server.account.ListGroupMembership;
 import com.google.gerrit.server.auth.ldap.Helper.LdapSchema;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectControl;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.name.Named;
@@ -164,7 +165,7 @@
   }
 
   @Override
-  public Collection<GroupReference> suggest(String name) {
+  public Collection<GroupReference> suggest(String name, ProjectControl project) {
     AccountGroup.UUID uuid = new AccountGroup.UUID(name);
     if (isLdapUUID(uuid)) {
       GroupDescription.Basic g = get(uuid);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 7bbb073..e74172e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -367,7 +367,7 @@
 
     // If its not an account, maybe its a group?
     //
-    Collection<GroupReference> suggestions = args.groupBackend.suggest(who);
+    Collection<GroupReference> suggestions = args.groupBackend.suggest(who, null);
     if (!suggestions.isEmpty()) {
       HashSet<AccountGroup.UUID> ids = new HashSet<AccountGroup.UUID>();
       for (GroupReference ref : suggestions) {