diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java index a7e525460a..a121248dba 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java @@ -77,7 +77,7 @@ class DeleteReviewer implements RestModifyView { new Predicate() { @Override public boolean apply(PatchSetApproval input) { - return input.getAccountId().equals(rsrc.getAccount().getId()); + return input.getAccountId().equals(rsrc.getUser().getAccountId()); } }); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java index 28f397c6a2..8c41be8df0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java @@ -27,7 +27,7 @@ public class GetReviewer implements RestReadView { } @Override - public Object apply(ReviewerResource reviewerResource) throws OrmException { - return json.format(reviewerResource); + public Object apply(ReviewerResource rsrc) throws OrmException { + return json.format(rsrc); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java index 1c68e9492e..48c054adb6 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java @@ -32,20 +32,23 @@ class ListReviewers implements RestReadView { private final AccountCache accountCache; private final Provider dbProvider; private final ReviewerJson json; + private final ReviewerResource.Factory resourceFactory; @Inject ListReviewers(AccountCache accountCache, Provider dbProvider, + ReviewerResource.Factory resourceFactory, ReviewerJson json) { this.accountCache = accountCache; this.dbProvider = dbProvider; + this.resourceFactory = resourceFactory; this.json = json; } @Override public Object apply(ChangeResource rsrc) throws BadRequestException, OrmException { - Map reviewers = Maps.newLinkedHashMap(); + Map reviewers = Maps.newLinkedHashMap(); ReviewDb db = dbProvider.get(); Change.Id changeId = rsrc.getChange().getId(); for (PatchSetApproval patchSetApproval @@ -53,10 +56,9 @@ class ListReviewers implements RestReadView { Account.Id accountId = patchSetApproval.getAccountId(); if (!reviewers.containsKey(accountId)) { Account account = accountCache.get(accountId).getAccount(); - reviewers.put(accountId, - json.format(new ReviewerResource(rsrc, account))); + reviewers.put(accountId, resourceFactory.create(rsrc, account)); } } - return reviewers.values(); + return json.format(reviewers.values()); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java index 6586725e78..b00b3d278e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java @@ -71,6 +71,7 @@ public class Module extends RestApiModule { install(new FactoryModule() { @Override protected void configure() { + factory(ReviewerResource.Factory.class); factory(AccountInfo.Loader.Factory.class); factory(EmailReviewComments.Factory.class); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerJson.java index d4743865cb..9479e67a99 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerJson.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerJson.java @@ -14,25 +14,104 @@ package com.google.gerrit.server.change; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gerrit.common.data.ApprovalType; +import com.google.gerrit.common.data.ApprovalTypes; +import com.google.gerrit.common.data.PermissionRange; import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.ApprovalCategoryValue; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.PatchSetApproval; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.project.ChangeControl; +import com.google.gerrit.server.workflow.CategoryFunction; +import com.google.gerrit.server.workflow.FunctionState; +import com.google.gwtorm.server.OrmException; +import com.google.inject.Inject; +import com.google.inject.Provider; + +import java.util.Collection; +import java.util.List; +import java.util.Map; public class ReviewerJson { - ReviewerJson() { + private final Provider db; + private final ApprovalTypes approvalTypes; + private final FunctionState.Factory functionState; + private final AccountInfo.Loader.Factory accountLoaderFactory; + + @Inject + ReviewerJson(Provider db, + ApprovalTypes approvalTypes, + FunctionState.Factory functionState, + AccountInfo.Loader.Factory accountLoaderFactory) { + this.db = db; + this.approvalTypes = approvalTypes; + this.functionState = functionState; + this.accountLoaderFactory = accountLoaderFactory; } - public ReviewerInfo format(ReviewerResource reviewerResource) { - ReviewerInfo reviewerInfo = new ReviewerInfo(); - Account account = reviewerResource.getAccount(); - reviewerInfo.id = account.getId().toString(); - reviewerInfo.email = account.getPreferredEmail(); - reviewerInfo.name = account.getFullName(); - return reviewerInfo; + public List format(Collection rsrcs) throws OrmException { + List infos = Lists.newArrayListWithCapacity(rsrcs.size()); + AccountInfo.Loader loader = accountLoaderFactory.create(true); + for (ReviewerResource rsrc : rsrcs) { + ReviewerInfo info = formatOne(rsrc); + loader.put(info); + infos.add(info); + } + loader.fill(); + return infos; } - public static class ReviewerInfo { + public List format(ReviewerResource rsrc) throws OrmException { + return format(ImmutableList. of(rsrc)); + } + + private ReviewerInfo formatOne(ReviewerResource rsrc) throws OrmException { + Account.Id id = rsrc.getUser().getAccountId(); + ReviewerInfo out = new ReviewerInfo(id); + + Change change = rsrc.getChange(); + PatchSet.Id psId = change.currentPatchSetId(); + + List approvals = db.get().patchSetApprovals() + .byPatchSetUser(psId, id).toList(); + + ChangeControl control = rsrc.getControl().forUser(rsrc.getUser()); + FunctionState fs = functionState.create(control, psId, approvals); + for (ApprovalType at : approvalTypes.getApprovalTypes()) { + CategoryFunction.forCategory(at.getCategory()).run(at, fs); + } + + out.approvals = Maps.newHashMapWithExpectedSize(approvals.size()); + for (PatchSetApproval ca : approvals) { + for (PermissionRange pr : control.getLabelRanges()) { + if (pr.getMin() != 0 || pr.getMax() != 0) { + // TODO: Support arbitrary labels. + ApprovalType at = approvalTypes.byId(ca.getCategoryId()); + if (at != null) { + out.approvals.put(at.getCategory().getLabelName(), + ApprovalCategoryValue.formatValue(ca.getValue())); + } + } + } + } + if (out.approvals.isEmpty()) { + out.approvals = null; + } + + return out; + } + + public static class ReviewerInfo extends AccountInfo { final String kind = "gerritcodereview#reviewer"; - String id; - String email; - String name; + Map approvals; + + protected ReviewerInfo(Account.Id id) { + super(id); + } } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerResource.java index e93c1754b3..23fba4720f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ReviewerResource.java @@ -16,20 +16,37 @@ package com.google.gerrit.server.change; import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.server.IdentifiedUser; import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; public class ReviewerResource extends ChangeResource { public static final TypeLiteral> REVIEWER_KIND = new TypeLiteral>() {}; - private final Account account; - - public ReviewerResource(ChangeResource changeResource, Account account) { - super(changeResource); - this.account = account; + static interface Factory { + ReviewerResource create(ChangeResource rsrc, IdentifiedUser user); + ReviewerResource create(ChangeResource rsrc, Account account); } - public Account getAccount() { - return account; + private final IdentifiedUser user; + + @AssistedInject + ReviewerResource(@Assisted ChangeResource rsrc, + @Assisted IdentifiedUser user) { + super(rsrc); + this.user = user; + } + + @AssistedInject + ReviewerResource(IdentifiedUser.GenericFactory userFactory, + @Assisted ChangeResource rsrc, + @Assisted Account account) { + this(rsrc, userFactory.create(account.getId())); + } + + public IdentifiedUser getUser() { + return user; } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewers.java index 267f357c65..ba91da3c5d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewers.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewers.java @@ -38,15 +38,18 @@ public class Reviewers implements ChildCollection { private final DynamicMap> views; private final Provider dbProvider; + private final ReviewerResource.Factory resourceFactory; private final AccountCache accountCache; private final Provider list; @Inject Reviewers(Provider dbProvider, - DynamicMap> views, - AccountCache accountCache, - Provider list) { + ReviewerResource.Factory resourceFactory, + DynamicMap> views, + AccountCache accountCache, + Provider list) { this.dbProvider = dbProvider; + this.resourceFactory = resourceFactory; this.views = views; this.accountCache = accountCache; this.list = list; @@ -69,7 +72,7 @@ public class Reviewers implements if (id.equals("self")) { CurrentUser user = rsrc.getControl().getCurrentUser(); if (user instanceof IdentifiedUser) { - accountId = ((IdentifiedUser)user).getAccountId(); + accountId = ((IdentifiedUser) user).getAccountId(); } else if (user instanceof AnonymousUser) { throw new AuthException("Authentication required"); } else { @@ -84,7 +87,7 @@ public class Reviewers implements // See if the id exists as a reviewer for this change if (fetchAccountIds(rsrc).contains(accountId)) { Account account = accountCache.get(accountId).getAccount(); - return new ReviewerResource(rsrc, account); + return resourceFactory.create(rsrc, account); } throw new ResourceNotFoundException(id); }