Line data Source code
1 : // Copyright (C) 2009 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.index.query; 16 : 17 : import static com.google.common.base.Preconditions.checkState; 18 : 19 : import java.util.ArrayList; 20 : import java.util.Arrays; 21 : import java.util.Collection; 22 : import java.util.Collections; 23 : import java.util.List; 24 : 25 : /** Requires one predicate to be true. */ 26 : public class OrPredicate<T> extends Predicate<T> implements Matchable<T> { 27 : private final List<Predicate<T>> children; 28 : private final int cost; 29 : 30 : @SafeVarargs 31 : protected OrPredicate(Predicate<T>... that) { 32 16 : this(Arrays.asList(that)); 33 16 : } 34 : 35 122 : protected OrPredicate(Collection<? extends Predicate<T>> that) { 36 122 : List<Predicate<T>> t = new ArrayList<>(that.size()); 37 122 : int c = 0; 38 122 : for (Predicate<T> p : that) { 39 122 : if (getClass() == p.getClass()) { 40 16 : for (Predicate<T> gp : p.getChildren()) { 41 16 : t.add(gp); 42 16 : c += gp.estimateCost(); 43 16 : } 44 : } else { 45 122 : t.add(p); 46 122 : c += p.estimateCost(); 47 : } 48 122 : } 49 122 : children = t; 50 122 : cost = c; 51 122 : } 52 : 53 : @Override 54 : public final List<Predicate<T>> getChildren() { 55 61 : return Collections.unmodifiableList(children); 56 : } 57 : 58 : @Override 59 : public final int getChildCount() { 60 41 : return children.size(); 61 : } 62 : 63 : @Override 64 : public final Predicate<T> getChild(int i) { 65 41 : return children.get(i); 66 : } 67 : 68 : @Override 69 : public Predicate<T> copy(Collection<? extends Predicate<T>> children) { 70 6 : return new OrPredicate<>(children); 71 : } 72 : 73 : @Override 74 : public boolean isMatchable() { 75 59 : for (Predicate<T> c : children) { 76 59 : if (!c.isMatchable()) { 77 1 : return false; 78 : } 79 59 : } 80 59 : return true; 81 : } 82 : 83 : @Override 84 : public boolean match(T object) { 85 58 : for (Predicate<T> c : children) { 86 58 : checkState( 87 58 : c.isMatchable(), 88 : "match invoked, but child predicate %s doesn't implement %s", 89 : c, 90 58 : Matchable.class.getName()); 91 58 : if (c.asMatchable().match(object)) { 92 53 : return true; 93 : } 94 49 : } 95 33 : return false; 96 : } 97 : 98 : @Override 99 : public int getCost() { 100 36 : return cost; 101 : } 102 : 103 : @Override 104 : public int hashCode() { 105 1 : return getChild(0).hashCode() * 31 + getChild(1).hashCode(); 106 : } 107 : 108 : // Suppress the EqualsGetClass warning as this is legacy code. 109 : @SuppressWarnings("EqualsGetClass") 110 : @Override 111 : public boolean equals(Object other) { 112 8 : if (other == null) { 113 0 : return false; 114 : } 115 8 : return getClass() == other.getClass() 116 8 : && getChildren().equals(((Predicate<?>) other).getChildren()); 117 : } 118 : 119 : @Override 120 : public String toString() { 121 14 : final StringBuilder r = new StringBuilder(); 122 14 : r.append("("); 123 14 : for (int i = 0; i < getChildCount(); i++) { 124 13 : if (i != 0) { 125 13 : r.append(" OR "); 126 : } 127 13 : r.append(getChild(i)); 128 : } 129 14 : r.append(")"); 130 14 : return r.toString(); 131 : } 132 : }