// Copyright (C) 2009 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.gerrit.httpd.rpc.changedetail; import com.google.gerrit.common.data.AccountInfoCache; import com.google.gerrit.common.data.ApprovalType; import com.google.gerrit.common.data.ApprovalTypes; import com.google.gerrit.common.data.PatchSetPublishDetail; import com.google.gerrit.httpd.rpc.Handler; import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.reviewdb.ApprovalCategory; import com.google.gerrit.reviewdb.ApprovalCategoryValue; import com.google.gerrit.reviewdb.Change; import com.google.gerrit.reviewdb.PatchLineComment; import com.google.gerrit.reviewdb.PatchSet; import com.google.gerrit.reviewdb.PatchSetApproval; import com.google.gerrit.reviewdb.PatchSetInfo; import com.google.gerrit.reviewdb.RefRight; import com.google.gerrit.reviewdb.ReviewDb; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.AccountInfoCacheFactory; import com.google.gerrit.server.patch.PatchSetInfoFactory; import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException; import com.google.gerrit.server.project.CanSubmitResult; import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectState; import com.google.gerrit.server.project.RefControl; import com.google.gwtorm.client.OrmException; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail> { interface Factory { PatchSetPublishDetailFactory create(PatchSet.Id patchSetId); } private final ProjectCache projectCache; private final PatchSetInfoFactory infoFactory; private final ApprovalTypes approvalTypes; private final ReviewDb db; private final ChangeControl.Factory changeControlFactory; private final AccountInfoCacheFactory aic; private final IdentifiedUser user; private final PatchSet.Id patchSetId; private AccountInfoCache accounts; private PatchSetInfo patchSetInfo; private Change change; private List<PatchLineComment> drafts; private Map<ApprovalCategory.Id, Set<ApprovalCategoryValue.Id>> allowed; private Map<ApprovalCategory.Id, PatchSetApproval> given; @Inject PatchSetPublishDetailFactory(final PatchSetInfoFactory infoFactory, final ProjectCache projectCache, final ApprovalTypes approvalTypes, final ReviewDb db, final AccountInfoCacheFactory.Factory accountInfoCacheFactory, final ChangeControl.Factory changeControlFactory, final IdentifiedUser user, @Assisted final PatchSet.Id patchSetId) { this.projectCache = projectCache; this.infoFactory = infoFactory; this.approvalTypes = approvalTypes; this.db = db; this.changeControlFactory = changeControlFactory; this.aic = accountInfoCacheFactory.create(); this.user = user; this.patchSetId = patchSetId; } @Override public PatchSetPublishDetail call() throws OrmException, PatchSetInfoNotAvailableException, NoSuchChangeException { final Change.Id changeId = patchSetId.getParentKey(); final ChangeControl control = changeControlFactory.validateFor(changeId); change = control.getChange(); patchSetInfo = infoFactory.get(patchSetId); drafts = db.patchComments().draft(patchSetId, user.getAccountId()).toList(); allowed = new HashMap<ApprovalCategory.Id, Set<ApprovalCategoryValue.Id>>(); given = new HashMap<ApprovalCategory.Id, PatchSetApproval>(); if (change.getStatus().isOpen() && patchSetId.equals(change.currentPatchSetId())) { computeAllowed(); for (final PatchSetApproval a : db.patchSetApprovals().byPatchSetUser( patchSetId, user.getAccountId())) { given.put(a.getCategoryId(), a); } } aic.want(change.getOwner()); accounts = aic.create(); PatchSetPublishDetail detail = new PatchSetPublishDetail(); detail.setAccounts(accounts); detail.setPatchSetInfo(patchSetInfo); detail.setChange(change); detail.setDrafts(drafts); detail.setAllowed(allowed); detail.setGiven(given); final CanSubmitResult canSubmitResult = control.canSubmit(patchSetId); detail.setSubmitAllowed(canSubmitResult == CanSubmitResult.OK); return detail; } private void computeAllowed() { final Set<AccountGroup.Id> am = user.getEffectiveGroups(); final ProjectState pe = projectCache.get(change.getProject()); for (ApprovalCategory.Id category : approvalTypes.getApprovalCategories()) { RefControl rc = pe.controlFor(user).controlForRef(change.getDest()); List<RefRight> categoryRights = rc.getApplicableRights(category); computeAllowed(am, categoryRights, category); } } private void computeAllowed(final Set<AccountGroup.Id> am, final List<RefRight> list, ApprovalCategory.Id category) { Set<ApprovalCategoryValue.Id> s = allowed.get(category); if (s == null) { s = new HashSet<ApprovalCategoryValue.Id>(); allowed.put(category, s); } for (final RefRight r : list) { if (!am.contains(r.getAccountGroupId())) { continue; } final ApprovalType at = approvalTypes.getApprovalType(r.getApprovalCategoryId()); for (short m = r.getMinValue(); m <= r.getMaxValue(); m++) { final ApprovalCategoryValue v = at.getValue(m); if (v != null) { s.add(v.getId()); } } } } }