View Javadoc
1   package org.wikimedia.search.extra.util;
2   
3   import java.util.function.IntPredicate;
4   
5   import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
6   import lombok.EqualsAndHashCode;
7   
8   /**
9    * Int predicates that uses concrete classes to support hashCode/equals.
10   */
11  public abstract class ConcreteIntPredicate implements IntPredicate {
12      private ConcreteIntPredicate() {}
13  
14      /**
15       * @throws IllegalArgumentException if intPredicate is not an instance of ConcreteIntPredicate
16       */
17      @Override
18      public final ConcreteIntPredicate and(IntPredicate intPredicate) {
19          if (!(intPredicate instanceof ConcreteIntPredicate)) {
20              throw new IllegalArgumentException("intPredicate must be an instance of ConcreteIntPredicate");
21          }
22          return new ConjunctionIntPredicate(this, intPredicate);
23      }
24  
25      @Override
26      public final ConcreteIntPredicate negate() {
27          return new NegationIntPredicate(this);
28      }
29  
30      /**
31       * @throws IllegalArgumentException if intPredicate is not an instance of ConcreteIntPredicate
32       */
33      @Override
34      public final ConcreteIntPredicate or(IntPredicate intPredicate) {
35          if (!(intPredicate instanceof ConcreteIntPredicate)) {
36              throw new IllegalArgumentException("intPredicate must be an instance of ConcreteIntPredicate");
37          }
38          return new DisjunctionIntPredicate(this, intPredicate);
39      }
40  
41      @Override
42      @SuppressFBWarnings(value = "AOM_ABSTRACT_OVERRIDDEN_METHOD", justification = "We want subclasses to implement this")
43      public abstract int hashCode();
44  
45      @Override
46      @SuppressFBWarnings(value = "AOM_ABSTRACT_OVERRIDDEN_METHOD", justification = "We want subclasses to implement this")
47      public abstract boolean equals(Object o);
48  
49      @Override
50      @SuppressFBWarnings(value = "AOM_ABSTRACT_OVERRIDDEN_METHOD", justification = "We want subclasses to implement this")
51      public abstract String toString();
52  
53      /**
54       * Greater than i.
55       */
56      public static ConcreteIntPredicate gt(int i) {
57          return new GTIntPredicate(i);
58      }
59  
60      /**
61       * Greater than or equal i.
62       */
63      public static ConcreteIntPredicate gte(int i) {
64          return new GTEIntPredicate(i);
65      }
66  
67      /**
68       * Lesser than or equal i.
69       */
70      public static ConcreteIntPredicate lte(int i) {
71          return new LTEIntPredicate(i);
72      }
73  
74      /**
75       * Lesser than i.
76       */
77      public static ConcreteIntPredicate lt(int i) {
78          return new LTIntPredicate(i);
79      }
80  
81      /**
82       * Lesser than i.
83       */
84      public static ConcreteIntPredicate eq(int i) {
85          return new EqualsIntPredicate(i);
86      }
87  
88      @EqualsAndHashCode(callSuper = false)
89      abstract class CompositeIntPredicate extends ConcreteIntPredicate {
90          final IntPredicate left;
91          final IntPredicate right;
92  
93          CompositeIntPredicate(IntPredicate left, IntPredicate right) {
94              this.left = left;
95              this.right = right;
96          }
97      }
98  
99      @EqualsAndHashCode
100     class ConjunctionIntPredicate extends CompositeIntPredicate {
101         ConjunctionIntPredicate(IntPredicate left, IntPredicate right) {
102             super(left, right);
103         }
104 
105         @Override
106         public boolean test(int i) {
107             return left.test(i) && right.test(i);
108         }
109 
110         @Override
111         public String toString() {
112             return left + " and " + right;
113         }
114     }
115 
116     @EqualsAndHashCode(callSuper = false)
117     class NegationIntPredicate extends ConcreteIntPredicate {
118         private final IntPredicate predicate;
119 
120         NegationIntPredicate(IntPredicate predicate) {
121             this.predicate = predicate;
122         }
123 
124         @Override
125         public boolean test(int i) {
126             return !predicate.test(i);
127         }
128 
129         @Override
130         public String toString() {
131             return "not " + predicate;
132         }
133     }
134 
135     @EqualsAndHashCode(callSuper = true)
136     class DisjunctionIntPredicate extends CompositeIntPredicate {
137         DisjunctionIntPredicate(IntPredicate left, IntPredicate right) {
138             super(left, right);
139         }
140 
141         @Override
142         public boolean test(int i) {
143             return left.test(i) || right.test(i);
144         }
145 
146         @Override
147         public String toString() {
148             return left + " or " + right;
149         }
150     }
151 
152     @EqualsAndHashCode(callSuper = false)
153     private static class EqualsIntPredicate extends ConcreteIntPredicate {
154         private final int value;
155 
156         EqualsIntPredicate(int value) {
157             this.value = value;
158         }
159 
160         @Override
161         public boolean test(int i) {
162             return i == value;
163         }
164 
165         @Override
166         public String toString() {
167             return "= " + value;
168         }
169     }
170 
171     @EqualsAndHashCode(callSuper = false)
172     private static class GTIntPredicate extends ConcreteIntPredicate {
173         private final int value;
174 
175         GTIntPredicate(int value) {
176             this.value = value;
177         }
178 
179         @Override
180         public boolean test(int i) {
181             return i > value;
182         }
183 
184         @Override
185         public String toString() {
186             return "> " + value;
187         }
188     }
189 
190     @EqualsAndHashCode(callSuper = false)
191     private static class GTEIntPredicate extends ConcreteIntPredicate {
192         private final int value;
193 
194         GTEIntPredicate(int value) {
195             this.value = value;
196         }
197 
198         @Override
199         public boolean test(int i) {
200             return i >= value;
201         }
202 
203         @Override
204         public String toString() {
205             return ">= " + value;
206         }
207     }
208 
209     @EqualsAndHashCode(callSuper = false)
210     private static class LTIntPredicate extends ConcreteIntPredicate {
211         private final int value;
212 
213         LTIntPredicate(int value) {
214             this.value = value;
215         }
216 
217         @Override
218         public boolean test(int i) {
219             return i < value;
220         }
221 
222         @Override
223         public String toString() {
224             return "< " + value;
225         }
226     }
227 
228     @EqualsAndHashCode(callSuper = false)
229     private static class LTEIntPredicate extends ConcreteIntPredicate {
230         private final int value;
231 
232         LTEIntPredicate(int value) {
233             this.value = value;
234         }
235 
236         @Override
237         public boolean test(int i) {
238             return i <= value;
239         }
240 
241         @Override
242         public String toString() {
243             return "<= " + value;
244         }
245     }
246 }