Line data Source code
1 : // Copyright (C) 2011 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 static com.google.common.collect.ImmutableList.toImmutableList; 18 : 19 : import com.google.common.collect.ImmutableList; 20 : import java.util.Collection; 21 : import java.util.List; 22 : import java.util.Objects; 23 : 24 : /** Describes the state and edits required to submit a change. */ 25 104 : public class SubmitRecord { 26 : public static boolean allRecordsOK(Collection<SubmitRecord> in) { 27 1 : if (in == null || in.isEmpty()) { 28 : // If the list is null or empty, it means that this Gerrit installation does not 29 : // have any form of validation rules. 30 : // Hence, the permission system should be used to determine if the change can be merged 31 : // or not. 32 1 : return true; 33 : } 34 : 35 : // The change can be submitted, unless at least one plugin prevents it. 36 1 : return in.stream().map(SubmitRecord::status).allMatch(SubmitRecord.Status::allowsSubmission); 37 : } 38 : 39 104 : public enum Status { 40 : // NOTE: These values are persisted in the index, so deleting or changing 41 : // the name of any values requires a schema upgrade. 42 : 43 : /** The change is ready for submission. */ 44 104 : OK, 45 : 46 : /** Something is preventing this change from being submitted. */ 47 104 : NOT_READY, 48 : 49 : /** The change has been closed. */ 50 104 : CLOSED, 51 : 52 : /** The change was submitted bypassing submit rules. */ 53 104 : FORCED, 54 : 55 : /** 56 : * A rule error caused by user misconfiguration. 57 : * 58 : * <p>This status should only be used to signal that the user has misconfigured the submit rule. 59 : * In case plugins encounter server exceptions while evaluating the rule, they should throw a 60 : * {@link RuntimeException} such as {@link IllegalStateException}. 61 : * 62 : * <p>Additional detail may be available in {@link SubmitRecord#errorMessage}. 63 : */ 64 104 : RULE_ERROR; 65 : 66 : private boolean allowsSubmission() { 67 1 : return this == OK || this == FORCED; 68 : } 69 : } 70 : 71 : // Name of the rule that created this submit record, formatted as '$pluginName~$ruleName' 72 : public String ruleName; 73 : public SubmitRecord.Status status; 74 : public List<Label> labels; 75 : public List<LegacySubmitRequirement> requirements; 76 : public String errorMessage; 77 : 78 104 : public static class Label { 79 104 : public enum Status { 80 : // NOTE: These values are persisted in the index, so deleting or changing 81 : // the name of any values requires a schema upgrade. 82 : 83 : /** 84 : * This label provides what is necessary for submission. 85 : * 86 : * <p>If provided, {@link Label#appliedBy} describes the user account that applied this label 87 : * to the change. 88 : */ 89 104 : OK, 90 : 91 : /** 92 : * This label prevents the change from being submitted. 93 : * 94 : * <p>If provided, {@link Label#appliedBy} describes the user account that applied this label 95 : * to the change. 96 : */ 97 104 : REJECT, 98 : 99 : /** The label is required for submission, but has not been satisfied. */ 100 104 : NEED, 101 : 102 : /** 103 : * The label may be set, but it's neither necessary for submission nor does it block 104 : * submission if set. 105 : */ 106 104 : MAY, 107 : 108 : /** 109 : * The label is required for submission, but is impossible to complete. The likely cause is 110 : * access has not been granted correctly by the project owner or site administrator. 111 : */ 112 104 : IMPOSSIBLE 113 : } 114 : 115 : public String label; 116 : public Label.Status status; 117 : public Account.Id appliedBy; 118 : 119 : /** 120 : * Returns a new instance of {@link Label} that contains a new instance for each mutable field. 121 : */ 122 : public Label deepCopy() { 123 55 : Label copy = new Label(); 124 55 : copy.label = label; 125 55 : copy.status = status; 126 55 : copy.appliedBy = appliedBy; 127 55 : return copy; 128 : } 129 : 130 : @Override 131 : public String toString() { 132 16 : StringBuilder sb = new StringBuilder(); 133 16 : sb.append(label).append(": ").append(status); 134 16 : if (appliedBy != null) { 135 6 : sb.append(" by ").append(appliedBy); 136 : } 137 16 : return sb.toString(); 138 : } 139 : 140 : @Override 141 : public boolean equals(Object o) { 142 4 : if (o instanceof Label) { 143 4 : Label l = (Label) o; 144 4 : return Objects.equals(label, l.label) 145 4 : && Objects.equals(status, l.status) 146 4 : && Objects.equals(appliedBy, l.appliedBy); 147 : } 148 0 : return false; 149 : } 150 : 151 : @Override 152 : public int hashCode() { 153 0 : return Objects.hash(label, status, appliedBy); 154 : } 155 : } 156 : 157 : /** 158 : * Returns a new instance of {@link SubmitRecord} that contains a new instance for each mutable 159 : * field. 160 : */ 161 : public SubmitRecord deepCopy() { 162 55 : SubmitRecord copy = new SubmitRecord(); 163 55 : copy.ruleName = ruleName; 164 55 : copy.status = status; 165 55 : copy.errorMessage = errorMessage; 166 55 : if (labels != null) { 167 55 : copy.labels = labels.stream().map(Label::deepCopy).collect(toImmutableList()); 168 : } 169 55 : if (requirements != null) { 170 1 : copy.requirements = ImmutableList.copyOf(requirements); 171 : } 172 55 : return copy; 173 : } 174 : 175 : @Override 176 : public String toString() { 177 16 : StringBuilder sb = new StringBuilder(); 178 16 : sb.append(status); 179 16 : if (status == Status.RULE_ERROR && errorMessage != null) { 180 0 : sb.append('(').append(errorMessage).append(')'); 181 : } 182 16 : sb.append('['); 183 16 : if (labels != null) { 184 16 : String delimiter = ""; 185 16 : for (Label label : labels) { 186 16 : sb.append(delimiter).append(label); 187 16 : delimiter = ", "; 188 16 : } 189 : } 190 16 : sb.append("],["); 191 16 : if (requirements != null) { 192 0 : String delimiter = ""; 193 0 : for (LegacySubmitRequirement requirement : requirements) { 194 0 : sb.append(delimiter).append(requirement); 195 0 : delimiter = ", "; 196 0 : } 197 : } 198 16 : sb.append(']'); 199 16 : return sb.toString(); 200 : } 201 : 202 : @Override 203 : public boolean equals(Object o) { 204 4 : if (o instanceof SubmitRecord) { 205 4 : SubmitRecord r = (SubmitRecord) o; 206 4 : return Objects.equals(status, r.status) 207 4 : && Objects.equals(labels, r.labels) 208 4 : && Objects.equals(errorMessage, r.errorMessage) 209 4 : && Objects.equals(requirements, r.requirements); 210 : } 211 0 : return false; 212 : } 213 : 214 : @Override 215 : public int hashCode() { 216 0 : return Objects.hash(status, labels, errorMessage, requirements); 217 : } 218 : 219 : private Status status() { 220 1 : return status; 221 : } 222 : }