Move the workflow package to be strictly server side
We likely cannot invoke this on the client anymore, so move it all to be server side. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -37,10 +37,10 @@ import com.google.gerrit.client.reviewdb.RevId;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.client.rpc.NoSuchEntityException;
|
||||
import com.google.gerrit.client.workflow.CategoryFunction;
|
||||
import com.google.gerrit.client.workflow.FunctionState;
|
||||
import com.google.gerrit.server.BaseServiceImplementation.Action;
|
||||
import com.google.gerrit.server.BaseServiceImplementation.Failure;
|
||||
import com.google.gerrit.server.workflow.CategoryFunction;
|
||||
import com.google.gerrit.server.workflow.FunctionState;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@@ -25,9 +25,9 @@ import com.google.gerrit.client.reviewdb.PatchSet;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.client.rpc.NoSuchEntityException;
|
||||
import com.google.gerrit.client.workflow.CategoryFunction;
|
||||
import com.google.gerrit.client.workflow.FunctionState;
|
||||
import com.google.gerrit.git.MergeQueue;
|
||||
import com.google.gerrit.server.workflow.CategoryFunction;
|
||||
import com.google.gerrit.server.workflow.FunctionState;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
@@ -33,8 +33,6 @@ import com.google.gerrit.client.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.client.reviewdb.TrustedExternalId;
|
||||
import com.google.gerrit.client.reviewdb.SystemConfig.LoginType;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.client.workflow.NoOpFunction;
|
||||
import com.google.gerrit.client.workflow.SubmitFunction;
|
||||
import com.google.gerrit.git.MergeQueue;
|
||||
import com.google.gerrit.git.PushAllProjectsOp;
|
||||
import com.google.gerrit.git.PushQueue;
|
||||
@@ -42,6 +40,8 @@ import com.google.gerrit.git.WorkQueue;
|
||||
import com.google.gerrit.server.mail.EmailException;
|
||||
import com.google.gerrit.server.patch.DiffCacheEntryFactory;
|
||||
import com.google.gerrit.server.ssh.SshKeyCacheEntryFactory;
|
||||
import com.google.gerrit.server.workflow.NoOpFunction;
|
||||
import com.google.gerrit.server.workflow.SubmitFunction;
|
||||
import com.google.gwtjsonrpc.server.SignedToken;
|
||||
import com.google.gwtjsonrpc.server.XsrfException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
@@ -0,0 +1,100 @@
|
||||
// Copyright (C) 2008 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.server.workflow;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.ChangeApproval;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Function to control {@link ChangeApproval}s in an {@link ApprovalCategory}. */
|
||||
public abstract class CategoryFunction {
|
||||
private static Map<String, CategoryFunction> all =
|
||||
new HashMap<String, CategoryFunction>();
|
||||
static {
|
||||
all.put(SubmitFunction.NAME, new SubmitFunction());
|
||||
all.put(MaxWithBlock.NAME, new MaxWithBlock());
|
||||
all.put(NoOpFunction.NAME, new NoOpFunction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a function by category.
|
||||
*
|
||||
* @param category the category the function is for.
|
||||
* @return the function implementation; {@link NoOpFunction} if the function
|
||||
* is not known to Gerrit and thus cannot be executed.
|
||||
*/
|
||||
public static CategoryFunction forCategory(final ApprovalCategory category) {
|
||||
final CategoryFunction r = forName(category.getFunctionName());
|
||||
return r != null ? r : new NoOpFunction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a function by name.
|
||||
*
|
||||
* @param functionName the function's unique name.
|
||||
* @return the function implementation; null if the function is not known to
|
||||
* Gerrit and thus cannot be executed.
|
||||
*/
|
||||
public static CategoryFunction forName(final String functionName) {
|
||||
return all.get(functionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize ChangeApprovals and set the valid flag for this category.
|
||||
* <p>
|
||||
* Implementors should invoke:
|
||||
*
|
||||
* <pre>
|
||||
* state.valid(at, true);
|
||||
* </pre>
|
||||
* <p>
|
||||
* If the set of approvals from <code>state.getApprovals(at)</code> covers the
|
||||
* requirements for the function, indicating the category has been completed.
|
||||
* <p>
|
||||
* An example implementation which requires at least one positive and no
|
||||
* negatives might be:
|
||||
*
|
||||
* <pre>
|
||||
* boolean neg = false, pos = false;
|
||||
* for (final ChangeApproval ca : state.getApprovals(at)) {
|
||||
* state.normalize(ca);
|
||||
* neg |= ca.getValue() < 0;
|
||||
* pos |= ca.getValue() > 0;
|
||||
* }
|
||||
* state.valid(at, !neg && pos);
|
||||
* </pre>
|
||||
*
|
||||
* @param at the cached category description to process.
|
||||
* @param state state to read approvals and project rights from, and to update
|
||||
* the valid status into.
|
||||
*/
|
||||
public abstract void run(ApprovalType at, FunctionState state);
|
||||
|
||||
public boolean isValid(final Account.Id accountId, final ApprovalType at,
|
||||
final FunctionState state) {
|
||||
for (final ProjectRight pr : state.getAllRights(at)) {
|
||||
if (state.isMember(accountId, pr.getAccountGroupId())
|
||||
&& (pr.getMinValue() < 0 || pr.getMaxValue() > 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2008 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.server.workflow;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategoryValue;
|
||||
import com.google.gerrit.client.reviewdb.Change;
|
||||
import com.google.gerrit.client.reviewdb.ChangeApproval;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory.Id;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/** State passed through to a {@link CategoryFunction}. */
|
||||
public class FunctionState {
|
||||
private final Map<Account.Id, Set<AccountGroup.Id>> groupCache =
|
||||
new HashMap<Account.Id, Set<AccountGroup.Id>>();
|
||||
private final Map<ApprovalCategory.Id, Collection<ChangeApproval>> approvals =
|
||||
new HashMap<ApprovalCategory.Id, Collection<ChangeApproval>>();
|
||||
private final Map<ApprovalCategory.Id, Boolean> valid =
|
||||
new HashMap<ApprovalCategory.Id, Boolean>();
|
||||
private final Change change;
|
||||
private final ProjectCache.Entry project;
|
||||
private final Map<ApprovalCategory.Id, Collection<ProjectRight>> allRights =
|
||||
new HashMap<ApprovalCategory.Id, Collection<ProjectRight>>();
|
||||
private Map<ApprovalCategory.Id, Collection<ProjectRight>> projectRights;
|
||||
private Map<ApprovalCategory.Id, Collection<ProjectRight>> wildcardRights;
|
||||
private Set<ChangeApproval> modified;
|
||||
|
||||
public FunctionState(final Change c, final Collection<ChangeApproval> all) {
|
||||
change = c;
|
||||
project = Common.getProjectCache().get(change.getDest().getParentKey());
|
||||
|
||||
for (final ChangeApproval ca : all) {
|
||||
Collection<ChangeApproval> l = approvals.get(ca.getCategoryId());
|
||||
if (l == null) {
|
||||
l = new ArrayList<ChangeApproval>();
|
||||
approvals.put(ca.getCategoryId(), l);
|
||||
}
|
||||
l.add(ca);
|
||||
}
|
||||
}
|
||||
|
||||
public Change getChange() {
|
||||
return change;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return project.getProject();
|
||||
}
|
||||
|
||||
public void valid(final ApprovalType at, final boolean v) {
|
||||
valid.put(id(at), v);
|
||||
}
|
||||
|
||||
public boolean isValid(final ApprovalType at) {
|
||||
return isValid(id(at));
|
||||
}
|
||||
|
||||
public boolean isValid(final ApprovalCategory.Id id) {
|
||||
final Boolean b = valid.get(id);
|
||||
return b != null && b;
|
||||
}
|
||||
|
||||
public Collection<ChangeApproval> getApprovals(final ApprovalType at) {
|
||||
return getApprovals(id(at));
|
||||
}
|
||||
|
||||
public Collection<ChangeApproval> getApprovals(final ApprovalCategory.Id id) {
|
||||
final Collection<ChangeApproval> l = approvals.get(id);
|
||||
return l != null ? l : Collections.<ChangeApproval> emptySet();
|
||||
}
|
||||
|
||||
public void dirty(final ChangeApproval ap) {
|
||||
if (modified == null) {
|
||||
modified = new HashSet<ChangeApproval>();
|
||||
}
|
||||
modified.add(ap);
|
||||
}
|
||||
|
||||
public Collection<ChangeApproval> getDirtyChangeApprovals() {
|
||||
if (modified != null) {
|
||||
return modified;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getProjectRights(final ApprovalType at) {
|
||||
return getProjectRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getProjectRights(final ApprovalCategory.Id id) {
|
||||
if (projectRights == null) {
|
||||
projectRights = index(project.getRights());
|
||||
}
|
||||
final Collection<ProjectRight> l = projectRights.get(id);
|
||||
return l != null ? l : Collections.<ProjectRight> emptySet();
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getWildcardRights(final ApprovalType at) {
|
||||
return getWildcardRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getWildcardRights(final ApprovalCategory.Id id) {
|
||||
if (wildcardRights == null) {
|
||||
wildcardRights = index(Common.getProjectCache().getWildcardRights());
|
||||
}
|
||||
final Collection<ProjectRight> l = wildcardRights.get(id);
|
||||
return l != null ? l : Collections.<ProjectRight> emptySet();
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getAllRights(final ApprovalType at) {
|
||||
return getAllRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<ProjectRight> getAllRights(final ApprovalCategory.Id id) {
|
||||
Collection<ProjectRight> l = allRights.get(id);
|
||||
if (l == null) {
|
||||
l = new ArrayList<ProjectRight>();
|
||||
l.addAll(getProjectRights(id));
|
||||
l.addAll(getWildcardRights(id));
|
||||
l = Collections.unmodifiableCollection(l);
|
||||
allRights.put(id, l);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
private static Map<Id, Collection<ProjectRight>> index(
|
||||
final Collection<ProjectRight> rights) {
|
||||
final HashMap<ApprovalCategory.Id, Collection<ProjectRight>> r;
|
||||
|
||||
r = new HashMap<ApprovalCategory.Id, Collection<ProjectRight>>();
|
||||
for (final ProjectRight pr : rights) {
|
||||
Collection<ProjectRight> l = r.get(pr.getApprovalCategoryId());
|
||||
if (l == null) {
|
||||
l = new ArrayList<ProjectRight>();
|
||||
r.put(pr.getApprovalCategoryId(), l);
|
||||
}
|
||||
l.add(pr);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public boolean isMember(final ChangeApproval ca, final ProjectRight r) {
|
||||
return isMember(ca.getAccountId(), r.getAccountGroupId());
|
||||
}
|
||||
|
||||
public boolean isMember(final Account.Id accountId,
|
||||
final AccountGroup.Id groupId) {
|
||||
return getGroups(accountId).contains(groupId);
|
||||
}
|
||||
|
||||
public Set<AccountGroup.Id> getGroups(final Account.Id id) {
|
||||
Set<AccountGroup.Id> g = groupCache.get(id);
|
||||
if (g == null) {
|
||||
g = Common.getGroupCache().getEffectiveGroups(id);
|
||||
groupCache.put(id, g);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the approval record down to the range permitted by the type, in
|
||||
* case the type was modified since the approval was originally granted.
|
||||
* <p>
|
||||
* If the record's value was modified, its automatically marked as dirty.
|
||||
*/
|
||||
public void applyTypeFloor(final ApprovalType at, final ChangeApproval a) {
|
||||
final ApprovalCategoryValue atMin = at.getMin();
|
||||
|
||||
if (atMin != null && a.getValue() < atMin.getValue()) {
|
||||
a.setValue(atMin.getValue());
|
||||
dirty(a);
|
||||
}
|
||||
|
||||
final ApprovalCategoryValue atMax = at.getMax();
|
||||
if (atMax != null && a.getValue() > atMax.getValue()) {
|
||||
a.setValue(atMax.getValue());
|
||||
dirty(a);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the approval record to be inside the maximum range permitted by
|
||||
* the ProjectRights granted to groups the account is a member of.
|
||||
* <p>
|
||||
* If multiple ProjectRights are matched (assigned to different groups the
|
||||
* account is a member of) the lowest minValue and the highest maxValue of the
|
||||
* union of them is used.
|
||||
* <p>
|
||||
* If the record's value was modified, its automatically marked as dirty.
|
||||
*/
|
||||
public void applyRightFloor(final ChangeApproval a) {
|
||||
// Find the maximal range actually granted to the user.
|
||||
//
|
||||
short minAllowed = 0, maxAllowed = 0;
|
||||
for (final ProjectRight r : getAllRights(a.getCategoryId())) {
|
||||
if (isMember(a, r)) {
|
||||
minAllowed = (short) Math.min(minAllowed, r.getMinValue());
|
||||
maxAllowed = (short) Math.max(maxAllowed, r.getMaxValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the value into that range, returning true if we changed
|
||||
// the value.
|
||||
//
|
||||
if (a.getValue() < minAllowed) {
|
||||
a.setValue(minAllowed);
|
||||
dirty(a);
|
||||
|
||||
} else if (a.getValue() > maxAllowed) {
|
||||
a.setValue(maxAllowed);
|
||||
dirty(a);
|
||||
}
|
||||
}
|
||||
|
||||
/** Run <code>applyTypeFloor</code>, <code>applyRightFloor</code>. */
|
||||
public void normalize(final ApprovalType at, final ChangeApproval ca) {
|
||||
applyTypeFloor(at, ca);
|
||||
applyRightFloor(ca);
|
||||
}
|
||||
|
||||
private static Id id(final ApprovalType at) {
|
||||
return at.getCategory().getId();
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2008 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.server.workflow;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.ChangeApproval;
|
||||
|
||||
/**
|
||||
* Computes an {@link ApprovalCategory} by looking at maximum values.
|
||||
* <p>
|
||||
* In order to be considered "approved" this function requires that:
|
||||
* <ul>
|
||||
* <li>The maximum negative value is never used;</li>
|
||||
* <li>The maximum positive value is used at least once;</li>
|
||||
* <li>The user approving the maximum positive has been granted that.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This function is primarily useful for review fields, with values such as:
|
||||
* <ul>
|
||||
* <li>+2: Approved change.</li>
|
||||
* <li>+1: Looks ok, but get another approval from someone with more depth.</li>
|
||||
* <li>-1: Soft reject, it isn't a great change but its OK if approved.</li>
|
||||
* <li>-2: Rejected, must not be submitted.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note that projects using this function would typically want to assign out the
|
||||
* middle range (-1 .. +1) to almost everyone, so people can indicate how they
|
||||
* feel about a change, but the extremes of -2 and +2 should be reserved for the
|
||||
* project's long-term maintainers, those who are most familiar with its code.
|
||||
*/
|
||||
public class MaxWithBlock extends CategoryFunction {
|
||||
public static String NAME = "MaxWithBlock";
|
||||
|
||||
@Override
|
||||
public void run(final ApprovalType at, final FunctionState state) {
|
||||
boolean rejected = false;
|
||||
boolean passed = false;
|
||||
for (final ChangeApproval a : state.getApprovals(at)) {
|
||||
state.normalize(at, a);
|
||||
|
||||
rejected |= at.isMaxNegative(a);
|
||||
passed |= at.isMaxPositive(a);
|
||||
}
|
||||
|
||||
// The type must not have had its max negative (a forceful reject)
|
||||
// and must have at least one max positive (a full accept).
|
||||
//
|
||||
state.valid(at, !rejected && passed);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2008 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.server.workflow;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
|
||||
/** A function that does nothing. */
|
||||
public class NoOpFunction extends CategoryFunction {
|
||||
public static String NAME = "NoOp";
|
||||
|
||||
@Override
|
||||
public void run(final ApprovalType at, final FunctionState state) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final Account.Id accountId, final ApprovalType at,
|
||||
final FunctionState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2008 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.server.workflow;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.Change;
|
||||
import com.google.gerrit.client.reviewdb.ProjectRight;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
|
||||
/**
|
||||
* Computes if the submit function can be used.
|
||||
* <p>
|
||||
* In order to be considered "approved" this function requires that all approval
|
||||
* categories with a position >= 0 (that is any whose
|
||||
* {@link ApprovalCategory#isAction()} method returns false) is valid and that
|
||||
* the change state be {@link Change.Status#NEW}.
|
||||
* <p>
|
||||
* This is mostly useful for actions, like {@link ApprovalCategory#SUBMIT}.
|
||||
*/
|
||||
public class SubmitFunction extends CategoryFunction {
|
||||
public static String NAME = "Submit";
|
||||
|
||||
@Override
|
||||
public void run(final ApprovalType at, final FunctionState state) {
|
||||
state.valid(at, valid(at, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final Account.Id accountId, final ApprovalType at,
|
||||
final FunctionState state) {
|
||||
if (valid(at, state)) {
|
||||
for (final ProjectRight pr : state.getAllRights(at)) {
|
||||
if (state.isMember(accountId, pr.getAccountGroupId())
|
||||
&& pr.getMaxValue() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean valid(final ApprovalType at, final FunctionState state) {
|
||||
if (state.getChange().getStatus() != Change.Status.NEW) {
|
||||
return false;
|
||||
}
|
||||
for (final ApprovalType t : Common.getGerritConfig().getApprovalTypes()) {
|
||||
if (!state.isValid(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user