001: // ============================================================================
002: // $Id: Filter.java,v 1.7 2006/12/16 16:48:57 davidahall Exp $
003: // Copyright (c) 2005 David A. Hall
004: // ============================================================================
005: // The contents of this file are subject to the Common Development and
006: // Distribution License (CDDL), Version 1.0 (the License); you may not use this
007: // file except in compliance with the License. You should have received a copy
008: // of the the License along with this file: if not, a copy of the License is
009: // available from Sun Microsystems, Inc.
010: //
011: // http://www.sun.com/cddl/cddl.html
012: //
013: // From time to time, the license steward (initially Sun Microsystems, Inc.) may
014: // publish revised and/or new versions of the License. You may not use,
015: // distribute, or otherwise make this file available under subsequent versions
016: // of the License.
017: //
018: // Alternatively, the contents of this file may be used under the terms of the
019: // GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
020: // case the provisions of the LGPL are applicable instead of those above. If you
021: // wish to allow use of your version of this file only under the terms of the
022: // LGPL, and not to allow others to use your version of this file under the
023: // terms of the CDDL, indicate your decision by deleting the provisions above
024: // and replace them with the notice and other provisions required by the LGPL.
025: // If you do not delete the provisions above, a recipient may use your version
026: // of this file under the terms of either the CDDL or the LGPL.
027: //
028: // This library is distributed in the hope that it will be useful,
029: // but WITHOUT ANY WARRANTY; without even the implied warranty of
030: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
031: // ============================================================================
032:
033: package net.sf.jga.algorithms;
034:
035: import java.util.Collection;
036: import java.util.Iterator;
037: import net.sf.jga.fn.UnaryFunctor;
038: import net.sf.jga.fn.comparison.Equality;
039: import net.sf.jga.fn.comparison.NotEqualTo;
040: import net.sf.jga.fn.logical.UnaryNegate;
041: import net.sf.jga.util.FindIterator;
042:
043: import static net.sf.jga.util.ArrayUtils.*;
044: import static net.sf.jga.util.CollectionUtils.*;
045:
046: /**
047: * Algorithms that return a subset of its input. The input may be an array, collection, or
048: * iteration. There are two general algorithms included: filter and remove. The filter
049: * methods return elements from the input that pass the selection criteria, while the remove
050: * methods removes elements from the input stream for which the selection criteria is true.
051: * Note that the actual input is not modified in any of these methods.
052: * <p>
053: * Copyright © 2006 David A. Hall
054: */
055:
056: public class Filter {
057:
058: // ============
059: // Arrays
060: // ============
061:
062: /**
063: * Returns the elements of the array that meet the given selection criteria.
064: */
065: static public <T> Iterable<T> filter(T[] ts,
066: UnaryFunctor<T, Boolean> pred) {
067: return new FilterIterable<T>(iterable(ts), pred);
068: }
069:
070: /**
071: * Returns the elements of the array that are not equal to the given value, using the value's
072: * {@link equals} method
073: */
074: static public <T> Iterable<T> remove(T[] ts, T value) {
075: return filter(ts, new NotEqualTo<T>().bind2nd(value));
076: }
077:
078: /**
079: * Returns the elements of the array that are not equal to the given value, using the given
080: * functor to compare for equality
081: */
082: static public <T> Iterable<T> remove(T[] ts, T value, Equality<T> eq) {
083: return filter(ts, new UnaryNegate<T>(eq.bind2nd(value)));
084: }
085:
086: /**
087: * Returns the elements of the array that do not meet the given selection criteria
088: */
089: static public <T> Iterable<T> remove(T[] ts,
090: UnaryFunctor<T, Boolean> pred) {
091: return filter(ts, new UnaryNegate<T>(pred));
092: }
093:
094: // ============
095: // Iterables
096: // ============
097:
098: /**
099: * Returns the contents of the input that meet the given selection criteria.
100: */
101: static public <T> Iterable<T> filter(Iterable<? extends T> i,
102: UnaryFunctor<T, Boolean> pred) {
103: return new FilterIterable<T>(i, pred);
104: }
105:
106: /**
107: * Returns the elements of the input that are not equal to the given value, using the value's
108: * {@link equals} method
109: */
110: static public <T> Iterable<T> remove(Iterable<? extends T> i,
111: T value) {
112: return filter(i, new NotEqualTo<T>().bind2nd(value));
113: }
114:
115: /**
116: * Returns the elements of the input that are not equal to the given value, using the given
117: * functor to compare for equality
118: */
119: static public <T> Iterable<T> remove(Iterable<? extends T> i,
120: T value, Equality<T> eq) {
121: return filter(i, new UnaryNegate<T>(eq.bind2nd(value)));
122: }
123:
124: /**
125: * Returns the elements of the input that do not meet the given selection criteria
126: */
127: static public <T> Iterable<T> remove(Iterable<? extends T> i,
128: UnaryFunctor<T, Boolean> pred) {
129: return filter(i, new UnaryNegate<T>(pred));
130: }
131:
132: // ============
133: // Iterators
134: // ============
135:
136: /**
137: * Returns the contents of the iterator that meet the given selection criteria.
138: */
139: static public <T> Iterator<T> filter(Iterator<? extends T> iter,
140: UnaryFunctor<T, Boolean> pred) {
141: return new net.sf.jga.util.FilterIterator<T>(iter, pred);
142: }
143:
144: /**
145: * Returns the elements of the iterator that are not equal to the given value, using the value's
146: * {@link equals} method
147: */
148: static public <T> Iterator<T> remove(Iterator<? extends T> iter,
149: T value) {
150: return filter(iter, new NotEqualTo<T>().bind2nd(value));
151: }
152:
153: /**
154: * Returns the elements of the iterator that are not equal to the given value, using the given
155: * functor to compare for equality
156: */
157: static public <T> Iterator<T> remove(Iterator<? extends T> iter,
158: T value, Equality<T> eq) {
159: return filter(iter, new UnaryNegate<T>(eq.bind2nd(value)));
160: }
161:
162: /**
163: * Returns the elements of the iterator that do not meet the given selection criteria
164: */
165: static public <T> Iterator<T> remove(Iterator<? extends T> iter,
166: UnaryFunctor<T, Boolean> pred) {
167: return filter(iter, new UnaryNegate<T>(pred));
168: }
169:
170: // ============
171: // IterableCopy
172: // ============
173:
174: /**
175: * Appends the contents of the input that meet the given selection criteria to the output.
176: */
177: static public <T, TCollection extends Collection<? super T>> TCollection filter(
178: Iterable<? extends T> cin, UnaryFunctor<T, Boolean> pred,
179: TCollection cout) {
180: return append(cout, filter(cin.iterator(), pred));
181: }
182:
183: /**
184: * Returns the elements of the input that are not equal to the given value, using the value's
185: * {@link equals} method
186: */
187: static public <T, TCollection extends Collection<? super T>> TCollection remove(
188: Iterable<? extends T> cin, T value, TCollection cout) {
189: return append(cout, remove(cin.iterator(), value));
190: }
191:
192: /**
193: * Returns the elements of the input that are not equal to the given value, using the given
194: * functor to compare for equality
195: */
196: static public <T, TCollection extends Collection<? super T>> TCollection remove(
197: Iterable<? extends T> cin, T value, Equality<T> eq,
198: TCollection cout) {
199: return append(cout, remove(cin.iterator(), value, eq));
200: }
201:
202: /**
203: * Returns the elements of the input that do not meet the given selection criteria
204: */
205: static public <T, TCollection extends Collection<? super T>> TCollection remove(
206: Iterable<? extends T> cin, UnaryFunctor<T, Boolean> pred,
207: TCollection cout) {
208: return append(cout, remove(cin.iterator(), pred));
209: }
210:
211: // ==============
212: // FilterIterable
213: // ==============
214:
215: /**
216: * Produces Iterators that only return elements that meet a given condition.
217: */
218:
219: // Suggested by sourceforge user Jerry Vos:
220: // https://sourceforge.net/tracker/index.php?func=detail&aid=1276988&group_id=49942&atid=458041
221: static public class FilterIterable<T> implements Iterable<T> {
222:
223: private Iterable<? extends T> _delegate;
224:
225: // predicate used to test elements of the base iterator.
226: private UnaryFunctor<T, Boolean> _filter;
227:
228: /**
229: * Builds a FilterIterator that will return only qualifying elements of
230: * the given iterable.
231: */
232: public FilterIterable(Iterable<? extends T> iter,
233: UnaryFunctor<T, Boolean> pred) {
234: _delegate = iter;
235: _filter = pred;
236: }
237:
238: // - - - - - - - - - - -
239: // Iterable<T> interface
240: // - - - - - - - - - - -
241:
242: public Iterator<T> iterator() {
243: return new net.sf.jga.util.FilterIterator<T>(_delegate
244: .iterator(), _filter);
245: }
246: }
247:
248: /**
249: * Iterator that only returns elements that meet the given selection criteria.
250: **/
251:
252: static public class FilterIterator<T> implements Iterator<T> {
253:
254: // base iterator
255: private FindIterator<T> _base;
256:
257: // predicate used to test elements of the base iterator.
258: private UnaryFunctor<T, Boolean> _filter;
259:
260: // flag indicating that the base iterator has been advanced to the next
261: // qualifying element (or off the end if no remaining element qualifies)
262: private boolean _testedNext;
263:
264: /**
265: * Builds a FilterIterator that will return only qualifying elements of
266: * the given iterator.
267: */
268: public FilterIterator(Iterator<? extends T> iter,
269: UnaryFunctor<T, Boolean> pred) {
270: _base = new FindIterator<T>(iter);
271: _filter = pred;
272: }
273:
274: // - - - - - - - - - - - - -
275: // Iterator<T> interface
276: // - - - - - - - - - - - - -
277:
278: public boolean hasNext() {
279: _testedNext = true;
280: return _base.findNext(_filter);
281: }
282:
283: public T next() {
284: if (!_testedNext) {
285: hasNext();
286: }
287:
288: _testedNext = false;
289: return _base.next();
290: }
291:
292: public void remove() {
293: throw new UnsupportedOperationException();
294: }
295: }
296: }
|