ListBranches: Use FluentIterable for filter, start, and limit

Factor out predicates and refactor for better readability.

Change-Id: I2fdded5cabc455d4a866b2f8befd361f2cffe611
This commit is contained in:
Dave Borowitz
2015-03-17 14:03:10 -07:00
parent 660f3b4c70
commit 18a8ce9b5e

View File

@@ -15,9 +15,8 @@
package com.google.gerrit.server.project; package com.google.gerrit.server.project;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.gerrit.extensions.common.ActionInfo; import com.google.gerrit.extensions.common.ActionInfo;
import com.google.gerrit.extensions.common.WebLinkInfo; import com.google.gerrit.extensions.common.WebLinkInfo;
@@ -83,7 +82,7 @@ public class ListBranches implements RestReadView<ProjectResource> {
@Override @Override
public List<BranchInfo> apply(ProjectResource rsrc) public List<BranchInfo> apply(ProjectResource rsrc)
throws ResourceNotFoundException, IOException, BadRequestException { throws ResourceNotFoundException, IOException, BadRequestException {
List<BranchInfo> branches; List<BranchInfo> branchList;
BranchInfo headBranch = null; BranchInfo headBranch = null;
BranchInfo configBranch = null; BranchInfo configBranch = null;
@@ -102,7 +101,7 @@ public class ListBranches implements RestReadView<ProjectResource> {
} }
} }
branches = new ArrayList<>(refs.size()); branchList = new ArrayList<>(refs.size());
for (Ref ref : refs) { for (Ref ref : refs) {
if (ref.isSymbolic()) { if (ref.isSymbolic()) {
// A symbolic reference to another branch, instead of // A symbolic reference to another branch, instead of
@@ -123,7 +122,7 @@ public class ListBranches implements RestReadView<ProjectResource> {
headBranch = b; headBranch = b;
} else { } else {
b.setCanDelete(targetRefControl.canDelete()); b.setCanDelete(targetRefControl.canDelete());
branches.add(b); branchList.add(b);
} }
continue; continue;
} }
@@ -133,45 +132,34 @@ public class ListBranches implements RestReadView<ProjectResource> {
if (RefNames.REFS_CONFIG.equals(ref.getName())) { if (RefNames.REFS_CONFIG.equals(ref.getName())) {
configBranch = createBranchInfo(ref, refControl, targets); configBranch = createBranchInfo(ref, refControl, targets);
} else { } else {
branches.add(createBranchInfo(ref, refControl, targets)); branchList.add(createBranchInfo(ref, refControl, targets));
} }
} }
} }
} catch (RepositoryNotFoundException noGitRepository) { } catch (RepositoryNotFoundException noGitRepository) {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
Collections.sort(branches, new Comparator<BranchInfo>() { Collections.sort(branchList, new Comparator<BranchInfo>() {
@Override @Override
public int compare(BranchInfo a, BranchInfo b) { public int compare(BranchInfo a, BranchInfo b) {
return a.ref.compareTo(b.ref); return a.ref.compareTo(b.ref);
} }
}); });
if (configBranch != null) { if (configBranch != null) {
branches.add(0, configBranch); branchList.add(0, configBranch);
} }
if (headBranch != null) { if (headBranch != null) {
branches.add(0, headBranch); branchList.add(0, headBranch);
} }
List<BranchInfo> filteredBranches; FluentIterable<BranchInfo> branches = filterBranches(branchList);
if ((matchSubstring != null && !matchSubstring.isEmpty()) if (start > 0) {
|| (matchRegex != null && !matchRegex.isEmpty())) { branches = branches.skip(start);
filteredBranches = filterBranches(branches);
} else {
filteredBranches = branches;
} }
if (!filteredBranches.isEmpty()) { if (limit > 0) {
int end = filteredBranches.size(); branches = branches.limit(limit);
if (limit > 0 && start + limit < end) {
end = start + limit;
} }
if (start <= end) { return branches.toList();
filteredBranches = filteredBranches.subList(start, end);
} else {
filteredBranches = Collections.emptyList();
}
}
return filteredBranches;
} }
private static void addRef(Repository db, List<Ref> refs, String name) private static void addRef(Repository db, List<Ref> refs, String name)
@@ -182,38 +170,52 @@ public class ListBranches implements RestReadView<ProjectResource> {
} }
} }
private List<BranchInfo> filterBranches(List<BranchInfo> branches) private FluentIterable<BranchInfo> filterBranches(List<BranchInfo> branchList)
throws BadRequestException { throws BadRequestException {
if (matchSubstring != null) { FluentIterable<BranchInfo> branches = FluentIterable.from(branchList);
return Lists.newArrayList(Iterables.filter(branches, if (!Strings.isNullOrEmpty(matchSubstring)) {
new Predicate<BranchInfo>() { branches = branches.filter(new SubstringPredicate(matchSubstring));
@Override } else if (!Strings.isNullOrEmpty(matchRegex)) {
public boolean apply(BranchInfo in) { branches = branches.filter(new RegexPredicate(matchRegex));
if (!in.ref.startsWith(Constants.R_HEADS)){
return in.ref.toLowerCase(Locale.US).contains(
matchSubstring.toLowerCase(Locale.US));
} else {
return in.ref.substring(Constants.R_HEADS.length())
.toLowerCase(Locale.US)
.contains(matchSubstring.toLowerCase(Locale.US));
} }
}
}));
} else if (matchRegex != null) {
if (matchRegex.startsWith("^")) {
matchRegex = matchRegex.substring(1);
if (matchRegex.endsWith("$") && !matchRegex.endsWith("\\$")) {
matchRegex = matchRegex.substring(0, matchRegex.length() - 1);
}
}
if (matchRegex.equals(".*")) {
return branches; return branches;
} }
private static class SubstringPredicate implements Predicate<BranchInfo> {
private final String substring;
private SubstringPredicate(String substring) {
this.substring = substring.toLowerCase(Locale.US);
}
@Override
public boolean apply(BranchInfo in) {
String ref = in.ref;
if (ref.startsWith(Constants.R_HEADS)) {
ref = ref.substring(Constants.R_HEADS.length());
}
ref = ref.toLowerCase(Locale.US);
return ref.contains(substring);
}
}
private static class RegexPredicate implements Predicate<BranchInfo> {
private final RunAutomaton a;
private RegexPredicate(String regex) throws BadRequestException {
if (regex.startsWith("^")) {
regex = regex.substring(1);
if (regex.endsWith("$") && !regex.endsWith("\\$")) {
regex = regex.substring(0, regex.length() - 1);
}
}
try { try {
final RunAutomaton a = a = new RunAutomaton(new RegExp(regex).toAutomaton());
new RunAutomaton(new RegExp(matchRegex).toAutomaton()); } catch (IllegalArgumentException e) {
return Lists.newArrayList(Iterables.filter( throw new BadRequestException(e.getMessage());
branches, new Predicate<BranchInfo>() { }
}
@Override @Override
public boolean apply(BranchInfo in) { public boolean apply(BranchInfo in) {
if (!in.ref.startsWith(Constants.R_HEADS)){ if (!in.ref.startsWith(Constants.R_HEADS)){
@@ -222,12 +224,6 @@ public class ListBranches implements RestReadView<ProjectResource> {
return a.run(in.ref.substring(Constants.R_HEADS.length())); return a.run(in.ref.substring(Constants.R_HEADS.length()));
} }
} }
}));
} catch (IllegalArgumentException e) {
throw new BadRequestException(e.getMessage());
}
}
return branches;
} }
private BranchInfo createBranchInfo(Ref ref, RefControl refControl, private BranchInfo createBranchInfo(Ref ref, RefControl refControl,