sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/02: Move `StreamDecoration` to "SQL store" internal package, renamed `StreamWrapper`. We limit the use of those wrappers for now because we do not yet have a mechanism for allowing methods with `Stream` return type to return also some `StreamWrapper`. In current implementation, any call to a method such as `Stream.map(…)` may cause the lost of all optimizations done in `StreamWrapper` subclasses.
Date Sat, 10 Oct 2020 14:39:14 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit b22fa6d53e2ded10eef9847fc62f8282ba2e3c67
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat Oct 10 14:50:10 2020 +0200

    Move `StreamDecoration` to "SQL store" internal package, renamed `StreamWrapper`.
    We limit the use of those wrappers for now because we do not yet have a mechanism
    for allowing methods with `Stream` return type to return also some `StreamWrapper`.
    In current implementation, any call to a method such as `Stream.map(…)` may cause
    the lost of all optimizations done in `StreamWrapper` subclasses.
---
 .../sis/internal/util/BaseStreamDecoration.java    | 104 ------
 .../sis/internal/util/DoubleStreamDecoration.java  | 201 -----------
 .../apache/sis/internal/util/StreamDecoration.java | 219 ------------
 .../internal/sql/feature/BaseStreamWrapper.java    | 159 +++++++++
 .../internal/sql/feature/DoubleStreamWrapper.java  | 343 +++++++++++++++++++
 .../apache/sis/internal/sql/feature/StreamSQL.java |  33 +-
 .../sis/internal/sql/feature/StreamWrapper.java    | 373 +++++++++++++++++++++
 7 files changed, 881 insertions(+), 551 deletions(-)

diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/BaseStreamDecoration.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/BaseStreamDecoration.java
deleted file mode 100644
index 980aac1..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/BaseStreamDecoration.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.util;
-
-import java.util.Iterator;
-import java.util.Spliterator;
-import java.util.stream.BaseStream;
-import javax.validation.constraints.NotNull;
-
-/**
- * Delegates operations to an underlying stream provided by {@link #createDecoratedStream()}. Allows for custom logic
- * decoration. See {@link StreamDecoration} for further details.
- *
- * @param <T> Type of values contained in the stream, as defined in {@link BaseStream}
- * @param <S> Type of stream implementation, as defined in {@link BaseStream}
- *
- *  @since 1.0
- *
- * @author Alexis Manin (Geomatys)
- */
-public abstract class BaseStreamDecoration<T, S extends BaseStream<T, S>> implements BaseStream<T, S> {
-
-    private S decorated;
-
-    private boolean closed;
-
-    /**
-     * Get previously created wrapped stream, or create it if never done.
-     * @return The stream containing actual data.
-     */
-
-    protected final @NotNull S getOrCreate() {
-        if (closed) throw new IllegalStateException("Stream has already been closed.");
-        if (decorated == null) {
-            decorated = createDecoratedStream();
-        }
-
-        return decorated;
-    }
-
-    /**
-     * Operation that creates underlying stream to delegate operations to as a last resort. Note that sub-classes should
-     * never call this method. Instead, please use {@link #getOrCreate()}, ensuring that decorated stream is created
-     * only once, then potentially re-used multiple times.
-     *
-     * @return A new, non-consumed stream to delegate actions to.
-     */
-    protected abstract @NotNull S createDecoratedStream();
-
-    @Override
-    public void close() {
-        closed = true;
-        if (decorated != null) decorated.close();
-    }
-
-    @Override
-    public Iterator<T> iterator() {
-        return getOrCreate().iterator();
-    }
-
-    @Override
-    public Spliterator<T> spliterator() {
-        return getOrCreate().spliterator();
-    }
-
-    @Override
-    public boolean isParallel() {
-        return getOrCreate().isParallel();
-    }
-
-    @Override
-    public S sequential() {
-        return getOrCreate().sequential();
-    }
-
-    @Override
-    public S parallel() {
-        return getOrCreate().parallel();
-    }
-
-    @Override
-    public S unordered() {
-        return getOrCreate().unordered();
-    }
-
-    @Override
-    public S onClose(Runnable closeHandler) {
-        return getOrCreate().onClose(closeHandler);
-    }
-}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleStreamDecoration.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleStreamDecoration.java
deleted file mode 100644
index 22e0fe1..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleStreamDecoration.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.util;
-
-import java.util.DoubleSummaryStatistics;
-import java.util.OptionalDouble;
-import java.util.PrimitiveIterator;
-import java.util.Spliterator;
-import java.util.function.BiConsumer;
-import java.util.function.DoubleBinaryOperator;
-import java.util.function.DoubleConsumer;
-import java.util.function.DoubleFunction;
-import java.util.function.DoublePredicate;
-import java.util.function.DoubleToIntFunction;
-import java.util.function.DoubleToLongFunction;
-import java.util.function.DoubleUnaryOperator;
-import java.util.function.ObjDoubleConsumer;
-import java.util.function.Supplier;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.Stream;
-
-/**
- * A specialization of {@link StreamDecoration} for {@link DoubleStream streams of double value}.
- *
- * @since 1.0
- *
- * @author Alexis Manin (Geomatys)
- */
-public abstract class DoubleStreamDecoration extends BaseStreamDecoration<Double, DoubleStream> implements DoubleStream {
-
-    @Override
-    public DoubleStream filter(DoublePredicate predicate) {
-        return getOrCreate().filter(predicate);
-    }
-
-    @Override
-    public DoubleStream map(DoubleUnaryOperator mapper) {
-        return getOrCreate().map(mapper);
-    }
-
-    @Override
-    public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
-        return getOrCreate().mapToObj(mapper);
-    }
-
-    @Override
-    public IntStream mapToInt(DoubleToIntFunction mapper) {
-        return getOrCreate().mapToInt(mapper);
-    }
-
-    @Override
-    public LongStream mapToLong(DoubleToLongFunction mapper) {
-        return getOrCreate().mapToLong(mapper);
-    }
-
-    @Override
-    public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
-        return getOrCreate().flatMap(mapper);
-    }
-
-    @Override
-    public DoubleStream distinct() {
-        return getOrCreate().distinct();
-    }
-
-    @Override
-    public DoubleStream sorted() {
-        return getOrCreate().sorted();
-    }
-
-    @Override
-    public DoubleStream peek(DoubleConsumer action) {
-        return getOrCreate().peek(action);
-    }
-
-    @Override
-    public DoubleStream limit(long maxSize) {
-        return getOrCreate().limit(maxSize);
-    }
-
-    @Override
-    public DoubleStream skip(long n) {
-        return getOrCreate().skip(n);
-    }
-
-    @Override
-    public void forEach(DoubleConsumer action) {
-        getOrCreate().forEach(action);
-    }
-
-    @Override
-    public void forEachOrdered(DoubleConsumer action) {
-        getOrCreate().forEachOrdered(action);
-    }
-
-    @Override
-    public double[] toArray() {
-        return getOrCreate().toArray();
-    }
-
-    @Override
-    public double reduce(double identity, DoubleBinaryOperator op) {
-        return getOrCreate().reduce(identity, op);
-    }
-
-    @Override
-    public OptionalDouble reduce(DoubleBinaryOperator op) {
-        return getOrCreate().reduce(op);
-    }
-
-    @Override
-    public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
-        return getOrCreate().collect(supplier, accumulator, combiner);
-    }
-
-    @Override
-    public double sum() {
-        return getOrCreate().sum();
-    }
-
-    @Override
-    public OptionalDouble min() {
-        return getOrCreate().min();
-    }
-
-    @Override
-    public OptionalDouble max() {
-        return getOrCreate().max();
-    }
-
-    @Override
-    public long count() {
-        return getOrCreate().count();
-    }
-
-    @Override
-    public OptionalDouble average() {
-        return getOrCreate().average();
-    }
-
-    @Override
-    public DoubleSummaryStatistics summaryStatistics() {
-        return getOrCreate().summaryStatistics();
-    }
-
-    @Override
-    public boolean anyMatch(DoublePredicate predicate) {
-        return getOrCreate().anyMatch(predicate);
-    }
-
-    @Override
-    public boolean allMatch(DoublePredicate predicate) {
-        return getOrCreate().allMatch(predicate);
-    }
-
-    @Override
-    public boolean noneMatch(DoublePredicate predicate) {
-        return getOrCreate().noneMatch(predicate);
-    }
-
-    @Override
-    public OptionalDouble findFirst() {
-        return getOrCreate().findFirst();
-    }
-
-    @Override
-    public OptionalDouble findAny() {
-        return getOrCreate().findAny();
-    }
-
-    @Override
-    public Stream<Double> boxed() {
-        return getOrCreate().boxed();
-    }
-
-    @Override
-    public PrimitiveIterator.OfDouble iterator() {
-        return getOrCreate().iterator();
-    }
-
-    @Override
-    public Spliterator.OfDouble spliterator() {
-        return getOrCreate().spliterator();
-    }
-}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StreamDecoration.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/StreamDecoration.java
deleted file mode 100644
index 75f143f..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StreamDecoration.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.util;
-
-import java.util.Comparator;
-import java.util.Optional;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.IntFunction;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.function.ToDoubleFunction;
-import java.util.function.ToIntFunction;
-import java.util.function.ToLongFunction;
-import java.util.stream.Collector;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.Stream;
-
-/**
- * Allows for delegation for a subset of behaviors of a stream to a custom component.
- * How it works: This class is simply delegating all {@link Stream} interface operations to the one provided by
- * {@link #createDecoratedStream()} implementation. It allows implementations to short-circuit a certain number of
- * methods to provide their own solution. For example, if you've got a streamable dataset whose count can be provided
- * efficiently by a third-party tool (typically COUNT query on SQL databases), you can create a {@link StreamDecoration}
- * with an overrided count method running the count query instead of counting elements of the stream manually.
- *
- * Another exemple would be intermediate operations. Let's keep SQL queries as example. If you create a stream executing
- * a statement on terminal operations, you could override {@link Stream#limit(long)} and {@link Stream#skip(long)}
- * methods to set LIMIT and OFFSET criterias in an SQL query.
- *
- * For an advanced example, you can look at {@link org.apache.sis.internal.sql.feature.StreamSQL} class.
- *
- * @param <T> The type of objects contained in the stream, as specified in {@link Stream} interface.
- *
- * @since 1.0
- *
- * @author Alexis Manin (Geomatys)
- */
-public abstract class StreamDecoration<T> extends BaseStreamDecoration<T, Stream<T>> implements Stream<T> {
-
-    @Override
-    public Stream<T> filter(Predicate<? super T> predicate) {
-        return getOrCreate().filter(predicate);
-    }
-
-    @Override
-    public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
-        return getOrCreate().map(mapper);
-    }
-
-    @Override
-    public IntStream mapToInt(ToIntFunction<? super T> mapper) {
-        return getOrCreate().mapToInt(mapper);
-    }
-
-    @Override
-    public LongStream mapToLong(ToLongFunction<? super T> mapper) {
-        return getOrCreate().mapToLong(mapper);
-    }
-
-    @Override
-    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
-        return getOrCreate().mapToDouble(mapper);
-    }
-
-    @Override
-    public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
-        return getOrCreate().flatMap(mapper);
-    }
-
-    @Override
-    public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
-        return getOrCreate().flatMapToInt(mapper);
-    }
-
-    @Override
-    public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
-        return getOrCreate().flatMapToLong(mapper);
-    }
-
-    @Override
-    public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
-        return getOrCreate().flatMapToDouble(mapper);
-    }
-
-    @Override
-    public Stream<T> distinct() {
-        return getOrCreate().distinct();
-    }
-
-    @Override
-    public Stream<T> sorted() {
-        return getOrCreate().sorted();
-    }
-
-    @Override
-    public Stream<T> sorted(Comparator<? super T> comparator) {
-        return getOrCreate().sorted(comparator);
-    }
-
-    @Override
-    public Stream<T> peek(Consumer<? super T> action) {
-        return getOrCreate().peek(action);
-    }
-
-    @Override
-    public Stream<T> limit(long maxSize) {
-        return getOrCreate().limit(maxSize);
-    }
-
-    @Override
-    public Stream<T> skip(long n) {
-        return getOrCreate().skip(n);
-    }
-
-    @Override
-    public void forEach(Consumer<? super T> action) {
-        getOrCreate().forEach(action);
-    }
-
-    @Override
-    public void forEachOrdered(Consumer<? super T> action) {
-        getOrCreate().forEachOrdered(action);
-    }
-
-    @Override
-    public Object[] toArray() {
-        return getOrCreate().toArray();
-    }
-
-    @Override
-    public <A> A[] toArray(IntFunction<A[]> generator) {
-        return getOrCreate().toArray(generator);
-    }
-
-    @Override
-    public T reduce(T identity, BinaryOperator<T> accumulator) {
-        return getOrCreate().reduce(identity, accumulator);
-    }
-
-    @Override
-    public Optional<T> reduce(BinaryOperator<T> accumulator) {
-        return getOrCreate().reduce(accumulator);
-    }
-
-    @Override
-    public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
-        return getOrCreate().reduce(identity, accumulator, combiner);
-    }
-
-    @Override
-    public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
-        return getOrCreate().collect(supplier, accumulator, combiner);
-    }
-
-    @Override
-    public <R, A> R collect(Collector<? super T, A, R> collector) {
-        return getOrCreate().collect(collector);
-    }
-
-    @Override
-    public Optional<T> min(Comparator<? super T> comparator) {
-        return getOrCreate().min(comparator);
-    }
-
-    @Override
-    public Optional<T> max(Comparator<? super T> comparator) {
-        return getOrCreate().max(comparator);
-    }
-
-    @Override
-    public long count() {
-        return getOrCreate().count();
-    }
-
-    @Override
-    public boolean anyMatch(Predicate<? super T> predicate) {
-        return getOrCreate().anyMatch(predicate);
-    }
-
-    @Override
-    public boolean allMatch(Predicate<? super T> predicate) {
-        return getOrCreate().allMatch(predicate);
-    }
-
-    @Override
-    public boolean noneMatch(Predicate<? super T> predicate) {
-        return getOrCreate().noneMatch(predicate);
-    }
-
-    @Override
-    public Optional<T> findFirst() {
-        return getOrCreate().findFirst();
-    }
-
-    @Override
-    public Optional<T> findAny() {
-        return getOrCreate().findAny();
-    }
-}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BaseStreamWrapper.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BaseStreamWrapper.java
new file mode 100644
index 0000000..d2143c5
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BaseStreamWrapper.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.sql.feature;
+
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.stream.BaseStream;
+
+
+/**
+ * Delegates operations to an underlying stream provided by {@link #createSource()}.
+ * Allows for custom logic decoration. See {@link StreamWrapper} for further details.
+ *
+ * @author  Alexis Manin (Geomatys)
+ * @version 1.1
+ *
+ * @param  <T>  type of values contained in the stream, as defined in {@link BaseStream}.
+ * @param  <S>  type of stream implementation, as defined in {@link BaseStream}.
+ *
+ * @since 1.1
+ * @module
+ */
+abstract class BaseStreamWrapper<T, S extends BaseStream<T, S>> implements BaseStream<T, S> {
+    /**
+     * The stream decorated by this class. Created when first needed.
+     *
+     * @see #getSource()
+     */
+    private S source;
+
+    /**
+     * Whether the stream has been closed.
+     */
+    private boolean closed;
+
+    /**
+     * For sub-classes constructors.
+     */
+    protected BaseStreamWrapper() {
+    }
+
+    /**
+     * Gets previously created wrapped stream, or creates it if never done.
+     *
+     * @return the stream containing actual data.
+     * @throws IllegalStateException if this stream is {@linkplain #close() closed}.
+     */
+    protected final S getSource() {
+        if (closed) {
+            throw new IllegalStateException("Stream is closed.");
+        }
+        if (source == null) {
+            source = createSource();
+        }
+        return source;
+    }
+
+    /**
+     * Creates underlying stream on which to delegate operations. Sub-classes should never call this method directly.
+     * Instead, use {@link #getSource()} for ensuring that decorated stream is created only once and potentially
+     * re-used multiple times.
+     *
+     * @return a new, non-consumed stream to delegate actions to.
+     */
+    protected abstract S createSource();
+
+    /**
+     * Returns an iterator for the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Iterator<T> iterator() {
+        return getSource().iterator();
+    }
+
+    /**
+     * Returns a spliterator for the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Spliterator<T> spliterator() {
+        return getSource().spliterator();
+    }
+
+    /**
+     * Returns whether stream terminal operation would execute in parallel.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean isParallel() {
+        return getSource().isParallel();
+    }
+
+    /**
+     * Returns an equivalent stream that is sequential.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public S sequential() {
+        return getSource().sequential();
+    }
+
+    /**
+     * Returns an equivalent stream that is parallel.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public S parallel() {
+        return getSource().parallel();
+    }
+
+    /**
+     * Returns an equivalent stream that is unordered.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public S unordered() {
+        return getSource().unordered();
+    }
+
+    /**
+     * Returns an equivalent stream with an additional close handler.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public S onClose(Runnable closeHandler) {
+        return getSource().onClose(closeHandler);
+    }
+
+    /**
+     * Closes the source stream and marks this stream as closed.
+     */
+    @Override
+    public void close() {
+        closed = true;
+        if (source != null) {
+            source.close();
+            source = null;
+        }
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DoubleStreamWrapper.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DoubleStreamWrapper.java
new file mode 100644
index 0000000..508f246
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DoubleStreamWrapper.java
@@ -0,0 +1,343 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.sql.feature;
+
+import java.util.DoubleSummaryStatistics;
+import java.util.OptionalDouble;
+import java.util.PrimitiveIterator;
+import java.util.Spliterator;
+import java.util.function.BiConsumer;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.DoubleConsumer;
+import java.util.function.DoubleFunction;
+import java.util.function.DoublePredicate;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
+import java.util.function.DoubleUnaryOperator;
+import java.util.function.ObjDoubleConsumer;
+import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+
+/**
+ * A specialization of {@link BaseStreamWrapper} for {@linkplain DoubleStream streams of double value}.
+ *
+ * @author  Alexis Manin (Geomatys)
+ * @version 1.1
+ * @since   1.1
+ * @module
+ */
+abstract class DoubleStreamWrapper extends BaseStreamWrapper<Double, DoubleStream> implements DoubleStream {
+    /**
+     * For subclass constructors.
+     */
+    protected DoubleStreamWrapper() {
+    }
+
+    /**
+     * Returns a stream with elements of this stream that match the given predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream filter(DoublePredicate predicate) {
+        return getSource().filter(predicate);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream map(DoubleUnaryOperator mapper) {
+        return getSource().map(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
+        return getSource().mapToObj(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public IntStream mapToInt(DoubleToIntFunction mapper) {
+        return getSource().mapToInt(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public LongStream mapToLong(DoubleToLongFunction mapper) {
+        return getSource().mapToLong(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
+        return getSource().flatMap(mapper);
+    }
+
+    /**
+     * Returns a stream with distinct elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream distinct() {
+        return getSource().distinct();
+    }
+
+    /**
+     * Returns a stream with elements of this stream sorted in ascending order.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream sorted() {
+        return getSource().sorted();
+    }
+
+    /**
+     * Returns a stream performing the specified action on each element when consumed.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream peek(DoubleConsumer action) {
+        return getSource().peek(action);
+    }
+
+    /**
+     * Returns a stream with truncated at the given number of elements.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream limit(long maxSize) {
+        return getSource().limit(maxSize);
+    }
+
+    /**
+     * Returns a stream discarding the specified number of elements.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream skip(long n) {
+        return getSource().skip(n);
+    }
+
+    /**
+     * Performs an action for each element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public void forEach(DoubleConsumer action) {
+        getSource().forEach(action);
+    }
+
+    /**
+     * Performs an action for each element of this stream in encounter order.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public void forEachOrdered(DoubleConsumer action) {
+        getSource().forEachOrdered(action);
+    }
+
+    /**
+     * Returns all elements in an array.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public double[] toArray() {
+        return getSource().toArray();
+    }
+
+    /**
+     * Performs a reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public double reduce(double identity, DoubleBinaryOperator op) {
+        return getSource().reduce(identity, op);
+    }
+
+    /**
+     * Performs a reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble reduce(DoubleBinaryOperator op) {
+        return getSource().reduce(op);
+    }
+
+    /**
+     * Performs a mutable reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
+        return getSource().collect(supplier, accumulator, combiner);
+    }
+
+    /**
+     * Returns the sum of elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public double sum() {
+        return getSource().sum();
+    }
+
+    /**
+     * Returns the minimum element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble min() {
+        return getSource().min();
+    }
+
+    /**
+     * Returns the maximum element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble max() {
+        return getSource().max();
+    }
+
+    /**
+     * Returns the number of elements in this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public long count() {
+        return getSource().count();
+    }
+
+    /**
+     * Returns the average of elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble average() {
+        return getSource().average();
+    }
+
+    /**
+     * Returns statistics about elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public DoubleSummaryStatistics summaryStatistics() {
+        return getSource().summaryStatistics();
+    }
+
+    /**
+     * Returns whether at least one element of this stream matches the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean anyMatch(DoublePredicate predicate) {
+        return getSource().anyMatch(predicate);
+    }
+
+    /**
+     * Returns whether all elements of this stream match the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean allMatch(DoublePredicate predicate) {
+        return getSource().allMatch(predicate);
+    }
+
+    /**
+     * Returns whether none element of this stream match the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean noneMatch(DoublePredicate predicate) {
+        return getSource().noneMatch(predicate);
+    }
+
+    /**
+     * Returns the first element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble findFirst() {
+        return getSource().findFirst();
+    }
+
+    /**
+     * Returns any element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public OptionalDouble findAny() {
+        return getSource().findAny();
+    }
+
+    /**
+     * Returns the stream elements as {@link Double} elements.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Stream<Double> boxed() {
+        return getSource().boxed();
+    }
+
+    /**
+     * Returns an iterator for the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public PrimitiveIterator.OfDouble iterator() {
+        return getSource().iterator();
+    }
+
+    /**
+     * Returns a spliterator for the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Spliterator.OfDouble spliterator() {
+        return getSource().spliterator();
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
index ee24fa7..c3dc7f0 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
@@ -30,20 +30,14 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.function.ToDoubleFunction;
-import java.util.function.ToIntFunction;
-import java.util.function.ToLongFunction;
 import java.util.logging.Level;
 import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 import javax.sql.DataSource;
 
 import org.opengis.feature.Feature;
 
-import org.apache.sis.internal.util.DoubleStreamDecoration;
-import org.apache.sis.internal.util.StreamDecoration;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.logging.Logging;
@@ -66,7 +60,7 @@ import static org.apache.sis.util.ArgumentChecks.ensurePositive;
  * @module
  *
  */
-class StreamSQL extends StreamDecoration<Feature> {
+final class StreamSQL extends StreamWrapper<Feature> {
 
     private final QueryBuilder queryAdapter;
 
@@ -100,21 +94,6 @@ class StreamSQL extends StreamDecoration<Feature> {
     }
 
     @Override
-    public IntStream mapToInt(ToIntFunction<? super Feature> mapper) {
-        return super.mapToInt(mapper);
-    }
-
-    @Override
-    public LongStream mapToLong(ToLongFunction<? super Feature> mapper) {
-        return super.mapToLong(mapper);
-    }
-
-    @Override
-    public DoubleStream mapToDouble(ToDoubleFunction<? super Feature> mapper) {
-        return super.mapToDouble(mapper);
-    }
-
-    @Override
     public Stream<Feature> parallel() {
         parallel = true;
         return this;
@@ -194,7 +173,7 @@ class StreamSQL extends StreamDecoration<Feature> {
     }
 
     @Override
-    protected synchronized Stream<Feature> createDecoratedStream() {
+    protected synchronized Stream<Feature> createSource() {
         final AtomicReference<Connection> connectionRef = new AtomicReference<>();
         Stream<Feature> featureStream = Stream.of(uncheck(() -> connectReadOnly(source)))
                 .map(Supplier::get)
@@ -237,7 +216,7 @@ class StreamSQL extends StreamDecoration<Feature> {
      * @param <I> Type of object received as input of mapping operation.
      * @param <O> Return type of mapping operation.
      */
-    private static final class MappedStream<I, O> extends StreamDecoration<O> {
+    private static final class MappedStream<I, O> extends StreamWrapper<O> {
         private Function<? super I, ? extends O> mapper;
         private Stream<I> source;
 
@@ -297,7 +276,7 @@ class StreamSQL extends StreamDecoration<Feature> {
         }
 
         @Override
-        protected Stream<O> createDecoratedStream() {
+        protected Stream<O> createSource() {
             // Break possible infinite loop by sinking source content through its spliterator (terminal op).
             final Stream<I> sink = StreamSupport.stream(source.spliterator(), source.isParallel());
             sink.onClose(source::close);
@@ -311,7 +290,7 @@ class StreamSQL extends StreamDecoration<Feature> {
      *
      * @param <T> Type of objects contained in source stream (before double mapping).
      */
-    private static final class ToDoubleStream<T> extends DoubleStreamDecoration {
+    private static final class ToDoubleStream<T> extends DoubleStreamWrapper {
 
         Stream<T> source;
         ToDoubleFunction<T> toDouble;
@@ -382,7 +361,7 @@ class StreamSQL extends StreamDecoration<Feature> {
         }
 
         @Override
-        protected DoubleStream createDecoratedStream() {
+        protected DoubleStream createSource() {
             // Break possible cycle by sinking source content through its spliterator (terminal op).
             final Stream<T> sink = StreamSupport.stream(source.spliterator(), source.isParallel());
             sink.onClose(source::close);
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamWrapper.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamWrapper.java
new file mode 100644
index 0000000..6836770
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamWrapper.java
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.sql.feature;
+
+import java.util.Comparator;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+import java.util.stream.Collector;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+
+/**
+ * Allows delegation for a subset of behaviors of a stream to a custom component.
+ * The default implementations of methods in this class delegate {@link Stream} operations to the stream provided
+ * by {@link #createSource()}. Implementations in subclasses can short-circuit some methods by overriding them
+ * with their own solution.
+ *
+ * <div class="note"><b>Example:</b>
+ * if a streamable dataset whose count can be provided efficiently by a third-party tool (typically COUNT query
+ * on SQL databases), a {@link StreamWrapper} subclass can override the {@link #count()} method for running
+ * the count query instead of counting elements of the stream manually.
+ *
+ * Another example would be intermediate operations. Let's keep SQL queries as example. If a stream is executing
+ * a statement on terminal operations, a subclasses can override {@link #limit(long)} and {@link #skip(long)}
+ * methods to set LIMIT and OFFSET criterion in an SQL query.</div>
+ *
+ * For an advanced example, see the {@link org.apache.sis.internal.sql.feature.StreamSQL} class.
+ *
+ * @author  Alexis Manin (Geomatys)
+ * @version 1.1
+ *
+ * @param  <T>  the type of objects contained in the stream, as specified in {@link Stream} interface.
+ *
+ * @since 1.1
+ * @module
+ */
+abstract class StreamWrapper<T> extends BaseStreamWrapper<T, Stream<T>> implements Stream<T> {
+    /**
+     * For subclass constructor.
+     */
+    protected StreamWrapper() {
+    }
+
+    /**
+     * Returns a stream with elements of this stream that match the given predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> filter(Predicate<? super T> predicate) {
+        return getSource().filter(predicate);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
+        return getSource().map(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public IntStream mapToInt(ToIntFunction<? super T> mapper) {
+        return getSource().mapToInt(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public LongStream mapToLong(ToLongFunction<? super T> mapper) {
+        return getSource().mapToLong(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
+        return getSource().mapToDouble(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
+        return getSource().flatMap(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
+        return getSource().flatMapToInt(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
+        return getSource().flatMapToLong(mapper);
+    }
+
+    /**
+     * Returns a stream with results of applying the given function to the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
+        return getSource().flatMapToDouble(mapper);
+    }
+
+    /**
+     * Returns a stream with distinct elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> distinct() {
+        return getSource().distinct();
+    }
+
+    /**
+     * Returns a stream with elements of this stream sorted in natural order.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> sorted() {
+        return getSource().sorted();
+    }
+
+    /**
+     * Returns a stream with elements of this stream sorted using the given comparator.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> sorted(Comparator<? super T> comparator) {
+        return getSource().sorted(comparator);
+    }
+
+    /**
+     * Returns a stream performing the specified action on each element when consumed.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> peek(Consumer<? super T> action) {
+        return getSource().peek(action);
+    }
+
+    /**
+     * Returns a stream with truncated at the given number of elements.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> limit(long maxSize) {
+        return getSource().limit(maxSize);
+    }
+
+    /**
+     * Returns a stream discarding the specified number of elements.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     * Note that in default implementation, the returned stream is not wrapped anymore.
+     */
+    @Override
+    public Stream<T> skip(long n) {
+        return getSource().skip(n);
+    }
+
+    /**
+     * Performs an action for each element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public void forEach(Consumer<? super T> action) {
+        getSource().forEach(action);
+    }
+
+    /**
+     * Performs an action for each element of this stream in encounter order.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public void forEachOrdered(Consumer<? super T> action) {
+        getSource().forEachOrdered(action);
+    }
+
+    /**
+     * Returns all elements in an array.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Object[] toArray() {
+        return getSource().toArray();
+    }
+
+    /**
+     * Returns all elements in an array.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public <A> A[] toArray(IntFunction<A[]> generator) {
+        return getSource().toArray(generator);
+    }
+
+    /**
+     * Performs a reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public T reduce(T identity, BinaryOperator<T> accumulator) {
+        return getSource().reduce(identity, accumulator);
+    }
+
+    /**
+     * Performs a reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Optional<T> reduce(BinaryOperator<T> accumulator) {
+        return getSource().reduce(accumulator);
+    }
+
+    /**
+     * Performs a reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
+        return getSource().reduce(identity, accumulator, combiner);
+    }
+
+    /**
+     * Performs a mutable reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
+        return getSource().collect(supplier, accumulator, combiner);
+    }
+
+    /**
+     * Performs a mutable reduction on the elements of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public <R, A> R collect(Collector<? super T, A, R> collector) {
+        return getSource().collect(collector);
+    }
+
+    /**
+     * Returns the minimum element of this stream according to the provided comparator.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Optional<T> min(Comparator<? super T> comparator) {
+        return getSource().min(comparator);
+    }
+
+    /**
+     * Returns the maximum element of this stream according to the provided comparator.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Optional<T> max(Comparator<? super T> comparator) {
+        return getSource().max(comparator);
+    }
+
+    /**
+     * Returns the number of elements in this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public long count() {
+        return getSource().count();
+    }
+
+    /**
+     * Returns whether at least one element of this stream matches the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean anyMatch(Predicate<? super T> predicate) {
+        return getSource().anyMatch(predicate);
+    }
+
+    /**
+     * Returns whether all elements of this stream match the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean allMatch(Predicate<? super T> predicate) {
+        return getSource().allMatch(predicate);
+    }
+
+    /**
+     * Returns whether none element of this stream match the provided predicate.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public boolean noneMatch(Predicate<? super T> predicate) {
+        return getSource().noneMatch(predicate);
+    }
+
+    /**
+     * Returns the first element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Optional<T> findFirst() {
+        return getSource().findFirst();
+    }
+
+    /**
+     * Returns any element of this stream.
+     * Default implementation delegates to the {@linkplain #getSource() source} stream.
+     */
+    @Override
+    public Optional<T> findAny() {
+        return getSource().findAny();
+    }
+}


Mime
View raw message