Delegate RefRight category filtering to ProjectState

Allow the ProjectState class to implement the filtering of each
RefRight instance by category, rather than repeating the logic
in the classes that use them.  This opens the door for the state
to cache the filtered collections at some later point in time,
and may help accelerate common action category lookups like for
READ or Push Branch.

Change-Id: I6ddddd031afe59fc04c4226a01d656cca14277d0
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2010-04-20 18:30:58 -07:00
parent 93951e0e13
commit 4cade210a5
3 changed files with 54 additions and 17 deletions

View File

@@ -130,20 +130,18 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
final ProjectState pe = projectCache.get(change.getProject());
for (ApprovalCategory.Id category : approvalTypes.getApprovalCategories()) {
List<RefRight> categoryRights = new ArrayList<RefRight>();
categoryRights.addAll(filterMatching(pe.getLocalRights(), category));
categoryRights.addAll(filterMatching(pe.getInheritedRights(), category));
categoryRights.addAll(filterMatching(pe.getLocalRights(category)));
categoryRights.addAll(filterMatching(pe.getInheritedRights(category)));
Collections.sort(categoryRights, RefRight.REF_PATTERN_ORDER);
categoryRights = RefControl.filterMostSpecific(categoryRights);
computeAllowed(am, categoryRights, category);
}
}
private List<RefRight> filterMatching(Collection<RefRight> rights,
ApprovalCategory.Id category) {
private List<RefRight> filterMatching(Collection<RefRight> rights) {
List<RefRight> result = new ArrayList<RefRight>();
for (RefRight right : rights) {
if (RefControl.matches(change.getDest().get(), right.getRefPattern())
&& category.equals(right.getApprovalCategoryId())) {
if (RefControl.matches(change.getDest().get(), right.getRefPattern())) {
result.add(right);
}
}

View File

@@ -24,9 +24,11 @@ import com.google.gerrit.server.config.WildProjectName;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Cached information on a project. */
@@ -80,6 +82,16 @@ public class ProjectState {
return localRights;
}
/**
* Get the rights that pertain only to this project.
*
* @param action the category requested.
* @return immutable collection of rights for the requested category.
*/
public Collection<RefRight> getLocalRights(ApprovalCategory.Id action) {
return filter(getLocalRights(), action);
}
/** Get the rights this project inherits from the wild project. */
public Collection<RefRight> getInheritedRights() {
if (isSpecialWildProject()) {
@@ -88,6 +100,19 @@ public class ProjectState {
return inheritedRights.get();
}
/**
* Get the rights this project inherits from the wild project.
*
* @param action the category requested.
* @return immutable collection of rights for the requested category.
*/
public Collection<RefRight> getInheritedRights(ApprovalCategory.Id action) {
if (action.canInheritFromWildProject()) {
return filter(getInheritedRights(), action);
}
return Collections.emptyList();
}
/** Is this the special wild project which manages inherited rights? */
public boolean isSpecialWildProject() {
return project.getNameKey().equals(wildProject);
@@ -104,4 +129,21 @@ public class ProjectState {
public ProjectControl controlFor(final CurrentUser user) {
return new ProjectControl(user, this);
}
private static Collection<RefRight> filter(Collection<RefRight> all,
ApprovalCategory.Id actionId) {
if (all.isEmpty()) {
return Collections.emptyList();
}
final Collection<RefRight> mine = new ArrayList<RefRight>(all.size());
for (final RefRight right : all) {
if (right.getApprovalCategoryId().equals(actionId)) {
mine.add(right);
}
}
if (mine.isEmpty()) {
return Collections.emptyList();
}
return Collections.unmodifiableCollection(mine);
}
}

View File

@@ -273,16 +273,11 @@ public class RefControl {
}
private List<RefRight> getLocalRights(ApprovalCategory.Id actionId) {
return filter(projectControl.getProjectState().getLocalRights(), actionId);
return filter(getProjectState().getLocalRights(actionId));
}
private List<RefRight> getInheritedRights(ApprovalCategory.Id actionId) {
if (actionId.canInheritFromWildProject()) {
return filter(projectControl.getProjectState().getInheritedRights(),
actionId);
} else {
return Collections.emptyList();
}
return filter(getProjectState().getInheritedRights(actionId));
}
public List<RefRight> getAllRights(final ApprovalCategory.Id id) {
@@ -293,18 +288,20 @@ public class RefControl {
return Collections.unmodifiableList(RefControl.filterMostSpecific(l));
}
private List<RefRight> filter(Collection<RefRight> all,
ApprovalCategory.Id actionId) {
private List<RefRight> filter(Collection<RefRight> all) {
List<RefRight> mine = new ArrayList<RefRight>(all.size());
for (RefRight right : all) {
if (matches(getRefName(), right.getRefPattern())
&& right.getApprovalCategoryId().equals(actionId)) {
if (matches(getRefName(), right.getRefPattern())) {
mine.add(right);
}
}
return mine;
}
private ProjectState getProjectState() {
return projectControl.getProjectState();
}
public static boolean matches(String refName, String refPattern) {
if (refPattern.endsWith("/*")) {
String prefix = refPattern.substring(0, refPattern.length() - 1);