ChangeStatusPredicate: Prefix search for open/closed

Change-Id: I6d0bfbf3db1263b68d85359ad11f2f2f948c6db9
This commit is contained in:
Dave Borowitz
2014-09-09 15:23:44 +02:00
parent 419fe43131
commit 90b89d1dfe
3 changed files with 49 additions and 28 deletions

View File

@@ -59,7 +59,7 @@ public class BasicChangeRewrites extends QueryRewriter<ChangeData> {
@Rewrite("-status:merged")
public Predicate<ChangeData> r00_notMerged() {
return or(ChangeStatusPredicate.open(),
new ChangeStatusPredicate(Change.Status.ABANDONED));
ChangeStatusPredicate.forStatus(Change.Status.ABANDONED));
}
@SuppressWarnings("unchecked")
@@ -67,7 +67,7 @@ public class BasicChangeRewrites extends QueryRewriter<ChangeData> {
@Rewrite("-status:abandoned")
public Predicate<ChangeData> r00_notAbandoned() {
return or(ChangeStatusPredicate.open(),
new ChangeStatusPredicate(Change.Status.MERGED));
ChangeStatusPredicate.forStatus(Change.Status.MERGED));
}
@NoCostComputation

View File

@@ -37,13 +37,27 @@ import java.util.TreeMap;
* Status names are looked up by prefix case-insensitively.
*/
public final class ChangeStatusPredicate extends IndexPredicate<ChangeData> {
private static final TreeMap<String, Change.Status> VALUES;
private static final TreeMap<String, Predicate<ChangeData>> PREDICATES;
private static final Predicate<ChangeData> CLOSED;
private static final Predicate<ChangeData> OPEN;
static {
VALUES = new TreeMap<>();
PREDICATES = new TreeMap<>();
List<Predicate<ChangeData>> open = new ArrayList<>();
List<Predicate<ChangeData>> closed = new ArrayList<>();
for (Change.Status s : Change.Status.values()) {
VALUES.put(canonicalize(s), s);
ChangeStatusPredicate p = new ChangeStatusPredicate(s);
PREDICATES.put(canonicalize(s), p);
(s.isOpen() ? open : closed).add(p);
}
CLOSED = Predicate.or(closed);
OPEN = Predicate.or(open);
PREDICATES.put("closed", CLOSED);
PREDICATES.put("open", OPEN);
PREDICATES.put("pending", OPEN);
}
public static String canonicalize(Change.Status status) {
@@ -51,46 +65,35 @@ public final class ChangeStatusPredicate extends IndexPredicate<ChangeData> {
}
public static Predicate<ChangeData> parse(String value) {
if ("open".equalsIgnoreCase(value) || "pending".equalsIgnoreCase(value)) {
return open();
} else if ("closed".equalsIgnoreCase(value)) {
return closed();
}
String lower = value.toLowerCase();
NavigableMap<String, Change.Status> head = VALUES.tailMap(lower, true);
NavigableMap<String, Predicate<ChangeData>> head =
PREDICATES.tailMap(lower, true);
if (!head.isEmpty()) {
// Assume no statuses share a common prefix so we can only walk one entry.
Map.Entry<String, Change.Status> e = head.entrySet().iterator().next();
Map.Entry<String, Predicate<ChangeData>> e =
head.entrySet().iterator().next();
if (e.getKey().startsWith(lower)) {
return new ChangeStatusPredicate(e.getValue());
return e.getValue();
}
}
throw new IllegalArgumentException("invalid change status: " + value);
}
public static Predicate<ChangeData> forStatus(Change.Status status) {
return parse(status.name());
}
public static Predicate<ChangeData> open() {
List<Predicate<ChangeData>> r = new ArrayList<>(4);
for (final Change.Status e : Change.Status.values()) {
if (e.isOpen()) {
r.add(new ChangeStatusPredicate(e));
}
}
return r.size() == 1 ? r.get(0) : or(r);
return OPEN;
}
public static Predicate<ChangeData> closed() {
List<Predicate<ChangeData>> r = new ArrayList<>(4);
for (final Change.Status e : Change.Status.values()) {
if (e.isClosed()) {
r.add(new ChangeStatusPredicate(e));
}
}
return r.size() == 1 ? r.get(0) : or(r);
return CLOSED;
}
private final Change.Status status;
ChangeStatusPredicate(Change.Status status) {
private ChangeStatusPredicate(Change.Status status) {
super(ChangeField.STATUS, canonicalize(status));
this.status = status;
}