CodeOwnerResolver: Return Optional from resolve method rather than Stream The resolve method either returns a stream with exactly one code owner or an empty stream. It's easier and more readable to just return an Optional. Returning a stream is a left-over from when the resolve method was resolving "*" to all users. Signed-off-by: Edwin Kempin <ekempin@google.com> Change-Id: I1a575727855e72dfea876facf142ef4534982315
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java index ad239f0..c6b5f55 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
@@ -45,7 +45,6 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; /** Class to resolve {@link CodeOwnerReference}s to {@link CodeOwner}s. */ public class CodeOwnerResolver { @@ -188,7 +187,9 @@ } return true; }) - .flatMap(this::resolve) + .map(this::resolve) + .filter(Optional::isPresent) + .map(Optional::get) .collect(toImmutableSet()); return CodeOwnerResolverResult.create(codeOwners, ownedByAllUsers.get()); } @@ -233,34 +234,34 @@ * @return the {@link CodeOwner} for the code owner reference if it was resolved, otherwise {@link * Optional#empty()} */ - public Stream<CodeOwner> resolve(CodeOwnerReference codeOwnerReference) { + public Optional<CodeOwner> resolve(CodeOwnerReference codeOwnerReference) { String email = requireNonNull(codeOwnerReference, "codeOwnerReference").email(); logger.atFine().log("resolving code owner reference %s", codeOwnerReference); if (!isEmailDomainAllowed(email)) { logger.atFine().log("domain of email %s is not allowed", email); - return Stream.of(); + return Optional.empty(); } Optional<AccountState> accountState = lookupEmail(email).flatMap(accountId -> lookupAccount(accountId, email)); if (!accountState.isPresent()) { logger.atFine().log("no account for email %s", email); - return Stream.of(); + return Optional.empty(); } if (!accountState.get().account().isActive()) { logger.atFine().log("account for email %s is inactive", email); - return Stream.of(); + return Optional.empty(); } if (enforceVisibility && !isVisible(accountState.get(), email)) { logger.atFine().log( "account %d or email %s not visible", accountState.get().account().id().get(), email); - return Stream.of(); + return Optional.empty(); } CodeOwner codeOwner = CodeOwner.create(accountState.get().account().id()); logger.atFine().log("resolved to code owner %s", codeOwner); - return Stream.of(codeOwner); + return Optional.of(codeOwner); } /** Whether the given account can be seen. */
diff --git a/java/com/google/gerrit/plugins/codeowners/restapi/RenameEmail.java b/java/com/google/gerrit/plugins/codeowners/restapi/RenameEmail.java index e8092b3..0ed505b 100644 --- a/java/com/google/gerrit/plugins/codeowners/restapi/RenameEmail.java +++ b/java/com/google/gerrit/plugins/codeowners/restapi/RenameEmail.java
@@ -14,13 +14,10 @@ package com.google.gerrit.plugins.codeowners.restapi; -import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.util.Objects.requireNonNull; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; import com.google.gerrit.entities.Account; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.BadRequestException; @@ -158,19 +155,14 @@ } } - private Account.Id resolveEmail(String email) - throws ResourceConflictException, UnprocessableEntityException { + private Account.Id resolveEmail(String email) throws UnprocessableEntityException { requireNonNull(email, "email"); - ImmutableSet<CodeOwner> codeOwners = - codeOwnerResolver.resolve(CodeOwnerReference.create(email)).collect(toImmutableSet()); - if (codeOwners.isEmpty()) { + Optional<CodeOwner> codeOwner = codeOwnerResolver.resolve(CodeOwnerReference.create(email)); + if (!codeOwner.isPresent()) { throw new UnprocessableEntityException(String.format("cannot resolve email %s", email)); } - if (codeOwners.size() > 1) { - throw new ResourceConflictException(String.format("email %s is ambigious", email)); - } - return Iterables.getOnlyElement(codeOwners).accountId(); + return codeOwner.get().accountId(); } /**
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java index 6e19e28..cefe297 100644 --- a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java +++ b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
@@ -34,8 +34,8 @@ import com.google.inject.Key; import com.google.inject.Provider; import java.nio.file.Paths; +import java.util.Optional; import java.util.Set; -import java.util.stream.Stream; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.junit.Before; @@ -89,14 +89,14 @@ @Test public void resolveCodeOwnerReferenceForEmail() throws Exception { - Stream<CodeOwner> codeOwner = + Optional<CodeOwner> codeOwner = codeOwnerResolver.get().resolve(CodeOwnerReference.create(admin.email())); - assertThat(codeOwner).onlyElement().hasAccountIdThat().isEqualTo(admin.id()); + assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(admin.id()); } @Test public void cannotResolveCodeOwnerReferenceForStarAsEmail() throws Exception { - Stream<CodeOwner> codeOwner = + Optional<CodeOwner> codeOwner = codeOwnerResolver .get() .resolve(CodeOwnerReference.create(CodeOwnerResolver.ALL_USERS_WILDCARD)); @@ -160,14 +160,14 @@ // admin has the "Modify Account" global capability and hence can see the secondary email of the // user account. - Stream<CodeOwner> codeOwner = + Optional<CodeOwner> codeOwner = codeOwnerResolver.get().resolve(CodeOwnerReference.create(secondaryEmail)); - assertThat(codeOwner).onlyElement().hasAccountIdThat().isEqualTo(user.id()); + assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id()); // user can see its own secondary email. requestScopeOperations.setApiUser(user.id()); codeOwner = codeOwnerResolver.get().resolve(CodeOwnerReference.create(secondaryEmail)); - assertThat(codeOwner).onlyElement().hasAccountIdThat().isEqualTo(user.id()); + assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id()); } @Test @@ -297,9 +297,9 @@ assertThat(codeOwnerResolver.get().resolve(adminCodeOwnerReference)).isEmpty(); // if visibility is not enforced the code owner reference can be resolved regardless - Stream<CodeOwner> codeOwner = + Optional<CodeOwner> codeOwner = codeOwnerResolver.get().enforceVisibility(false).resolve(adminCodeOwnerReference); - assertThat(codeOwner).onlyElement().hasAccountIdThat().isEqualTo(admin.id()); + assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(admin.id()); } @Test @@ -311,13 +311,13 @@ // admin is the current user and can see the account assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(user.email()))) - .isNotEmpty(); + .isPresent(); assertThat( codeOwnerResolver .get() .forUser(identifiedUserFactory.create(admin.id())) .resolve(CodeOwnerReference.create(user.email()))) - .isNotEmpty(); + .isPresent(); // user2 cannot see the account assertThat(