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