001: // ============================================================================
002: // $Id: Transform.java,v 1.5 2006/12/05 04:45:44 davidahall Exp $
003: // Copyright (c) 2002-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.BinaryFunctor;
038: import net.sf.jga.fn.UnaryFunctor;
039: import net.sf.jga.fn.adaptor.ConditionalUnary;
040: import net.sf.jga.fn.adaptor.ConstantUnary;
041: import net.sf.jga.fn.adaptor.Identity;
042: import net.sf.jga.fn.comparison.EqualTo;
043: import net.sf.jga.util.LookAheadIterator;
044:
045: import static net.sf.jga.util.ArrayUtils.*;
046: import static net.sf.jga.util.CollectionUtils.*;
047:
048: /**
049: * Algorithms that process the elements of a collection, iteration, or iterable resource,
050: * and present the results.
051: * <p>
052: * Copyright © 2002-2006 David A. Hall
053: *
054: * @author <a href="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
055: **/
056: public class Transform {
057:
058: static private <T> UnaryFunctor<T, T> conditional(
059: UnaryFunctor<T, Boolean> test, UnaryFunctor<T, T> xform) {
060: return new ConditionalUnary<T, T>(test, xform,
061: new Identity<T>());
062: }
063:
064: // ============
065: // Arrays
066: // ============
067:
068: /**
069: * Produces an iterable over the contents of the array, such that all instances of the
070: * given value are replaced with the given replacement value.
071: */
072: static public <T> Iterable<T> replace(T[] ts, T value, T replacement) {
073: return transform(ts, conditional(new EqualTo<T>()
074: .bind2nd(value), new ConstantUnary<T, T>(replacement)));
075: }
076:
077: /**
078: * Produces an iterable over the contents of the array, such that all elements for which
079: * the given test returns TRUE are replaced with the given replacement value.
080: */
081: static public <T> Iterable<T> replace(T[] ts,
082: UnaryFunctor<T, Boolean> test, T replacement) {
083: return transform(ts, conditional(test, new ConstantUnary<T, T>(
084: replacement)));
085: }
086:
087: /**
088: * Produces an iterable over the contents of the array, such that all elements for which
089: * the given test returns TRUE are replaced with the results of passing that element to
090: * the given replacement functor.
091: */
092: static public <T> Iterable<T> replace(T[] ts,
093: UnaryFunctor<T, Boolean> test, UnaryFunctor<T, T> fn) {
094: return transform(ts, conditional(test, fn));
095: }
096:
097: /**
098: * Passes each element in the array to the functor, iterating over the results
099: */
100: static public <T, R> Iterable<R> transform(T[] ts,
101: UnaryFunctor<T, R> fn) {
102: return new TransformIterable<T, R>(iterable(ts), fn);
103: }
104:
105: /**
106: * Passes successive pairs of elements in the array to the functor, iterating over the results
107: */
108: static public <T, R> Iterable<R> transform(T[] ts,
109: BinaryFunctor<T, T, R> fn) {
110: return new AdjacentIterable<T, R>(iterable(ts), fn);
111: }
112:
113: /**
114: * Passes corresponding pairs of elements in the arrays to the functor,
115: * iterating over the results
116: */
117: static public <T1, T2, R> Iterable<R> transform(T1[] ts1, T2[] ts2,
118: BinaryFunctor<T1, T2, R> fn) {
119: return new BinaryIterable<T1, T2, R>(iterable(ts1),
120: iterable(ts2), fn);
121: }
122:
123: // ============
124: // Iterables
125: // ============
126:
127: /**
128: * Produces an iterable over the contents of the input, such that all instances of the
129: * given value are replaced with the given replacement value.
130: */
131: static public <T> Iterable<T> replace(Iterable<T> ts, T value,
132: T replacement) {
133: return transform(ts, conditional(new EqualTo<T>()
134: .bind2nd(value), new ConstantUnary<T, T>(replacement)));
135: }
136:
137: /**
138: * Produces an iterable over the contents of the input, such that all elements for which
139: * the given test returns TRUE are replaced with the given replacement value.
140: */
141: static public <T> Iterable<T> replace(Iterable<T> ts,
142: UnaryFunctor<T, Boolean> test, T replacement) {
143: return transform(ts, conditional(test, new ConstantUnary<T, T>(
144: replacement)));
145: }
146:
147: /**
148: * Produces an iterable over the contents of the input, such that all elements for which
149: * the given test returns TRUE are replaced with the results of passing that element to
150: * the given replacement functor.
151: */
152: static public <T> Iterable<T> replace(Iterable<T> ts,
153: UnaryFunctor<T, Boolean> test, UnaryFunctor<T, T> fn) {
154: return transform(ts, conditional(test, fn));
155: }
156:
157: /**
158: * Passes each element in the iterable resource to the functor, iterating over the results
159: */
160: static public <T, R> Iterable<R> transform(Iterable<? extends T> i,
161: UnaryFunctor<T, R> fn) {
162: return new TransformIterable<T, R>(i, fn);
163: }
164:
165: /**
166: * Passes successive pairs of elements in the iterable resource to the functor,
167: * iterating over the results
168: */
169: static public <T, R> Iterable<R> transform(Iterable<? extends T> i,
170: BinaryFunctor<T, T, R> fn) {
171: return new AdjacentIterable<T, R>(i, fn);
172: }
173:
174: /**
175: * Passes corresponding pairs of elements in the iterable resources to the functor,
176: * iterating over the results
177: */
178: static public <T1, T2, R> Iterable<R> transform(
179: Iterable<? extends T1> i1, Iterable<? extends T2> i2,
180: BinaryFunctor<T1, T2, R> fn) {
181: return new BinaryIterable<T1, T2, R>(i1, i2, fn);
182: }
183:
184: // ============
185: // Iterators
186: // ============
187:
188: /**
189: * Produces an iterator over the contents of the given iterator, such that all instances of the
190: * given value are replaced with the given replacement value.
191: */
192: static public <T> Iterator<T> replace(Iterator<? extends T> ts,
193: T value, T replacement) {
194: return transform(ts, conditional(new EqualTo<T>()
195: .bind2nd(value), new ConstantUnary<T, T>(replacement)));
196: }
197:
198: /**
199: * Produces an iterator over the contents of the given iterator, such that all elements for which
200: * the given test returns TRUE are replaced with the given replacement value.
201: */
202: static public <T> Iterator<T> replace(Iterator<? extends T> ts,
203: UnaryFunctor<T, Boolean> test, T replacement) {
204: return transform(ts, conditional(test, new ConstantUnary<T, T>(
205: replacement)));
206: }
207:
208: /**
209: * Produces an iterator over the contents of the given iterator, such that all elements for which
210: * the given test returns TRUE are replaced with the results of passing that element to
211: * the given replacement functor.
212: */
213: static public <T> Iterator<T> replace(Iterator<? extends T> ts,
214: UnaryFunctor<T, Boolean> test, UnaryFunctor<T, T> fn) {
215: return transform(ts, conditional(test, fn));
216: }
217:
218: /**
219: * Passes each element in the iterator to the functor, iterating over the results
220: */
221: static public <T, R> Iterator<R> transform(
222: Iterator<? extends T> iter, UnaryFunctor<T, R> fn) {
223: return new net.sf.jga.util.TransformIterator<T, R>(iter, fn);
224: }
225:
226: /**
227: * Passes successive pairs of elements in the iterator to the functor, iterating over the results
228: */
229: static public <T, R> Iterator<R> transform(
230: Iterator<? extends T> iter, BinaryFunctor<T, T, R> fn) {
231: return new net.sf.jga.util.TransformAdjacentIterator<T, R>(
232: iter, fn);
233: }
234:
235: /**
236: * Passes corresponding pairs of elements in the iterators to the functor,
237: * iterating over the results
238: */
239: static public <T1, T2, R> Iterator<R> transform(
240: Iterator<? extends T1> iter1, Iterator<? extends T2> iter2,
241: BinaryFunctor<T1, T2, R> fn) {
242: return new net.sf.jga.util.TransformBinaryIterator<T1, T2, R>(
243: iter1, iter2, fn);
244: }
245:
246: // ============
247: // IterableCopy
248: // ============
249:
250: /**
251: * Appends the contents of the input to the output, such that all instances of the
252: * given value are replaced with the given replacement value
253: */
254: static public <T, TCollection extends Collection<? super T>> TCollection replace(
255: Iterable<? extends T> cin, T value, T repl, TCollection cout) {
256: return append(cout, replace(cin.iterator(), value, repl));
257: }
258:
259: /**
260: * Appends the contents of the input to the output, such that all elements for which
261: * the given test returns TRUE are replaced with the given replacement value.
262: */
263: static public <T, TCollection extends Collection<? super T>> TCollection replace(
264: Iterable<? extends T> cin, UnaryFunctor<T, Boolean> test,
265: T repl, TCollection cout) {
266: return append(cout, replace(cin.iterator(), test, repl));
267: }
268:
269: /**
270: * Appends the contents of the input to the output, such that all elements for which
271: * the given test returns TRUE are replaced with the results of passing that element to
272: * the given replacement functor.
273: */
274: static public <T, TCollection extends Collection<? super T>> TCollection replace(
275: Iterable<? extends T> cin, UnaryFunctor<T, Boolean> test,
276: UnaryFunctor<T, T> fn, TCollection cout) {
277: return append(cout, replace(cin.iterator(), test, fn));
278: }
279:
280: /**
281: * Appends the transformed contents of the input to the output.
282: */
283: static public <T, RCollection extends Collection<? super R>, R> RCollection transform(
284: Iterable<? extends T> cin, UnaryFunctor<T, R> fn,
285: RCollection cout) {
286: return append(cout, transform(cin.iterator(), fn));
287: }
288:
289: /**
290: * Appends the results of transforming successive pairs of elements from the input to the output.
291: */
292: static public <T, RCollection extends Collection<? super R>, R> RCollection transform(
293: Iterable<? extends T> cin, BinaryFunctor<T, T, R> fn,
294: RCollection cout) {
295: return append(cout, transform(cin.iterator(), fn));
296: }
297:
298: /**
299: * Appends the results of transforming corresponding pairs of elements from the
300: * input sto the output.
301: */
302: static public <T1, T2, RCollection extends Collection<? super R>, R> RCollection transform(
303: Iterable<? extends T1> cin1, Iterable<? extends T2> cin2,
304: BinaryFunctor<T1, T2, R> fn, RCollection cout) {
305: return append(cout, transform(cin1.iterator(), cin2.iterator(),
306: fn));
307: }
308:
309: /**
310: * Produces iterators that will process elements of an iterable resource and present
311: * the results.
312: * <p>
313: * Copyright © 2005 David A. Hall
314: */
315:
316: static public class TransformIterable<T, R> implements Iterable<R> {
317: // The contents
318: private Iterable<? extends T> _delegate;
319:
320: // The process to be applied
321: private UnaryFunctor<T, R> _fn;
322:
323: /**
324: * Builds a TransformIterable for the given base.
325: * @throws IllegalArgumentException if the base iterable is null
326: */
327: public TransformIterable(Iterable<? extends T> base,
328: UnaryFunctor<T, R> process) {
329: _delegate = base;
330: _fn = process;
331: }
332:
333: // - - - - - - - - - - -
334: // Iterable<T> interface
335: // - - - - - - - - - - -
336:
337: public Iterator<R> iterator() {
338: return new net.sf.jga.util.TransformIterator(_delegate
339: .iterator(), _fn);
340: }
341: }
342:
343: /*
344: * Iterator that returns the results of applying the given functor to the
345: * elements of the given iterator.
346: */
347: static public class TransformIterator<T, R> implements Iterator<R> {
348:
349: // The base iterator
350: private Iterator<? extends T> _base;
351:
352: // Functor applied to each element of the base iterator
353: private UnaryFunctor<T, R> _fn;
354:
355: /**
356: * Builds a TransformIterator that applies the given functor to each element
357: * of the given base iterator.
358: */
359: public TransformIterator(Iterator<? extends T> iter,
360: UnaryFunctor<T, R> fn) {
361: _base = iter;
362: _fn = fn;
363: }
364:
365: // - - - - - - - - - - -
366: // Iterator<R> interface
367: // - - - - - - - - - - -
368:
369: public boolean hasNext() {
370: return _base.hasNext();
371: }
372:
373: public R next() {
374: return _fn.fn(_base.next());
375: }
376:
377: public void remove() {
378: throw new UnsupportedOperationException();
379: }
380: }
381:
382: /**
383: * Produces iterators that will process successive pairs of elements of an iterable resource
384: * and present the results.
385: */
386:
387: static public class AdjacentIterable<T, R> implements Iterable<R> {
388: // The contents
389: private Iterable<? extends T> _delegate;
390:
391: // The process to be applied
392: private BinaryFunctor<T, T, R> _fn;
393:
394: /**
395: * Builds a TransformIterable for the given base.
396: * @throws IllegalArgumentException if the base iterable is null
397: */
398: public AdjacentIterable(Iterable<? extends T> base,
399: BinaryFunctor<T, T, R> process) {
400: _delegate = base;
401: _fn = process;
402: }
403:
404: // - - - - - - - - - - -
405: // Iterable<R> interface
406: // - - - - - - - - - - -
407:
408: public Iterator<R> iterator() {
409: return new net.sf.jga.util.TransformAdjacentIterator(
410: _delegate.iterator(), _fn);
411: }
412: }
413:
414: /**
415: * Iterator that applies a given BinaryFunctor to successive pairs of elements
416: * from a given iterator, returning the results as elements.
417: */
418: static public class AdjacentIterator<T, R> implements Iterator<R> {
419:
420: // The base iterator
421: private LookAheadIterator<? extends T> _base;
422:
423: // Functor applied to adjacent values in the base iterator
424: private BinaryFunctor<T, T, R> _fn;
425:
426: /**
427: * Builds a TransormAdjacentIterator that applies the given functor to
428: * adjacent elements of the given base iterator.
429: */
430: public AdjacentIterator(Iterator<? extends T> iter,
431: BinaryFunctor<T, T, R> fn) {
432: _base = new LookAheadIterator<T>(iter, 2);
433: _fn = fn;
434: }
435:
436: // - - - - - - - - - - -
437: // Iterator<R> interface
438: // - - - - - - - - - - -
439:
440: public boolean hasNext() {
441: return _base.hasNextPlus(2);
442: }
443:
444: public R next() {
445: T next = _base.next();
446: return _fn.fn(next, _base.peek(1));
447: }
448:
449: public void remove() {
450: throw new UnsupportedOperationException();
451: }
452: }
453:
454: /**
455: * Produces iterators that applies a given BinaryFunctor to corresponding pairs of elements
456: * from a pair of iterators, returning the results.
457: */
458:
459: static public class BinaryIterable<T1, T2, R> implements
460: Iterable<R> {
461: // The contents
462: private Iterable<? extends T1> _delegate1;
463: private Iterable<? extends T2> _delegate2;
464:
465: // The process to be applied
466: private BinaryFunctor<T1, T2, R> _fn;
467:
468: /**
469: * Builds a TransformIterable for the given base.
470: * @throws IllegalArgumentException if the base iterable is null
471: */
472: public BinaryIterable(Iterable<? extends T1> base1,
473: Iterable<? extends T2> base2,
474: BinaryFunctor<T1, T2, R> process) {
475: _delegate1 = base1;
476: _delegate2 = base2;
477: _fn = process;
478: }
479:
480: // - - - - - - - - - - -
481: // Iterable<R> interface
482: // - - - - - - - - - - -
483:
484: public Iterator<R> iterator() {
485: return new net.sf.jga.util.TransformBinaryIterator(
486: _delegate1.iterator(), _delegate2.iterator(), _fn);
487: }
488: }
489:
490: /**
491: * Iterator that applies a given BinaryFunctor to corresponding pairs of elements
492: * from a pair of iterators, returning the results.
493: */
494: static public class BinaryIterator<T1, T2, R> implements
495: Iterator<R> {
496: // The two base iterators
497: private Iterator<? extends T1> _i1;
498: private Iterator<? extends T2> _i2;
499:
500: // Functor applied to corresponding elements of the base iterator
501: private BinaryFunctor<T1, T2, R> _bf;
502:
503: /**
504: * Builds a TransformBinaryIterator that applies the given functor to
505: * corresponding elements of the given base iterators.
506: */
507: public BinaryIterator(Iterator<? extends T1> i1,
508: Iterator<? extends T2> i2, BinaryFunctor<T1, T2, R> bf) {
509: _i1 = i1;
510: _i2 = i2;
511: _bf = bf;
512: }
513:
514: // - - - - - - - - - - -
515: // Iterator<R> interface
516: // - - - - - - - - - - -
517:
518: public boolean hasNext() {
519: return _i1.hasNext() && _i2.hasNext();
520: }
521:
522: public R next() {
523: return _bf.fn(_i1.next(), _i2.next());
524: }
525:
526: public void remove() {
527: throw new UnsupportedOperationException();
528: }
529: }
530: }
|