001 // Copyright 2010, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.func;
016
017 import java.util.Collection;
018 import java.util.Comparator;
019 import java.util.Iterator;
020 import java.util.Map;
021 import java.util.Map.Entry;
022
023 /**
024 * Functional operations on collections with generics support. The core interface is {@link Flow} to
025 * which operations
026 * and transformations
027 * (in terms of {@link Predicate}s, {@link Mapper}s and {@link Reducer}s) to create new Flows. Flows
028 * are initially
029 * created
030 * using {@link #flow(Collection)} and {@link #flow(Object...)}.
031 * <p/>
032 * F will be used a bit, thus it has a short name (for those who don't like static imports). It provides a base set of
033 * Predicate, Mapper and Reducer factories. A good development pattern for applications is to provide a similar,
034 * application-specific, set of such factories.
035 *
036 * @since 5.2.0
037 */
038 @SuppressWarnings("all")
039 public class F
040 {
041 final static Flow<?> EMPTY_FLOW = new EmptyFlow();
042
043 @SuppressWarnings("unchecked")
044 static <T> Flow<T> emptyFlow()
045 {
046 return (Flow<T>) EMPTY_FLOW;
047 }
048
049 /**
050 * A Predicate factory for equality of an element from a flow against a specified
051 * value.
052 */
053 public static <T> Predicate<T> eql(final T value)
054 {
055 return new Predicate<T>()
056 {
057 public boolean accept(T element)
058 {
059 return element.equals(value);
060 }
061 };
062 }
063
064 /**
065 * A Predicate factory for comparison of a Comparable element from a flow against a fixed value.
066 */
067 public static <T extends Comparable<T>> Predicate<T> eq(final T value)
068 {
069 return new Predicate<T>()
070 {
071 public boolean accept(T element)
072 {
073 return element.compareTo(value) == 0;
074 }
075 };
076 }
077
078 /**
079 * A Predicate factory for comparison of a Comparable element against a fixed value.
080 */
081 public static <T extends Comparable<T>> Predicate<T> neq(final T value)
082 {
083 return new Predicate<T>()
084 {
085 public boolean accept(T object)
086 {
087 return object.compareTo(value) != 0;
088 }
089 };
090 }
091
092 /**
093 * A Predicate factory for comparison of a Comparable against a fixed value; true
094 * if the flow element is greater than the provided value.
095 */
096 public static <T extends Comparable<T>> Predicate<T> gt(final T value)
097 {
098 return new Predicate<T>()
099 {
100 public boolean accept(T element)
101 {
102 return element.compareTo(value) > 0;
103 }
104 };
105 }
106
107 /**
108 * A Predicate factory for comparison of a Comparable against a fixed value; true
109 * if the flow element is greater than or equal to the value.
110 */
111 public static <T extends Comparable<T>> Predicate<T> gteq(final T value)
112 {
113 return new Predicate<T>()
114 {
115 public boolean accept(T element)
116 {
117 return element.compareTo(value) >= 0;
118 }
119 };
120 }
121
122 /**
123 * A Predicate factory for comparison of a Comparable against a fixed value; true
124 * if the element is less than the value.
125 */
126 public static <T extends Comparable<T>> Predicate<T> lt(T value)
127 {
128 return not(gteq(value));
129 }
130
131 /**
132 * A Predicate factory for comparison of a Comprable element against a fixed value; true
133 * if the element is less than or equal to the value.
134 */
135 public static <T extends Comparable<T>> Predicate<T> lteq(T value)
136 {
137 return not(gt(value));
138 }
139
140 /**
141 * A Predicate factory; returns true if the value from the Flow is null.
142 */
143 public static <T> Predicate<T> isNull()
144 {
145 return new Predicate<T>()
146 {
147 public boolean accept(T element)
148 {
149 return element == null;
150 }
151 };
152 }
153
154 /**
155 * A Predicate factory; returns true if the value from the Flow is not null.
156 */
157 public static <T> Predicate<T> notNull()
158 {
159 return not(isNull());
160 }
161
162 /**
163 * A Mapper factory that gets the string value of the flow value using {@link String#valueOf(Object)}.
164 */
165 public static <T> Mapper<T, String> stringValueOf()
166 {
167 return new Mapper<T, String>()
168 {
169 public String map(T value)
170 {
171 return String.valueOf(value);
172 }
173 };
174 }
175
176 /**
177 * A Mapper factory; the returned Mapper ignores its input value and always returns a
178 * predetermined result.
179 */
180 public static <S, T> Mapper<S, T> always(final T fixedResult)
181 {
182 return new Mapper<S, T>()
183 {
184 public T map(S input)
185 {
186 return fixedResult;
187 }
188 };
189 }
190
191 /**
192 * A Mapper factory that combines a Predicate with two {@link Mapper}s; evaluating the predicate
193 * selects one of the two mappers.
194 *
195 * @param predicate evaluated to selected a coercion
196 * @param ifAccepted used when predicate evaluates to true
197 * @param ifRejected used when predicate evaluates to false
198 */
199 public static <S, T> Mapper<S, T> select(final Predicate<? super S> predicate, final Mapper<S, T> ifAccepted,
200 final Mapper<S, T> ifRejected)
201 {
202 assert predicate != null;
203 assert ifAccepted != null;
204 assert ifRejected != null;
205
206 return new Mapper<S, T>()
207 {
208 public T map(S input)
209 {
210 Mapper<S, T> active = predicate.accept(input) ? ifAccepted : ifRejected;
211
212 return active.map(input);
213 }
214 };
215 }
216
217 /**
218 * Override of {@link #select(Predicate, Mapper, Mapper)} where rejected values are replaced
219 * with null.
220 */
221 public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted)
222 {
223 return select(predicate, ifAccepted, (T) null);
224 }
225
226 /**
227 * Override of {@link #select(Predicate, Mapper)} where rejected values are replaced with a
228 * fixed value.
229 */
230 public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted, T ifRejectedValue)
231 {
232 Mapper<S, T> rejectedMapper = always(ifRejectedValue);
233
234 return select(predicate, ifAccepted, rejectedMapper);
235 }
236
237 /**
238 * A Mapper factory; the Mapper returns the the flow value unchanged.
239 */
240 public static <S> Mapper<S, S> identity()
241 {
242 return new Mapper<S, S>()
243 {
244 public S map(S input)
245 {
246 return input;
247 }
248 };
249 }
250
251 /**
252 * Allows a Mapper that maps to boolean to be used as a Predicate.
253 */
254 public static <S> Predicate<S> toPredicate(final Mapper<S, Boolean> mapper)
255 {
256 assert mapper != null;
257
258 return new Predicate<S>()
259 {
260 public boolean accept(S object)
261 {
262 return mapper.map(object);
263 }
264 };
265 }
266
267 /**
268 * A Reducer that operates on a Flow of Integers and is used to sum the values.
269 */
270 public static Reducer<Integer, Integer> SUM_INTS = new Reducer<Integer, Integer>()
271 {
272 public Integer reduce(Integer accumulator, Integer value)
273 {
274 return accumulator + value;
275 }
276 };
277
278 /**
279 * A two-input Mapper used to add the values from two Flows of Integers into a Flow of Integer
280 * sums.
281 */
282 public static Mapper2<Integer, Integer, Integer> ADD_INTS = new Mapper2<Integer, Integer, Integer>()
283 {
284 public Integer map(Integer first, Integer second)
285 {
286 return first + second;
287 }
288 };
289
290 /**
291 * Extracts the values from the collection to form a {@link Flow}. The Collection
292 * may change after the Flow is created without affecting the Flow.
293 */
294 public static <T> Flow<T> flow(Collection<T> values)
295 {
296 assert values != null;
297
298 if (values.isEmpty())
299 return emptyFlow();
300
301 return new ArrayFlow<T>(values);
302 }
303
304 /**
305 * Creates a new Flow from the values. You should not change the values array
306 * after invoking this method (i.e., no defensive copy of the values is made).
307 */
308 public static <T> Flow<T> flow(T... values)
309 {
310 if (values.length == 0)
311 return emptyFlow();
312
313 return new ArrayFlow<T>(values);
314 }
315
316 /**
317 * Creates a lazy Flow from the {@link Iterator} obtained from the iterable. The Flow
318 * will be threadsafe as long as the iterable yields a new Iterator on each invocation <em>and</em> the underlying
319 * iterable object is not modified while the Flow is evaluating.
320 * In other words, not extremely threadsafe.
321 */
322 public static <T> Flow<T> flow(Iterable<T> iterable)
323 {
324 assert iterable != null;
325
326 return flow(iterable.iterator());
327 }
328
329 /**
330 * Creates a lazy Flow from the {@link Iterator}. The Flow will be threadsafe as long as the underlying iterable
331 * object is not modified while the Flow is evaluating. In other words, not extremely threadsafe.
332 *
333 * @since 5.3
334 */
335 public static <T> Flow<T> flow(Iterator<T> iterator)
336 {
337 return lazy(new LazyIterator<T>(iterator));
338 }
339
340 /**
341 * Creates a ZippedFlow from the provided map; the order of the tuples in the ZippedFlow is defined
342 * by the iteration order of the map entries.
343 *
344 * @param <A> type of key and first tuple value
345 * @param <B> type of value and second tuple value
346 * @param map source of tuples
347 * @return zipped flow created from map
348 * @since 5.3
349 */
350 public static <A, B> ZippedFlow<A, B> zippedFlow(Map<A, B> map)
351 {
352 assert map != null;
353
354 Flow<Tuple<A, B>> tuples = F.flow(map.entrySet()).map(new Mapper<Map.Entry<A, B>, Tuple<A, B>>()
355 {
356 public Tuple<A, B> map(Entry<A, B> element)
357 {
358 return Tuple.create(element.getKey(), element.getValue());
359 }
360 });
361
362 return ZippedFlowImpl.create(tuples);
363 }
364
365 /**
366 * Creates a lazy Flow that returns integers in the given range. The range starts
367 * with the lower value and counts by 1 up to the upper range (which is not part of
368 * the Flow). If lower equals upper, the Flow is empty. If upper is less than lower,
369 * the Flow counts down instead.
370 *
371 * @param lower start of range (inclusive)
372 * @param upper end of range (exclusive)
373 */
374 public static Flow<Integer> range(int lower, int upper)
375 {
376 if (lower == upper)
377 return F.emptyFlow();
378
379 if (lower < upper)
380 return lazy(new LazyRange(lower, upper, 1));
381
382 return lazy(new LazyRange(lower, upper, -1));
383 }
384
385 /**
386 * Creates a {@link Flow} from a {@linkplain LazyFunction lazy function}.
387 */
388 public static <T> Flow<T> lazy(LazyFunction<T> function)
389 {
390 assert function != null;
391
392 return new LazyFlow<T>(function);
393 }
394
395 private static <T> LazyFunction<T> toLazyFunction(final T currentValue, final Mapper<T, T> function)
396 {
397 return new LazyFunction<T>()
398 {
399 public LazyContinuation<T> next()
400 {
401 final T nextValue = function.map(currentValue);
402
403 return new LazyContinuation<T>(nextValue, toLazyFunction(nextValue, function));
404 }
405 };
406 }
407
408 /**
409 * Creates an infinite lazy flow from an initial value and a function to map from the current value to the
410 * next value.
411 *
412 * @param initial initial value in flow
413 * @param function maps from current value in flow to next value in flow
414 * @return lazy flow
415 */
416 public static <T> Flow<T> iterate(final T initial, final Mapper<T, T> function)
417 {
418 LazyFunction<T> head = new LazyFunction<T>()
419 {
420 public LazyContinuation<T> next()
421 {
422 return new LazyContinuation<T>(initial, toLazyFunction(initial, function));
423 }
424 };
425
426 return lazy(head);
427 }
428
429 /**
430 * Creates an <em>infinite</em> series of numbers.
431 * <p/>
432 * Attempting to get the {@linkplain Flow#count()} of the series will form an infinite loop.
433 */
434 public static Flow<Integer> series(int start, final int delta)
435 {
436 return iterate(start, new Mapper<Integer, Integer>()
437 {
438 public Integer map(Integer element)
439 {
440 return element + delta;
441 }
442 });
443 }
444
445 /**
446 * A Worker factory; the returnedWorker adds the values to a provided collection.
447 */
448 public static <T> Worker<T> addToCollection(final Collection<T> coll)
449 {
450 return new Worker<T>()
451 {
452 public void work(T value)
453 {
454 coll.add(value);
455 }
456 };
457 }
458
459 /**
460 * A Predicate factory for matching String elements with a given prefix.
461 *
462 * @since 5.3
463 */
464 public static Predicate<String> startsWith(String prefix)
465 {
466 return startsWith(prefix, false);
467 }
468
469 /**
470 * As {@link #startsWith(String)}, but ignores case.
471 *
472 * @since 5.3
473 */
474 public static Predicate<String> startsWithIgnoringCase(String prefix)
475 {
476 return startsWith(prefix, true);
477 }
478
479 /**
480 * @since 5.3
481 */
482 private static Predicate<String> startsWith(final String prefix, final boolean ignoreCase)
483 {
484 return new Predicate<String>()
485 {
486 public boolean accept(String element)
487 {
488 return element.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
489 }
490 };
491 }
492
493 /**
494 * A Predicate factory for matching String elements with a given suffix.
495 *
496 * @since 5.3
497 */
498 public static Predicate<String> endsWith(String suffix)
499 {
500 return endsWith(suffix, false);
501 }
502
503 /**
504 * As with {@link #endsWith(String)} but ignores case.
505 *
506 * @since 5.3
507 */
508 public static Predicate<String> endsWithIgnoringCase(String suffix)
509 {
510 return endsWith(suffix, true);
511 }
512
513 /**
514 * @since 5.3
515 */
516 private static Predicate<String> endsWith(final String suffix, final boolean ignoreCase)
517 {
518 return new Predicate<String>()
519 {
520 public boolean accept(String element)
521 {
522 return element
523 .regionMatches(ignoreCase, element.length() - suffix.length(), suffix, 0, suffix.length());
524 }
525 };
526 }
527
528 /**
529 * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first
530 * value in the Tuple.
531 *
532 * @since 5.3
533 */
534 public static <A extends Comparable<A>, B> Comparator<Tuple<A, B>> orderByFirst()
535 {
536 return new Comparator<Tuple<A, B>>()
537 {
538 public int compare(Tuple<A, B> o1, Tuple<A, B> o2)
539 {
540 return o1.first.compareTo(o2.first);
541 }
542 };
543 }
544
545 /**
546 * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first
547 * value in the Tuple.
548 *
549 * @since 5.3
550 */
551 public static <A, B extends Comparable<B>> Comparator<Tuple<A, B>> orderBySecond()
552 {
553 return new Comparator<Tuple<A, B>>()
554 {
555 public int compare(Tuple<A, B> o1, Tuple<A, B> o2)
556 {
557 return o1.second.compareTo(o2.second);
558 }
559 };
560 }
561
562 /**
563 * Inverts a predicate.
564 *
565 * @param delegate the predicate to invert
566 * @return a new predicate that is inverse to the existing predicate
567 * @since 5.3
568 */
569 public static <T> Predicate<T> not(final Predicate<? super T> delegate)
570 {
571 assert delegate != null;
572
573 return new Predicate<T>()
574 {
575 public boolean accept(T element)
576 {
577 return !delegate.accept(element);
578 }
579 };
580 }
581
582 /**
583 * Combines two mappers into a composite mapping from type A to type C via type B.
584 *
585 * @param abMapper maps from A to B
586 * @param bcMapper maps from B to C
587 * @return mapper from A to C
588 */
589 public static <A, B, C> Mapper<A, C> combine(final Mapper<A, B> abMapper, final Mapper<B, C> bcMapper)
590 {
591 assert abMapper != null;
592 assert bcMapper != null;
593
594 return new Mapper<A, C>()
595 {
596
597 public C map(A aElement)
598 {
599 B bElement = abMapper.map(aElement);
600
601 return bcMapper.map(bElement);
602 }
603
604 };
605 }
606
607 /**
608 * Combines any number of delegates as a logical and operation. Evaluation terminates
609 * with the first delegate predicate that returns false.
610 *
611 * @param delegates to evaluate
612 * @return combined delegate
613 * @since 5.3
614 */
615 public static <T> Predicate<T> and(final Predicate<? super T>... delegates)
616 {
617 return new Predicate<T>()
618 {
619 public boolean accept(T element)
620 {
621 for (Predicate<? super T> delegate : delegates)
622 {
623 if (!delegate.accept(element))
624 return false;
625 }
626
627 return true;
628 }
629 };
630 }
631
632 /**
633 * Combines any number of delegates as a logical or operation. Evaluation terminates
634 * with the first delegate predicate that returns true.
635 *
636 * @param delegates to evaluate
637 * @return combined delegate
638 * @since 5.3
639 */
640 public static <T> Predicate<T> or(final Predicate<? super T>... delegates)
641 {
642 return new Predicate<T>()
643 {
644 public boolean accept(T element)
645 {
646 for (Predicate<? super T> delegate : delegates)
647 {
648 if (delegate.accept(element))
649 return true;
650 }
651
652 return false;
653 }
654 };
655 }
656
657 /**
658 * Combines several compatible workers together into a composite.
659 *
660 * @since 5.3
661 */
662 public static <T> Worker<T> combine(final Worker<? super T>... delegates)
663 {
664 assert delegates.length > 0;
665
666 return new Worker<T>()
667 {
668 public void work(T value)
669 {
670 for (Worker<? super T> delegate : delegates)
671 {
672 delegate.work(value);
673 }
674 }
675 };
676 }
677 }