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
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     * 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}