author | malenkov |
Wed, 30 Apr 2014 19:28:05 +0400 | |
changeset 24544 | c0133e7c7162 |
parent 23010 | 6dadb192ad81 |
child 25386 | 9ef80c24fd74 |
child 25568 | b906a74c6882 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
21982
diff
changeset
|
2 |
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
package javax.swing; |
|
26 |
||
27 |
import java.util.ArrayList; |
|
28 |
import java.math.BigDecimal; |
|
29 |
import java.math.BigInteger; |
|
30 |
import java.util.Date; |
|
31 |
import java.util.List; |
|
32 |
import java.util.regex.Matcher; |
|
33 |
import java.util.regex.Pattern; |
|
21982 | 34 |
import java.util.regex.PatternSyntaxException; |
2 | 35 |
|
36 |
/** |
|
37 |
* <code>RowFilter</code> is used to filter out entries from the |
|
38 |
* model so that they are not shown in the view. For example, a |
|
39 |
* <code>RowFilter</code> associated with a <code>JTable</code> might |
|
40 |
* only allow rows that contain a column with a specific string. The |
|
41 |
* meaning of <em>entry</em> depends on the component type. |
|
42 |
* For example, when a filter is |
|
43 |
* associated with a <code>JTable</code>, an entry corresponds to a |
|
44 |
* row; when associated with a <code>JTree</code>, an entry corresponds |
|
45 |
* to a node. |
|
46 |
* <p> |
|
47 |
* Subclasses must override the <code>include</code> method to |
|
48 |
* indicate whether the entry should be shown in the |
|
49 |
* view. The <code>Entry</code> argument can be used to obtain the values in |
|
50 |
* each of the columns in that entry. The following example shows an |
|
51 |
* <code>include</code> method that allows only entries containing one or |
|
52 |
* more values starting with the string "a": |
|
53 |
* <pre> |
|
54 |
* RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() { |
|
55 |
* public boolean include(Entry<? extends Object, ? extends Object> entry) { |
|
56 |
* for (int i = entry.getValueCount() - 1; i >= 0; i--) { |
|
57 |
* if (entry.getStringValue(i).startsWith("a")) { |
|
58 |
* // The value starts with "a", include it |
|
59 |
* return true; |
|
60 |
* } |
|
61 |
* } |
|
62 |
* // None of the columns start with "a"; return false so that this |
|
63 |
* // entry is not shown |
|
64 |
* return false; |
|
65 |
* } |
|
66 |
* }; |
|
67 |
* </pre> |
|
68 |
* <code>RowFilter</code> has two formal type parameters that allow |
|
69 |
* you to create a <code>RowFilter</code> for a specific model. For |
|
70 |
* example, the following assumes a specific model that is wrapping |
|
71 |
* objects of type <code>Person</code>. Only <code>Person</code>s |
|
72 |
* with an age over 20 will be shown: |
|
73 |
* <pre> |
|
74 |
* RowFilter<PersonModel,Integer> ageFilter = new RowFilter<PersonModel,Integer>() { |
|
75 |
* public boolean include(Entry<? extends PersonModel, ? extends Integer> entry) { |
|
76 |
* PersonModel personModel = entry.getModel(); |
|
77 |
* Person person = personModel.getPerson(entry.getIdentifier()); |
|
78 |
* if (person.getAge() > 20) { |
|
79 |
* // Returning true indicates this row should be shown. |
|
80 |
* return true; |
|
81 |
* } |
|
82 |
* // Age is <= 20, don't show it. |
|
83 |
* return false; |
|
84 |
* } |
|
85 |
* }; |
|
86 |
* PersonModel model = createPersonModel(); |
|
87 |
* TableRowSorter<PersonModel> sorter = new TableRowSorter<PersonModel>(model); |
|
88 |
* sorter.setRowFilter(ageFilter); |
|
89 |
* </pre> |
|
90 |
* |
|
91 |
* @param <M> the type of the model; for example <code>PersonModel</code> |
|
92 |
* @param <I> the type of the identifier; when using |
|
93 |
* <code>TableRowSorter</code> this will be <code>Integer</code> |
|
94 |
* @see javax.swing.table.TableRowSorter |
|
95 |
* @since 1.6 |
|
96 |
*/ |
|
97 |
public abstract class RowFilter<M,I> { |
|
98 |
/** |
|
99 |
* Enumeration of the possible comparison values supported by |
|
100 |
* some of the default <code>RowFilter</code>s. |
|
101 |
* |
|
102 |
* @see RowFilter |
|
103 |
* @since 1.6 |
|
104 |
*/ |
|
105 |
public enum ComparisonType { |
|
106 |
/** |
|
107 |
* Indicates that entries with a value before the supplied |
|
108 |
* value should be included. |
|
109 |
*/ |
|
110 |
BEFORE, |
|
111 |
||
112 |
/** |
|
113 |
* Indicates that entries with a value after the supplied |
|
114 |
* value should be included. |
|
115 |
*/ |
|
116 |
AFTER, |
|
117 |
||
118 |
/** |
|
119 |
* Indicates that entries with a value equal to the supplied |
|
120 |
* value should be included. |
|
121 |
*/ |
|
122 |
EQUAL, |
|
123 |
||
124 |
/** |
|
125 |
* Indicates that entries with a value not equal to the supplied |
|
126 |
* value should be included. |
|
127 |
*/ |
|
128 |
NOT_EQUAL |
|
129 |
} |
|
130 |
||
131 |
/** |
|
132 |
* Throws an IllegalArgumentException if any of the values in |
|
21982 | 133 |
* columns are {@literal <} 0. |
2 | 134 |
*/ |
135 |
private static void checkIndices(int[] columns) { |
|
136 |
for (int i = columns.length - 1; i >= 0; i--) { |
|
137 |
if (columns[i] < 0) { |
|
138 |
throw new IllegalArgumentException("Index must be >= 0"); |
|
139 |
} |
|
140 |
} |
|
141 |
} |
|
142 |
||
143 |
/** |
|
144 |
* Returns a <code>RowFilter</code> that uses a regular |
|
145 |
* expression to determine which entries to include. Only entries |
|
146 |
* with at least one matching value are included. For |
|
147 |
* example, the following creates a <code>RowFilter</code> that |
|
148 |
* includes entries with at least one value starting with |
|
149 |
* "a": |
|
150 |
* <pre> |
|
151 |
* RowFilter.regexFilter("^a"); |
|
152 |
* </pre> |
|
153 |
* <p> |
|
154 |
* The returned filter uses {@link java.util.regex.Matcher#find} |
|
155 |
* to test for inclusion. To test for exact matches use the |
|
156 |
* characters '^' and '$' to match the beginning and end of the |
|
157 |
* string respectively. For example, "^foo$" includes only rows whose |
|
158 |
* string is exactly "foo" and not, for example, "food". See |
|
159 |
* {@link java.util.regex.Pattern} for a complete description of |
|
160 |
* the supported regular-expression constructs. |
|
161 |
* |
|
162 |
* @param regex the regular expression to filter on |
|
163 |
* @param indices the indices of the values to check. If not supplied all |
|
164 |
* values are evaluated |
|
165 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
166 |
* @throws NullPointerException if <code>regex</code> is |
|
167 |
* <code>null</code> |
|
168 |
* @throws IllegalArgumentException if any of the <code>indices</code> |
|
169 |
* are < 0 |
|
170 |
* @throws PatternSyntaxException if <code>regex</code> is |
|
171 |
* not a valid regular expression. |
|
172 |
* @see java.util.regex.Pattern |
|
173 |
*/ |
|
174 |
public static <M,I> RowFilter<M,I> regexFilter(String regex, |
|
175 |
int... indices) { |
|
176 |
return (RowFilter<M,I>)new RegexFilter(Pattern.compile(regex), |
|
177 |
indices); |
|
178 |
} |
|
179 |
||
180 |
/** |
|
181 |
* Returns a <code>RowFilter</code> that includes entries that |
|
182 |
* have at least one <code>Date</code> value meeting the specified |
|
183 |
* criteria. For example, the following <code>RowFilter</code> includes |
|
184 |
* only entries with at least one date value after the current date: |
|
185 |
* <pre> |
|
186 |
* RowFilter.dateFilter(ComparisonType.AFTER, new Date()); |
|
187 |
* </pre> |
|
188 |
* |
|
189 |
* @param type the type of comparison to perform |
|
190 |
* @param date the date to compare against |
|
191 |
* @param indices the indices of the values to check. If not supplied all |
|
192 |
* values are evaluated |
|
193 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
194 |
* @throws NullPointerException if <code>date</code> is |
|
195 |
* <code>null</code> |
|
196 |
* @throws IllegalArgumentException if any of the <code>indices</code> |
|
197 |
* are < 0 or <code>type</code> is |
|
198 |
* <code>null</code> |
|
199 |
* @see java.util.Calendar |
|
200 |
* @see java.util.Date |
|
201 |
*/ |
|
202 |
public static <M,I> RowFilter<M,I> dateFilter(ComparisonType type, |
|
203 |
Date date, int... indices) { |
|
204 |
return (RowFilter<M,I>)new DateFilter(type, date.getTime(), indices); |
|
205 |
} |
|
206 |
||
207 |
/** |
|
208 |
* Returns a <code>RowFilter</code> that includes entries that |
|
209 |
* have at least one <code>Number</code> value meeting the |
|
210 |
* specified criteria. For example, the following |
|
211 |
* filter will only include entries with at |
|
212 |
* least one number value equal to 10: |
|
213 |
* <pre> |
|
214 |
* RowFilter.numberFilter(ComparisonType.EQUAL, 10); |
|
215 |
* </pre> |
|
216 |
* |
|
217 |
* @param type the type of comparison to perform |
|
218 |
* @param indices the indices of the values to check. If not supplied all |
|
219 |
* values are evaluated |
|
220 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
221 |
* @throws IllegalArgumentException if any of the <code>indices</code> |
|
222 |
* are < 0, <code>type</code> is <code>null</code> |
|
223 |
* or <code>number</code> is <code>null</code> |
|
224 |
*/ |
|
225 |
public static <M,I> RowFilter<M,I> numberFilter(ComparisonType type, |
|
226 |
Number number, int... indices) { |
|
227 |
return (RowFilter<M,I>)new NumberFilter(type, number, indices); |
|
228 |
} |
|
229 |
||
230 |
/** |
|
231 |
* Returns a <code>RowFilter</code> that includes entries if any |
|
232 |
* of the supplied filters includes the entry. |
|
233 |
* <p> |
|
234 |
* The following example creates a <code>RowFilter</code> that will |
|
235 |
* include any entries containing the string "foo" or the string |
|
236 |
* "bar": |
|
237 |
* <pre> |
|
238 |
* List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2); |
|
239 |
* filters.add(RowFilter.regexFilter("foo")); |
|
240 |
* filters.add(RowFilter.regexFilter("bar")); |
|
241 |
* RowFilter<Object,Object> fooBarFilter = RowFilter.orFilter(filters); |
|
242 |
* </pre> |
|
243 |
* |
|
244 |
* @param filters the <code>RowFilter</code>s to test |
|
245 |
* @throws IllegalArgumentException if any of the filters |
|
246 |
* are <code>null</code> |
|
247 |
* @throws NullPointerException if <code>filters</code> is null |
|
248 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
249 |
* @see java.util.Arrays#asList |
|
250 |
*/ |
|
251 |
public static <M,I> RowFilter<M,I> orFilter( |
|
252 |
Iterable<? extends RowFilter<? super M, ? super I>> filters) { |
|
253 |
return new OrFilter<M,I>(filters); |
|
254 |
} |
|
255 |
||
256 |
/** |
|
257 |
* Returns a <code>RowFilter</code> that includes entries if all |
|
258 |
* of the supplied filters include the entry. |
|
259 |
* <p> |
|
260 |
* The following example creates a <code>RowFilter</code> that will |
|
261 |
* include any entries containing the string "foo" and the string |
|
262 |
* "bar": |
|
263 |
* <pre> |
|
264 |
* List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2); |
|
265 |
* filters.add(RowFilter.regexFilter("foo")); |
|
266 |
* filters.add(RowFilter.regexFilter("bar")); |
|
267 |
* RowFilter<Object,Object> fooBarFilter = RowFilter.andFilter(filters); |
|
268 |
* </pre> |
|
269 |
* |
|
270 |
* @param filters the <code>RowFilter</code>s to test |
|
271 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
272 |
* @throws IllegalArgumentException if any of the filters |
|
273 |
* are <code>null</code> |
|
274 |
* @throws NullPointerException if <code>filters</code> is null |
|
275 |
* @see java.util.Arrays#asList |
|
276 |
*/ |
|
277 |
public static <M,I> RowFilter<M,I> andFilter( |
|
278 |
Iterable<? extends RowFilter<? super M, ? super I>> filters) { |
|
279 |
return new AndFilter<M,I>(filters); |
|
280 |
} |
|
281 |
||
282 |
/** |
|
283 |
* Returns a <code>RowFilter</code> that includes entries if the |
|
284 |
* supplied filter does not include the entry. |
|
285 |
* |
|
286 |
* @param filter the <code>RowFilter</code> to negate |
|
287 |
* @return a <code>RowFilter</code> implementing the specified criteria |
|
288 |
* @throws IllegalArgumentException if <code>filter</code> is |
|
289 |
* <code>null</code> |
|
290 |
*/ |
|
291 |
public static <M,I> RowFilter<M,I> notFilter(RowFilter<M,I> filter) { |
|
292 |
return new NotFilter<M,I>(filter); |
|
293 |
} |
|
294 |
||
295 |
/** |
|
296 |
* Returns true if the specified entry should be shown; |
|
297 |
* returns false if the entry should be hidden. |
|
298 |
* <p> |
|
299 |
* The <code>entry</code> argument is valid only for the duration of |
|
300 |
* the invocation. Using <code>entry</code> after the call returns |
|
301 |
* results in undefined behavior. |
|
302 |
* |
|
303 |
* @param entry a non-<code>null</code> object that wraps the underlying |
|
304 |
* object from the model |
|
305 |
* @return true if the entry should be shown |
|
306 |
*/ |
|
307 |
public abstract boolean include(Entry<? extends M, ? extends I> entry); |
|
308 |
||
309 |
// |
|
310 |
// WARNING: |
|
311 |
// Because of the method signature of dateFilter/numberFilter/regexFilter |
|
312 |
// we can NEVER add a method to RowFilter that returns M,I. If we were |
|
313 |
// to do so it would be possible to get a ClassCastException during normal |
|
314 |
// usage. |
|
315 |
// |
|
316 |
||
317 |
/** |
|
318 |
* An <code>Entry</code> object is passed to instances of |
|
319 |
* <code>RowFilter</code>, allowing the filter to get the value of the |
|
320 |
* entry's data, and thus to determine whether the entry should be shown. |
|
321 |
* An <code>Entry</code> object contains information about the model |
|
322 |
* as well as methods for getting the underlying values from the model. |
|
323 |
* |
|
324 |
* @param <M> the type of the model; for example <code>PersonModel</code> |
|
325 |
* @param <I> the type of the identifier; when using |
|
326 |
* <code>TableRowSorter</code> this will be <code>Integer</code> |
|
327 |
* @see javax.swing.RowFilter |
|
328 |
* @see javax.swing.DefaultRowSorter#setRowFilter(javax.swing.RowFilter) |
|
329 |
* @since 1.6 |
|
330 |
*/ |
|
331 |
public static abstract class Entry<M, I> { |
|
332 |
/** |
|
333 |
* Creates an <code>Entry</code>. |
|
334 |
*/ |
|
335 |
public Entry() { |
|
336 |
} |
|
337 |
||
338 |
/** |
|
339 |
* Returns the underlying model. |
|
340 |
* |
|
341 |
* @return the model containing the data that this entry represents |
|
342 |
*/ |
|
343 |
public abstract M getModel(); |
|
344 |
||
345 |
/** |
|
346 |
* Returns the number of values in the entry. For |
|
347 |
* example, when used with a table this corresponds to the |
|
348 |
* number of columns. |
|
349 |
* |
|
350 |
* @return number of values in the object being filtered |
|
351 |
*/ |
|
352 |
public abstract int getValueCount(); |
|
353 |
||
354 |
/** |
|
355 |
* Returns the value at the specified index. This may return |
|
356 |
* <code>null</code>. When used with a table, index |
|
357 |
* corresponds to the column number in the model. |
|
358 |
* |
|
359 |
* @param index the index of the value to get |
|
360 |
* @return value at the specified index |
|
20158
1c5d22e5b898
8025117: [cleanup] Eliminate doclint errors in javax/swing/text classes
yan
parents:
5506
diff
changeset
|
361 |
* @throws IndexOutOfBoundsException if index < 0 or |
2 | 362 |
* >= getValueCount |
363 |
*/ |
|
364 |
public abstract Object getValue(int index); |
|
365 |
||
366 |
/** |
|
367 |
* Returns the string value at the specified index. If |
|
368 |
* filtering is being done based on <code>String</code> values |
|
369 |
* this method is preferred to that of <code>getValue</code> |
|
370 |
* as <code>getValue(index).toString()</code> may return a |
|
371 |
* different result than <code>getStringValue(index)</code>. |
|
372 |
* <p> |
|
373 |
* This implementation calls <code>getValue(index).toString()</code> |
|
374 |
* after checking for <code>null</code>. Subclasses that provide |
|
375 |
* different string conversion should override this method if |
|
376 |
* necessary. |
|
377 |
* |
|
378 |
* @param index the index of the value to get |
|
379 |
* @return {@code non-null} string at the specified index |
|
20158
1c5d22e5b898
8025117: [cleanup] Eliminate doclint errors in javax/swing/text classes
yan
parents:
5506
diff
changeset
|
380 |
* @throws IndexOutOfBoundsException if index < 0 || |
2 | 381 |
* >= getValueCount |
382 |
*/ |
|
383 |
public String getStringValue(int index) { |
|
384 |
Object value = getValue(index); |
|
385 |
return (value == null) ? "" : value.toString(); |
|
386 |
} |
|
387 |
||
388 |
/** |
|
389 |
* Returns the identifer (in the model) of the entry. |
|
390 |
* For a table this corresponds to the index of the row in the model, |
|
391 |
* expressed as an <code>Integer</code>. |
|
392 |
* |
|
393 |
* @return a model-based (not view-based) identifier for |
|
394 |
* this entry |
|
395 |
*/ |
|
396 |
public abstract I getIdentifier(); |
|
397 |
} |
|
398 |
||
399 |
||
400 |
private static abstract class GeneralFilter extends RowFilter<Object,Object> { |
|
401 |
private int[] columns; |
|
402 |
||
403 |
GeneralFilter(int[] columns) { |
|
404 |
checkIndices(columns); |
|
405 |
this.columns = columns; |
|
406 |
} |
|
407 |
||
408 |
public boolean include(Entry<? extends Object,? extends Object> value){ |
|
409 |
int count = value.getValueCount(); |
|
410 |
if (columns.length > 0) { |
|
411 |
for (int i = columns.length - 1; i >= 0; i--) { |
|
412 |
int index = columns[i]; |
|
413 |
if (index < count) { |
|
414 |
if (include(value, index)) { |
|
415 |
return true; |
|
416 |
} |
|
417 |
} |
|
418 |
} |
|
419 |
} |
|
420 |
else { |
|
421 |
while (--count >= 0) { |
|
422 |
if (include(value, count)) { |
|
423 |
return true; |
|
424 |
} |
|
425 |
} |
|
426 |
} |
|
427 |
return false; |
|
428 |
} |
|
429 |
||
430 |
protected abstract boolean include( |
|
431 |
Entry<? extends Object,? extends Object> value, int index); |
|
432 |
} |
|
433 |
||
434 |
||
435 |
private static class RegexFilter extends GeneralFilter { |
|
436 |
private Matcher matcher; |
|
437 |
||
438 |
RegexFilter(Pattern regex, int[] columns) { |
|
439 |
super(columns); |
|
440 |
if (regex == null) { |
|
441 |
throw new IllegalArgumentException("Pattern must be non-null"); |
|
442 |
} |
|
443 |
matcher = regex.matcher(""); |
|
444 |
} |
|
445 |
||
446 |
protected boolean include( |
|
447 |
Entry<? extends Object,? extends Object> value, int index) { |
|
448 |
matcher.reset(value.getStringValue(index)); |
|
449 |
return matcher.find(); |
|
450 |
} |
|
451 |
} |
|
452 |
||
453 |
||
454 |
private static class DateFilter extends GeneralFilter { |
|
455 |
private long date; |
|
456 |
private ComparisonType type; |
|
457 |
||
458 |
DateFilter(ComparisonType type, long date, int[] columns) { |
|
459 |
super(columns); |
|
460 |
if (type == null) { |
|
461 |
throw new IllegalArgumentException("type must be non-null"); |
|
462 |
} |
|
463 |
this.type = type; |
|
464 |
this.date = date; |
|
465 |
} |
|
466 |
||
467 |
protected boolean include( |
|
468 |
Entry<? extends Object,? extends Object> value, int index) { |
|
469 |
Object v = value.getValue(index); |
|
470 |
||
471 |
if (v instanceof Date) { |
|
472 |
long vDate = ((Date)v).getTime(); |
|
473 |
switch(type) { |
|
474 |
case BEFORE: |
|
475 |
return (vDate < date); |
|
476 |
case AFTER: |
|
477 |
return (vDate > date); |
|
478 |
case EQUAL: |
|
479 |
return (vDate == date); |
|
480 |
case NOT_EQUAL: |
|
481 |
return (vDate != date); |
|
482 |
default: |
|
483 |
break; |
|
484 |
} |
|
485 |
} |
|
486 |
return false; |
|
487 |
} |
|
488 |
} |
|
489 |
||
490 |
||
491 |
||
492 |
||
493 |
private static class NumberFilter extends GeneralFilter { |
|
494 |
private boolean isComparable; |
|
495 |
private Number number; |
|
496 |
private ComparisonType type; |
|
497 |
||
498 |
NumberFilter(ComparisonType type, Number number, int[] columns) { |
|
499 |
super(columns); |
|
500 |
if (type == null || number == null) { |
|
501 |
throw new IllegalArgumentException( |
|
502 |
"type and number must be non-null"); |
|
503 |
} |
|
504 |
this.type = type; |
|
505 |
this.number = number; |
|
506 |
isComparable = (number instanceof Comparable); |
|
507 |
} |
|
508 |
||
509 |
@SuppressWarnings("unchecked") |
|
510 |
protected boolean include( |
|
511 |
Entry<? extends Object,? extends Object> value, int index) { |
|
512 |
Object v = value.getValue(index); |
|
513 |
||
514 |
if (v instanceof Number) { |
|
515 |
boolean compared = true; |
|
516 |
int compareResult; |
|
517 |
Class vClass = v.getClass(); |
|
518 |
if (number.getClass() == vClass && isComparable) { |
|
519 |
compareResult = ((Comparable)number).compareTo(v); |
|
520 |
} |
|
521 |
else { |
|
522 |
compareResult = longCompare((Number)v); |
|
523 |
} |
|
524 |
switch(type) { |
|
525 |
case BEFORE: |
|
526 |
return (compareResult > 0); |
|
527 |
case AFTER: |
|
528 |
return (compareResult < 0); |
|
529 |
case EQUAL: |
|
530 |
return (compareResult == 0); |
|
531 |
case NOT_EQUAL: |
|
532 |
return (compareResult != 0); |
|
533 |
default: |
|
534 |
break; |
|
535 |
} |
|
536 |
} |
|
537 |
return false; |
|
538 |
} |
|
539 |
||
540 |
private int longCompare(Number o) { |
|
541 |
long diff = number.longValue() - o.longValue(); |
|
542 |
||
543 |
if (diff < 0) { |
|
544 |
return -1; |
|
545 |
} |
|
546 |
else if (diff > 0) { |
|
547 |
return 1; |
|
548 |
} |
|
549 |
return 0; |
|
550 |
} |
|
551 |
} |
|
552 |
||
553 |
||
554 |
private static class OrFilter<M,I> extends RowFilter<M,I> { |
|
555 |
List<RowFilter<? super M,? super I>> filters; |
|
556 |
||
557 |
OrFilter(Iterable<? extends RowFilter<? super M, ? super I>> filters) { |
|
558 |
this.filters = new ArrayList<RowFilter<? super M,? super I>>(); |
|
559 |
for (RowFilter<? super M, ? super I> filter : filters) { |
|
560 |
if (filter == null) { |
|
561 |
throw new IllegalArgumentException( |
|
562 |
"Filter must be non-null"); |
|
563 |
} |
|
564 |
this.filters.add(filter); |
|
565 |
} |
|
566 |
} |
|
567 |
||
568 |
public boolean include(Entry<? extends M, ? extends I> value) { |
|
569 |
for (RowFilter<? super M,? super I> filter : filters) { |
|
570 |
if (filter.include(value)) { |
|
571 |
return true; |
|
572 |
} |
|
573 |
} |
|
574 |
return false; |
|
575 |
} |
|
576 |
} |
|
577 |
||
578 |
||
579 |
private static class AndFilter<M,I> extends OrFilter<M,I> { |
|
580 |
AndFilter(Iterable<? extends RowFilter<? super M,? super I>> filters) { |
|
581 |
super(filters); |
|
582 |
} |
|
583 |
||
584 |
public boolean include(Entry<? extends M, ? extends I> value) { |
|
585 |
for (RowFilter<? super M,? super I> filter : filters) { |
|
586 |
if (!filter.include(value)) { |
|
587 |
return false; |
|
588 |
} |
|
589 |
} |
|
590 |
return true; |
|
591 |
} |
|
592 |
} |
|
593 |
||
594 |
||
595 |
private static class NotFilter<M,I> extends RowFilter<M,I> { |
|
596 |
private RowFilter<M,I> filter; |
|
597 |
||
598 |
NotFilter(RowFilter<M,I> filter) { |
|
599 |
if (filter == null) { |
|
600 |
throw new IllegalArgumentException( |
|
601 |
"filter must be non-null"); |
|
602 |
} |
|
603 |
this.filter = filter; |
|
604 |
} |
|
605 |
||
606 |
public boolean include(Entry<? extends M, ? extends I> value) { |
|
607 |
return !filter.include(value); |
|
608 |
} |
|
609 |
} |
|
610 |
} |