    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}