1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.util.stream;
  26 
  27 /**
  28  * An operation in a stream pipeline that takes a stream as input and produces a stream, possibly of a different
  29  * type, as output.  An intermediate operation has an input type and an output type (and, an associated input
  30  * shape and output shape).  An intermediate operation also has a set of <em>operation flags</em> that describes
  31  * how the operation transforms characteristics of the stream (such as sortedness or size; see
  32  * {@link StreamOpFlag}).
  33  *
  34  * <p>Intermediate operations are implemented in terms of <em>sink transforms</em>; given a {@code Sink} for the
  35  * output type of the operation, produce a {@code Sink} for the input type of the operation, which, when fed with
  36  * values, has the effect of implementing the desired operation on the input values and feeding them to the output
  37  * sink.
  38  *
  39  * <p>Some intermediate operations are <em>stateful</em>.  This means that the sinks they produce as a result of
  40  * the above wrapping may maintain state from processing earlier elements.  Stateful intermediate operations must
  41  * implement the {@link StatefulOp} interface.
  42  *
  43  * @apiNote
  44  * As an example, consider the stream pipeline:
  45  * <pre>
  46  *     int oldestBob = people.stream().filter(p -> p.getFirstName.equals("Bob")).map(p -> p.getAge()).max();
  47  * </pre>
  48  *
  49  * <p>This pipeline has two intermediate operations, filter and map.  The filtering operation has input and output types
  50  * of {@code Person} (with input and output shape of {@code REFERENCE}), and the mapping operation has an input
  51  * type of {@code Person} and an output type of {@code Integer} (with shape {@code INT_VALUE}.)  When we construct
  52  * a sink chain, the mapping operation will be asked to transform a {@code Sink.OfInt} which computes the maximum
  53  * value into a {@code Sink} which accepts {@code Person} objects, and whose behavior is to take the supplied
  54  * {@code Person}, call {@code getAge()} on it, and pass the resulting value to the downstream sink.  This sink
  55  * transform might be implement as:
  56  *
  57  * <pre>
  58  *     new Sink.ChainedReference<U>(sink) {
  59  *         public void accept(U u) {
  60  *             downstream.accept(mappingFunction.applyAsInt(u));
  61  *         }
  62  *     }
  63  * </pre>
  64  *
  65  * @param <E_IN>  Type of input elements to the operation
  66  * @param <E_OUT> Type of output elements to the operation
  67  * @see TerminalOp
  68  * @see StatefulOp
  69  * @since 1.8
  70  */
  71 interface IntermediateOp<E_IN, E_OUT> {
  72 
  73     /**
  74      * Get the shape of the input type of this operation
  75      * @implSpec The default returns {@code StreamShape.REFERENCE}
  76      * @return Shape of the input type of this operation
  77      */
  78     default StreamShape inputShape() { return StreamShape.REFERENCE; }
  79 
  80     /**
  81      * Get the shape of the output type of this operation
  82      * @implSpec The default returns {@code StreamShape.REFERENCE}
  83      * @return Shape of the output type of this operation
  84      */
  85     default StreamShape outputShape() { return StreamShape.REFERENCE; }
  86 
  87     /**
  88      * Get the operation flags of this operation.
  89      *
  90      * @implSpec The default returns {@code 0}
  91      * @return a bitmap describing the operation flags of this operation
  92      * @see StreamOpFlag
  93      */
  94     default int getOpFlags() { return 0; }
  95 
  96     /**
  97      * Return whether this operation is stateful or not.  If it is stateful, then the method
  98      * {@link #evaluateParallel(PipelineHelper)} must be overridden.
  99      *
 100      * @implSpec The default implementation returns {@code false}.
 101      *
 102      * @return {@code true} then operation is stateful
 103      */
 104     default boolean isStateful() { return false; }
 105 
 106     /**
 107      * Accept a {@code Sink} which will receive the results of this operation, and return a {@code Sink}
 108      * which accepts elements of the input type of this operation and which performs the operation, passing
 109      * the results to the provided {@code Sink}.
 110      *
 111      * <p>The implementation may use the {@code flags} parameter to optimize the sink wrapping.  For example, if
 112      * the input is already {@code DISTINCT}, the implementation for the {@code Stream#distinct()} method could
 113      * just return the sink it was passed.
 114      *
 115      * @param flags The combined stream and operation flags up to, but not including, this operation.
 116      * @param sink elements will be sent to this sink after the processing.
 117      * @return a sink which will accept elements and perform the operation upon
 118      *         each element, passing the results (if any) to the provided {@code Sink}.
 119      */
 120     Sink<E_IN> wrapSink(int flags, Sink<E_OUT> sink);
 121 
 122     /**
 123      * Perform a parallel evaluation of the operation using the specified {@code PipelineHelper}, which describes
 124      * the stream source and upstream intermediate operations.  Only called on stateful operations.
 125      * If {@link #isStateful()} returns true then implementations must override the default implementation.
 126      *
 127      * @implSpec The default implementation throws an {@link UnsupportedOperationException}
 128      *
 129      * @param helper the pipeline helper
 130      * @param <P_IN> the type of elements in the pipeline source
 131      * @return a {@code Node} describing the result of the evaluation
 132      */
 133     default <P_IN> Node<E_OUT> evaluateParallel(PipelineHelper<P_IN, E_OUT> helper) {
 134         throw new UnsupportedOperationException("Parallel evaluation is not supported");
 135     }
 136 }