Line data Source code
1 : // Copyright (C) 2012 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.change; 16 : 17 : import static com.google.gerrit.entities.LabelValue.formatValue; 18 : 19 : import com.google.common.collect.ImmutableList; 20 : import com.google.common.collect.Lists; 21 : import com.google.gerrit.entities.Account; 22 : import com.google.gerrit.entities.Address; 23 : import com.google.gerrit.entities.LabelType; 24 : import com.google.gerrit.entities.LabelTypes; 25 : import com.google.gerrit.entities.PatchSet; 26 : import com.google.gerrit.entities.PatchSetApproval; 27 : import com.google.gerrit.entities.SubmitRecord; 28 : import com.google.gerrit.extensions.api.changes.ReviewerInfo; 29 : import com.google.gerrit.server.account.AccountLoader; 30 : import com.google.gerrit.server.approval.ApprovalsUtil; 31 : import com.google.gerrit.server.permissions.LabelPermission; 32 : import com.google.gerrit.server.permissions.PermissionBackend; 33 : import com.google.gerrit.server.permissions.PermissionBackendException; 34 : import com.google.gerrit.server.project.SubmitRuleOptions; 35 : import com.google.gerrit.server.query.change.ChangeData; 36 : import com.google.inject.Inject; 37 : import com.google.inject.Singleton; 38 : import java.util.Collection; 39 : import java.util.List; 40 : import java.util.Optional; 41 : import java.util.TreeMap; 42 : 43 : @Singleton 44 : public class ReviewerJson { 45 : private final PermissionBackend permissionBackend; 46 : private final ChangeData.Factory changeDataFactory; 47 : private final ApprovalsUtil approvalsUtil; 48 : private final AccountLoader.Factory accountLoaderFactory; 49 : 50 : @Inject 51 : ReviewerJson( 52 : PermissionBackend permissionBackend, 53 : ChangeData.Factory changeDataFactory, 54 : ApprovalsUtil approvalsUtil, 55 146 : AccountLoader.Factory accountLoaderFactory) { 56 146 : this.permissionBackend = permissionBackend; 57 146 : this.changeDataFactory = changeDataFactory; 58 146 : this.approvalsUtil = approvalsUtil; 59 146 : this.accountLoaderFactory = accountLoaderFactory; 60 146 : } 61 : 62 : public List<ReviewerInfo> format(Collection<ReviewerResource> rsrcs) 63 : throws PermissionBackendException { 64 4 : List<ReviewerInfo> infos = Lists.newArrayListWithCapacity(rsrcs.size()); 65 4 : AccountLoader loader = accountLoaderFactory.create(true); 66 4 : ChangeData cd = null; 67 4 : for (ReviewerResource rsrc : rsrcs) { 68 4 : if (cd == null || !cd.getId().equals(rsrc.getChangeId())) { 69 4 : cd = changeDataFactory.create(rsrc.getChangeResource().getNotes()); 70 : } 71 : ReviewerInfo info; 72 4 : if (rsrc.isByEmail()) { 73 1 : Address address = rsrc.getReviewerByEmail(); 74 1 : info = ReviewerInfo.byEmail(address.name(), address.email()); 75 1 : } else { 76 3 : Account.Id reviewerAccountId = rsrc.getReviewerUser().getAccountId(); 77 3 : info = format(new ReviewerInfo(reviewerAccountId.get()), reviewerAccountId, cd); 78 3 : loader.put(info); 79 : } 80 4 : infos.add(info); 81 4 : } 82 4 : loader.fill(); 83 4 : return infos; 84 : } 85 : 86 : public List<ReviewerInfo> format(ReviewerResource rsrc) throws PermissionBackendException { 87 1 : return format(ImmutableList.of(rsrc)); 88 : } 89 : 90 : public ReviewerInfo format(ReviewerInfo out, Account.Id reviewerAccountId, ChangeData cd) 91 : throws PermissionBackendException { 92 13 : PatchSet.Id psId = cd.change().currentPatchSetId(); 93 13 : return format( 94 : out, 95 : reviewerAccountId, 96 : cd, 97 13 : approvalsUtil.byPatchSetUser(cd.notes(), psId, reviewerAccountId)); 98 : } 99 : 100 : public ReviewerInfo format( 101 : ReviewerInfo out, 102 : Account.Id reviewerAccountId, 103 : ChangeData cd, 104 : Iterable<PatchSetApproval> approvals) 105 : throws PermissionBackendException { 106 30 : LabelTypes labelTypes = cd.getLabelTypes(); 107 : 108 30 : out.approvals = new TreeMap<>(labelTypes.nameComparator()); 109 30 : for (PatchSetApproval ca : approvals) { 110 30 : Optional<LabelType> at = labelTypes.byLabel(ca.labelId()); 111 30 : at.ifPresent(lt -> out.approvals.put(lt.getName(), formatValue(ca.value()))); 112 30 : } 113 : 114 : // Add dummy approvals for all permitted labels for the user even if they 115 : // do not exist in the DB. 116 30 : PatchSet ps = cd.currentPatchSet(); 117 30 : if (ps != null) { 118 30 : PermissionBackend.ForChange perm = permissionBackend.absentUser(reviewerAccountId).change(cd); 119 : 120 30 : for (SubmitRecord rec : cd.submitRecords(SubmitRuleOptions.defaults())) { 121 30 : if (rec.labels == null) { 122 0 : continue; 123 : } 124 30 : for (SubmitRecord.Label label : rec.labels) { 125 30 : String name = label.label; 126 30 : Optional<LabelType> type = labelTypes.byLabel(name); 127 30 : if (out.approvals.containsKey(name) || !type.isPresent()) { 128 0 : continue; 129 : } 130 : 131 18 : if (perm.test(new LabelPermission(type.get()))) { 132 18 : out.approvals.put(name, formatValue((short) 0)); 133 : } 134 18 : } 135 30 : } 136 : } 137 : 138 30 : if (out.approvals.isEmpty()) { 139 0 : out.approvals = null; 140 : } 141 : 142 30 : return out; 143 : } 144 : }