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