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    }