Line data Source code
1 : // Copyright (C) 2017 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.entities; 16 : 17 : import com.google.gerrit.common.Nullable; 18 : import com.google.gerrit.entities.SubmitRecord.Label; 19 : import java.util.Collections; 20 : import java.util.LinkedHashMap; 21 : import java.util.Map; 22 : import java.util.Optional; 23 : 24 : /** 25 : * Functions for determining submittability based on label votes. 26 : * 27 : * <p>Only describes built-in label functions. Admins can extend the logic arbitrarily using Prolog 28 : * rules, in which case the choice of function in the project config is ignored. 29 : * 30 : * <p>Function semantics are documented in {@code config-labels.txt}, and actual behavior is 31 : * implemented both in Prolog in {@code gerrit_common.pl} and in the {@link #check} method. 32 : */ 33 154 : public enum LabelFunction { 34 154 : ANY_WITH_BLOCK("AnyWithBlock", true, false, false), 35 154 : MAX_WITH_BLOCK("MaxWithBlock", true, true, true), 36 154 : MAX_NO_BLOCK("MaxNoBlock", false, true, true), 37 154 : NO_BLOCK("NoBlock"), 38 154 : NO_OP("NoOp"), 39 154 : PATCH_SET_LOCK("PatchSetLock"); 40 : 41 : public static final Map<String, LabelFunction> ALL; 42 : 43 : static { 44 154 : Map<String, LabelFunction> all = new LinkedHashMap<>(); 45 154 : for (LabelFunction f : values()) { 46 154 : all.put(f.getFunctionName(), f); 47 : } 48 154 : ALL = Collections.unmodifiableMap(all); 49 154 : } 50 : 51 : public static Optional<LabelFunction> parse(@Nullable String str) { 52 151 : return Optional.ofNullable(ALL.get(str)); 53 : } 54 : 55 : private final String name; 56 : private final boolean isBlock; 57 : private final boolean isRequired; 58 : private final boolean requiresMaxValue; 59 : 60 : LabelFunction(String name) { 61 154 : this(name, false, false, false); 62 154 : } 63 : 64 154 : LabelFunction(String name, boolean isBlock, boolean isRequired, boolean requiresMaxValue) { 65 154 : this.name = name; 66 154 : this.isBlock = isBlock; 67 154 : this.isRequired = isRequired; 68 154 : this.requiresMaxValue = requiresMaxValue; 69 154 : } 70 : 71 : /** The function name as defined in documentation and {@code project.config}. */ 72 : public String getFunctionName() { 73 154 : return name; 74 : } 75 : 76 : /** Whether the label is a "block" label, meaning a minimum vote will prevent submission. */ 77 : public boolean isBlock() { 78 103 : return isBlock; 79 : } 80 : 81 : /** Whether the label is a mandatory label, meaning absence of votes will prevent submission. */ 82 : public boolean isRequired() { 83 3 : return isRequired; 84 : } 85 : 86 : /** Whether the label requires a vote with the maximum value to allow submission. */ 87 : public boolean isMaxValueRequired() { 88 0 : return requiresMaxValue; 89 : } 90 : 91 : public Label check(LabelType labelType, Iterable<PatchSetApproval> approvals) { 92 104 : Label submitRecordLabel = new Label(); 93 104 : submitRecordLabel.label = labelType.getName(); 94 : 95 104 : submitRecordLabel.status = SubmitRecord.Label.Status.MAY; 96 104 : if (isRequired) { 97 104 : submitRecordLabel.status = SubmitRecord.Label.Status.NEED; 98 : } 99 : 100 104 : for (PatchSetApproval a : approvals) { 101 58 : if (a.value() == 0) { 102 14 : continue; 103 : } 104 : 105 58 : if (isBlock && labelType.isMaxNegative(a)) { 106 20 : submitRecordLabel.appliedBy = a.accountId(); 107 20 : submitRecordLabel.status = SubmitRecord.Label.Status.REJECT; 108 20 : return submitRecordLabel; 109 : } 110 : 111 58 : if (labelType.isMaxPositive(a) || !requiresMaxValue) { 112 56 : submitRecordLabel.appliedBy = a.accountId(); 113 : 114 56 : submitRecordLabel.status = SubmitRecord.Label.Status.MAY; 115 56 : if (isRequired) { 116 56 : submitRecordLabel.status = SubmitRecord.Label.Status.OK; 117 : } 118 : } 119 58 : } 120 : 121 104 : return submitRecordLabel; 122 : } 123 : }