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