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