/** * * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved. * * Licensed 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 com.speedment.runtime.core.internal.stream.builder; import com.speedment.runtime.core.internal.stream.builder.action.reference.*; import com.speedment.runtime.core.internal.stream.builder.pipeline.PipelineImpl; import com.speedment.runtime.core.internal.stream.builder.pipeline.ReferencePipeline; import com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminator; import java.util.*; import static java.util.Objects.requireNonNull; import java.util.function.*; import java.util.stream.*; import com.speedment.runtime.core.internal.util.java9.Java9StreamAdditions; /** * * @author pemi * @param <T> steam type */ public final class ReferenceStreamBuilder<T> extends AbstractStreamBuilder<ReferenceStreamBuilder<T>, ReferencePipeline<T>> implements Stream<T>, Java9StreamAdditions<T> { ReferenceStreamBuilder(PipelineImpl<?> pipeline, final StreamTerminator streamTerminator, Set<BaseStream<?, ?>> streamSet) { super(pipeline, streamTerminator, streamSet); streamSet.add(this); // Add this new stream to the streamSet so it may be closed later } public ReferenceStreamBuilder(PipelineImpl<?> pipeline, final StreamTerminator streamTerminator) { this(pipeline, streamTerminator, newStreamSet()); } @Override public Stream<T> filter(Predicate<? super T> predicate) { requireNonNull(predicate); return append(new FilterAction<>(predicate)); } @Override public <R> Stream<R> map(Function<? super T, ? extends R> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new ReferenceStreamBuilder<R>(pipeline, streamTerminator, streamSet).append(new MapAction<>(mapper)); } @Override public IntStream mapToInt(ToIntFunction<? super T> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new IntStreamBuilder(pipeline, streamTerminator, streamSet).append(new MapToIntAction<>(mapper)); } @Override public LongStream mapToLong(ToLongFunction<? super T> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new LongStreamBuilder(pipeline, streamTerminator, streamSet).append(new MapToLongAction<>(mapper)); } @Override public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new DoubleStreamBuilder(pipeline, streamTerminator, streamSet).append(new MapToDoubleAction<>(mapper)); } @Override public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new ReferenceStreamBuilder<R>(pipeline, streamTerminator, streamSet).append(new FlatMapAction<>(mapper)); } @Override public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new IntStreamBuilder(pipeline, streamTerminator, streamSet).append(new FlatMapToIntAction<>(mapper)); } @Override public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new LongStreamBuilder(pipeline, streamTerminator, streamSet).append(new FlatMapToLongAction<>(mapper)); } @Override public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) { requireNonNull(mapper); assertNotLinkedOrConsumedAndSet(); return new DoubleStreamBuilder(pipeline, streamTerminator, streamSet).append(new FlatMapToDoubleAction<>(mapper)); } @Override public Stream<T> distinct() { return append(new DistinctAction<>()); } @Override public Stream<T> sorted() { return append(new SortedAction<>()); } @Override public Stream<T> sorted(Comparator<? super T> comparator) { requireNonNull(comparator); return append(new SortedComparatorAction<>(comparator)); } @Override public Stream<T> peek(Consumer<? super T> action) { requireNonNull(action); return append(new PeekAction<>(action)); } @Override public Stream<T> limit(long maxSize) { return append(new LimitAction<>(maxSize)); } @Override public Stream<T> skip(long n) { return append(new SkipAction<>(n)); } @Override public Stream<T> takeWhile(Predicate<? super T> predicate) { requireNonNull(predicate); return append(new TakeWhileAction<>(predicate)); } @Override public Stream<T> dropWhile(Predicate<? super T> predicate) { requireNonNull(predicate); return append(new DropWhileAction<>(predicate)); } // Terminal operations /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public void forEach(Consumer<? super T> action) { requireNonNull(action); assertNotLinkedOrConsumedAndSet(); finallyClose(() -> streamTerminator.forEach(pipeline(), action)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public void forEachOrdered(Consumer<? super T> action) { requireNonNull(action); assertNotLinkedOrConsumedAndSet(); finallyClose(() -> streamTerminator.forEachOrdered(pipeline(), action)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Object[] toArray() { assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.toArray(pipeline())); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public <A> A[] toArray(IntFunction<A[]> generator) { requireNonNull(generator); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.toArray(pipeline(), generator)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public T reduce(T identity, BinaryOperator<T> accumulator) { requireNonNull(identity); requireNonNull(accumulator); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.reduce(pipeline(), identity, accumulator)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Optional<T> reduce(BinaryOperator<T> accumulator) { requireNonNull(accumulator); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.reduce(pipeline(), accumulator)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) { requireNonNull(identity); requireNonNull(accumulator); requireNonNull(combiner); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.reduce(pipeline(), identity, accumulator, combiner)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) { requireNonNull(supplier); requireNonNull(accumulator); requireNonNull(combiner); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.collect(pipeline(), supplier, accumulator, combiner)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public <R, A> R collect(Collector<? super T, A, R> collector) { requireNonNull(collector); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.collect(pipeline(), collector)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Optional<T> min(Comparator<? super T> comparator) { requireNonNull(comparator); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.min(pipeline(), comparator)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Optional<T> max(Comparator<? super T> comparator) { requireNonNull(comparator); assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.max(pipeline(), comparator)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public long count() { assertNotLinkedOrConsumedAndSet(); return finallyCloseLong(() -> streamTerminator.count(pipeline())); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public boolean anyMatch(Predicate<? super T> predicate) { requireNonNull(predicate); assertNotLinkedOrConsumedAndSet(); return finallyCloseBoolean(() -> streamTerminator.anyMatch(pipeline(), predicate)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public boolean allMatch(Predicate<? super T> predicate) { requireNonNull(predicate); assertNotLinkedOrConsumedAndSet(); return finallyCloseBoolean(() -> streamTerminator.allMatch(pipeline(), predicate)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public boolean noneMatch(Predicate<? super T> predicate) { requireNonNull(predicate); assertNotLinkedOrConsumedAndSet(); return finallyCloseBoolean(() -> streamTerminator.noneMatch(pipeline(), predicate)); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Optional<T> findFirst() { assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.findFirst(pipeline())); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline and * closes the stream automatically when a terminal operation is performed. * */ @Override public Optional<T> findAny() { assertNotLinkedOrConsumedAndSet(); return finallyCloseReference(() -> streamTerminator.findAny(pipeline())); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline. * <p> * If you call this method, you <em>must</em> ensure to call the stream's * {@link #close() } method or else resources may not be released properly. * */ @Override public Iterator<T> iterator() { assertNotLinkedOrConsumedAndSet(); //throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); return streamTerminator.iterator(pipeline()); } /** * {@inheritDoc} * * <p> * N.B. This method may short-circuit operations in the Stream pipeline. * <p> * If you call this method, you <em>must</em> ensure to call the stream's * {@link #close() } method or else resources may not be released properly. * */ @Override public Spliterator<T> spliterator() { assertNotLinkedOrConsumedAndSet(); //throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); return streamTerminator.spliterator(pipeline()); } }