Add Javadoc for Groups and GroupsUpdate
Change-Id: I95d2e23957bbabd2d8a848f713bf13681b30b5f1
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
index 578e4d1..9f840ee 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
@@ -31,19 +31,56 @@
import java.util.Optional;
import java.util.stream.Stream;
+/**
+ * A database accessor for read calls related to groups.
+ *
+ * <p>All calls which read group related details from the database (either ReviewDb or NoteDb) are
+ * gathered here. Other classes should always use this class instead of accessing the database
+ * directly. There are a few exceptions though: schema classes, wrapper classes, and classes
+ * executed during init. The latter ones should use {@code GroupsOnInit} instead.
+ *
+ * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups.
+ */
@Singleton
public class Groups {
+ /**
+ * Returns the {@code AccountGroup} for the specified UUID.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the group
+ * @return the {@code AccountGroup} which has the specified UUID
+ * @throws OrmDuplicateKeyException if multiple groups are found for the specified UUID
+ * @throws OrmException if the group couldn't be retrieved from ReviewDb
+ * @throws NoSuchGroupException if a group with such a UUID doesn't exist
+ */
public AccountGroup getExistingGroup(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
Optional<AccountGroup> group = getGroup(db, groupUuid);
return group.orElseThrow(() -> new NoSuchGroupException(groupUuid));
}
+ /**
+ * Returns the {@code AccountGroup} for the specified ID if it exists.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupId the ID of the group
+ * @return the found {@code AccountGroup} if it exists, or else an empty {@code Optional}
+ * @throws OrmException if the group couldn't be retrieved from ReviewDb
+ */
public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.Id groupId) throws OrmException {
return Optional.ofNullable(db.accountGroups().get(groupId));
}
+ /**
+ * Returns the {@code AccountGroup} for the specified UUID if it exists.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the group
+ * @return the found {@code AccountGroup} if it exists, or else an empty {@code Optional}
+ * @throws OrmDuplicateKeyException if multiple groups are found for the specified UUID
+ * @throws OrmException if the group couldn't be retrieved from ReviewDb
+ */
public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException {
List<AccountGroup> accountGroups = db.accountGroups().byUUID(groupUuid).toList();
@@ -56,6 +93,14 @@
}
}
+ /**
+ * Returns the {@code AccountGroup} for the specified name if it exists.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupName the name of the group
+ * @return the found {@code AccountGroup} if it exists, or else an empty {@code Optional}
+ * @throws OrmException if the group couldn't be retrieved from ReviewDb
+ */
public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.NameKey groupName)
throws OrmException {
AccountGroupName accountGroupName = db.accountGroupNames().get(groupName);
@@ -71,6 +116,18 @@
return Streams.stream(db.accountGroups().all());
}
+ /**
+ * Indicates whether the specified account is a member of the specified group.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the account exists!
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the group
+ * @param accountId the ID of the account
+ * @return {@code true} if the account is a member of the group, or else {@code false}
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public boolean isMember(ReviewDb db, AccountGroup.UUID groupUuid, Account.Id accountId)
throws OrmException, NoSuchGroupException {
AccountGroup group = getExistingGroup(db, groupUuid);
@@ -78,6 +135,21 @@
return db.accountGroupMembers().get(key) != null;
}
+ /**
+ * Indicates whether the specified group is a subgroup of the specified parent group.
+ *
+ * <p>The parent group must be an internal group whereas the subgroup may either be an internal or
+ * an external group.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the subgroup exists!
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param parentGroupUuid the UUID of the parent group
+ * @param includedGroupUuid the UUID of the subgroup
+ * @return {@code true} if the group is a subgroup of the other group, or else {@code false}
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ * @throws NoSuchGroupException if the specified parent group doesn't exist
+ */
public boolean isIncluded(
ReviewDb db, AccountGroup.UUID parentGroupUuid, AccountGroup.UUID includedGroupUuid)
throws OrmException, NoSuchGroupException {
@@ -86,6 +158,17 @@
return db.accountGroupById().get(key) != null;
}
+ /**
+ * Returns the members (accounts) of a group.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the accounts exist!
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the group
+ * @return a stream of the IDs of the members
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public Stream<Account.Id> getMembers(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
AccountGroup group = getExistingGroup(db, groupUuid);
@@ -94,6 +177,20 @@
return Streams.stream(accountGroupMembers).map(AccountGroupMember::getAccountId);
}
+ /**
+ * Returns the subgroups of a group.
+ *
+ * <p>This parent group must be an internal group whereas the subgroups can either be internal or
+ * external groups.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the subgroups exist!
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the parent group
+ * @return a stream of the UUIDs of the subgroups
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ * @throws NoSuchGroupException if the specified parent group doesn't exist
+ */
public Stream<AccountGroup.UUID> getIncludes(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
AccountGroup group = getExistingGroup(db, groupUuid);
@@ -101,6 +198,17 @@
return Streams.stream(accountGroupByIds).map(AccountGroupById::getIncludeUUID).distinct();
}
+ /**
+ * Returns the groups of which the specified account is a member.
+ *
+ * <p><strong>Note</strong>: This method returns an empty stream if the account doesn't exist.
+ * This method doesn't check whether the groups exist.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param accountId the ID of the account
+ * @return a stream of the IDs of the groups of which the account is a member
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ */
public Stream<AccountGroup.Id> getGroupsWithMember(ReviewDb db, Account.Id accountId)
throws OrmException {
ResultSet<AccountGroupMember> accountGroupMembers =
@@ -108,6 +216,20 @@
return Streams.stream(accountGroupMembers).map(AccountGroupMember::getAccountGroupId);
}
+ /**
+ * Returns the parent groups of the specified (sub)group.
+ *
+ * <p>The subgroup may either be an internal or an external group whereas the returned parent
+ * groups represent only internal groups.
+ *
+ * <p><strong>Note</strong>: This method returns an empty stream if the specified group doesn't
+ * exist. This method doesn't check whether the parent groups exist.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param includedGroupUuid the UUID of the subgroup
+ * @return a stream of the IDs of the parent groups
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ */
public Stream<AccountGroup.Id> getParentGroups(ReviewDb db, AccountGroup.UUID includedGroupUuid)
throws OrmException {
ResultSet<AccountGroupById> accountGroupByIds =
@@ -115,6 +237,14 @@
return Streams.stream(accountGroupByIds).map(AccountGroupById::getGroupId);
}
+ /**
+ * Returns all known external groups. External groups are 'known' when they are specified as a
+ * subgroup of an internal group.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @return a stream of the UUIDs of the known external groups
+ * @throws OrmException if an error occurs while reading from ReviewDb
+ */
public Stream<AccountGroup.UUID> getExternalGroups(ReviewDb db) throws OrmException {
return Streams.stream(db.accountGroupById().all())
.map(AccountGroupById::getIncludeUUID)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
index 0aea001..bbf4eca 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
@@ -44,6 +44,16 @@
import java.util.function.Consumer;
import org.eclipse.jgit.lib.PersonIdent;
+/**
+ * A database accessor for write calls related to groups.
+ *
+ * <p>All calls which write group related details to the database (either ReviewDb or NoteDb) are
+ * gathered here. Other classes should always use this class instead of accessing the database
+ * directly. There are a few exceptions though: schema classes, wrapper classes, and classes
+ * executed during init. The latter ones should use {@code GroupsOnInit} instead.
+ *
+ * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups.
+ */
public class GroupsUpdate {
public interface Factory {
GroupsUpdate create(@Nullable IdentifiedUser currentUser);
@@ -109,10 +119,24 @@
return user.newCommitterIdent(ident.getWhen(), ident.getTimeZone());
}
+ /**
+ * Adds/Creates the specified group.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param group the group to add
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ */
public void addGroup(ReviewDb db, AccountGroup group) throws OrmException {
addNewGroup(db, group);
}
+ /**
+ * Adds the specified group.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param group the group to add
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ */
public static void addNewGroup(ReviewDb db, AccountGroup group) throws OrmException {
AccountGroupName gn = new AccountGroupName(group);
// first insert the group name to validate that the group name hasn't
@@ -121,6 +145,16 @@
db.accountGroups().insert(ImmutableList.of(group));
}
+ /**
+ * Updates the specified group.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param groupUuid the UUID of the group to update
+ * @param groupConsumer a {@code Consumer} which performs the desired updates on the group
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws IOException if the cache entry for the group couldn't be invalidated
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public void updateGroup(
ReviewDb db, AccountGroup.UUID groupUuid, Consumer<AccountGroup> groupConsumer)
throws OrmException, IOException, NoSuchGroupException {
@@ -131,13 +165,24 @@
@VisibleForTesting
public AccountGroup updateGroupInDb(
ReviewDb db, AccountGroup.UUID groupUuid, Consumer<AccountGroup> groupConsumer)
- throws OrmException, IOException, NoSuchGroupException {
+ throws OrmException, NoSuchGroupException {
AccountGroup group = groups.getExistingGroup(db, groupUuid);
groupConsumer.accept(group);
db.accountGroups().update(ImmutableList.of(group));
return group;
}
+ /**
+ * Renames the specified group.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param groupUuid the UUID of the group to rename
+ * @param newName the new name of the group
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws IOException if the cache entry for the group couldn't be invalidated
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ * @throws NameAlreadyUsedException if another group has the name {@code newName}
+ */
public void renameGroup(ReviewDb db, AccountGroup.UUID groupUuid, AccountGroup.NameKey newName)
throws OrmException, IOException, NameAlreadyUsedException, NoSuchGroupException {
AccountGroup group = groups.getExistingGroup(db, groupUuid);
@@ -175,11 +220,37 @@
.start(0, TimeUnit.MILLISECONDS);
}
+ /**
+ * Adds an account as member to a group. The account is only added as a new member if it isn't
+ * already a member of the group.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the account exists!
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param groupUuid the UUID of the group
+ * @param accountId the ID of the account to add
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws IOException if the cache entry of the new member couldn't be invalidated
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public void addGroupMember(ReviewDb db, AccountGroup.UUID groupUuid, Account.Id accountId)
throws OrmException, IOException, NoSuchGroupException {
addGroupMembers(db, groupUuid, ImmutableSet.of(accountId));
}
+ /**
+ * Adds several accounts as members to a group. Only accounts which currently aren't members of
+ * the group are added.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the accounts exist!
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param groupUuid the UUID of the group
+ * @param accountIds a set of IDs of accounts to add
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws IOException if the cache entry of one of the new members couldn't be invalidated
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public void addGroupMembers(ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds)
throws OrmException, IOException, NoSuchGroupException {
AccountGroup group = groups.getExistingGroup(db, groupUuid);
@@ -206,6 +277,17 @@
}
}
+ /**
+ * Removes several members (accounts) from a group. Only accounts which currently are members of
+ * the group are removed.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param groupUuid the UUID of the group
+ * @param accountIds a set of IDs of accounts to remove
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws IOException if the cache entry of one of the removed members couldn't be invalidated
+ * @throws NoSuchGroupException if the specified group doesn't exist
+ */
public void removeGroupMembers(
ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds)
throws OrmException, IOException, NoSuchGroupException {
@@ -233,6 +315,21 @@
}
}
+ /**
+ * Adds several groups as subgroups to a group. Only groups which currently aren't subgroups of
+ * the group are added.
+ *
+ * <p>The parent group must be an internal group whereas the subgroups can either be internal or
+ * external groups.
+ *
+ * <p><strong>Note</strong>: This method doesn't check whether the subgroups exist!
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param parentGroupUuid the UUID of the parent group
+ * @param includedGroupUuids a set of IDs of the groups to add as subgroups
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws NoSuchGroupException if the specified parent group doesn't exist
+ */
public void addIncludedGroups(
ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> includedGroupUuids)
throws OrmException, NoSuchGroupException {
@@ -261,6 +358,19 @@
groupIncludeCache.evictSubgroupsOf(parentGroupUuid);
}
+ /**
+ * Removes several subgroups from a parent group. Only groups which currently are subgroups of the
+ * group are removed.
+ *
+ * <p>The parent group must be an internal group whereas the subgroups can either be internal or
+ * external groups.
+ *
+ * @param db the {@code ReviewDb} instance to update
+ * @param parentGroupUuid the UUID of the parent group
+ * @param includedGroupUuids a set of IDs of the subgroups to remove from the parent group
+ * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
+ * @throws NoSuchGroupException if the specified parent group doesn't exist
+ */
public void deleteIncludedGroups(
ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> includedGroupUuids)
throws OrmException, NoSuchGroupException {