    001    // Copyright 2010 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
    015    package org.apache.tapestry5.func;
    016
    017    import java.util.List;
    018
    019    /**
    020     * A flow is a a functional interface for working with an ordered collection of elements.
    021     * A given Flow contains only elements of a particular type. Standard operations allow for
    022     * filtering the flow, or appending elements to the Flow. Since flows are immutable, all operations
    023     * on flows return new immutable flows. Flows are thread safe (to the extent that the {@link Mapper} , {@link Predicate}
    024     * , {@link Worker} and {@link Reducer} objects applied to the flow are).
    025     * Flows are <em>lazy</em>: filtering, mapping, and concatenating flows will do so with no, or a
    026     * minimum, of evaluation. However, converting a Flow into a {@link List} (or other collection) will
    027     * force a realization of the entire flow.
    028     * <p>
    029     * In some cases, a flow may be an infinite, lazily evaluated sequence. Operations that iterate over all elements (such
    030     * as {@link #count()} or {@link #reduce(Reducer, Object)}) may become infinite loops.
    031     * <p>
    032     * Using flows allows for a very fluid interface.
    033     * <p>
    034     * Flows are initially created using {@link F#flow(java.util.Collection)}, {@link F#flow(Object...)} or
    035     * {@link F#flow(Iterable)}.
    036     *
    037     * @since 5.2.0
    038     * @see F#lazy(LazyFunction)
    039     */
    040    public interface Flow<T> extends FlowOperations<T, Flow<T>>
    041    {
    042        /** Maps a Flow into a new Flow with different type values. Mapping is a lazy operation. */
    043        <X> Flow<X> map(Mapper<T, X> mapper);
    044
    045        /**
    046         * Combines two Flows using a two-parameter Mapper. Each element of
    047         * this Flow, and the corresponding element of the other flow are passed through the Mapper
    048         * to provide the elements of the output Flow. The length of the result Flow is
    049         * the smaller of the lengths of the two input Flows. Mapping is a lazy operation.
    050         */
    051        <X, Y> Flow<Y> map(Mapper2<T, X, Y> mapper, Flow<? extends X> flow);
    052
    053        /**
    054         * Given a {@link Mapper} that maps a T to a Flow<X>, this method will lazily concatenate
    055         * all the output flows into a single Flow<X>.
    056         */
    057        <X> Flow<X> mapcat(Mapper<T, Flow<X>> mapper);
    058
    059        /**
    060         * Converts the Flow into an array of values (due to type erasure, you have to remind the Flow
    061         * about the type).
    062         */
    063        T[] toArray(Class<T> type);
    064
    065        /**
    066         * Returns a new Flow with the other Flow's elements appended to this Flow's. This is a lazy
    067         * operation.
    068         */
    069        Flow<T> concat(Flow<? extends T> other);
    070
    071        /**
    072         * Appends any number of type compatible values to the end of this Flow. This is a lazy
    073         * operation.
    074         */
    075        <V extends T> Flow<T> append(V... values);
    076
    077        /**
    078         * Sorts this Flow, forming a new Flow. This is a non-lazy operation; it will fully realize the
    079         * values of the Flow.
    080         *
    081         * @throws ClassCastException
    082         *             if type <T> does not extend {@link Comparable}
    083         */
    084        Flow<T> sort();
    085
    086        /**
    087         * Zips this Flow together with another flow to form a Flow of {@link Tuple}s. The resulting
    088         * flow is the length of the shorter of the two input flows. Zipping flows together is a lazy
    089         * operation.
    090         * <p>
    091         * The elements of this flow become the {@linkplain Tuple#first} value in each Tuple, the elements of the other flow
    092         * become the {@linkplain Tuple#second} value in each Tuple.
    093         *
    094         * @param <X>
    095         *            type of element stored in the other flow
    096         * @param otherFlow
    097         *            contains elements to match with elements in this flow
    098         * @return flow of tuples combining values from this flow with values form the other flow
    099         * @since 5.3
    100         */
    101        <X> ZippedFlow<T, X> zipWith(Flow<X> otherFlow);
    102
    103        /**
    104         * "Stripes" together a group of flows. The output flow contains the first value from this flow, then the first
    105         * value from each of the other flows, in turn, then the second value from this flow, etc. The resulting flow ends
    106         * when this or any of the other flows runs out of values.
    107         *
    108         * @return combined flow
    109         */
    110        Flow<T> interleave(Flow<T>... otherFlows);
    111    }