/**
*
* 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.common.mutablestream;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Optional;
import java.util.Spliterator;
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;
import com.speedment.common.mutablestream.action.DistinctAction;
import com.speedment.common.mutablestream.action.FilterAction;
import com.speedment.common.mutablestream.action.FlatMapAction;
import com.speedment.common.mutablestream.action.FlatMapToDoubleAction;
import com.speedment.common.mutablestream.action.FlatMapToIntAction;
import com.speedment.common.mutablestream.action.FlatMapToLongAction;
import com.speedment.common.mutablestream.action.LimitAction;
import com.speedment.common.mutablestream.action.MapAction;
import com.speedment.common.mutablestream.action.MapToDoubleAction;
import com.speedment.common.mutablestream.action.MapToIntAction;
import com.speedment.common.mutablestream.action.MapToLongAction;
import com.speedment.common.mutablestream.action.SkipAction;
import com.speedment.common.mutablestream.action.SortedAction;
import com.speedment.common.mutablestream.terminate.AllMatchTerminator;
import com.speedment.common.mutablestream.terminate.AnyMatchTerminator;
import com.speedment.common.mutablestream.terminate.CollectTerminator;
import com.speedment.common.mutablestream.terminate.CountTerminator;
import com.speedment.common.mutablestream.terminate.FindAnyTerminator;
import com.speedment.common.mutablestream.terminate.FindFirstTerminator;
import com.speedment.common.mutablestream.terminate.ForEachOrderedTerminator;
import com.speedment.common.mutablestream.terminate.ForEachTerminator;
import com.speedment.common.mutablestream.terminate.IteratorTerminator;
import com.speedment.common.mutablestream.terminate.MaxTerminator;
import com.speedment.common.mutablestream.terminate.MinTerminator;
import com.speedment.common.mutablestream.terminate.NoneMatchTerminator;
import com.speedment.common.mutablestream.terminate.ReduceTerminator;
import com.speedment.common.mutablestream.terminate.SpliteratorTerminator;
import com.speedment.common.mutablestream.terminate.ToArrayTerminator;
import static java.util.Objects.requireNonNull;
/**
*
* @param <T> the type of the stream
*
* @author Emil Forslund
* @since 1.0.0
*/
public final class MutableStream<T> implements Stream<T> {
public static <T> Stream<T> wrap(HasNext<T, Stream<T>> pipeline) {
return internalWrap(pipeline, false);
}
static <T> Stream<T> internalWrap(HasNext<T, Stream<T>> pipeline, boolean parallel) {
return new MutableStream<>(pipeline, parallel);
}
/**************************************************************************/
/* Intermediate Actions */
/**************************************************************************/
@Override
@SuppressWarnings("unchecked")
public Stream<T> filter(Predicate<? super T> filter) {
return internalWrap(pipeline.append(FilterAction.create(pipeline, (Predicate<T>) filter)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
return internalWrap(pipeline.append(MapAction.create(pipeline, (Function<T, R>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public IntStream mapToInt(ToIntFunction<? super T> mapper) {
return MutableIntStream.internalWrap(pipeline.append(MapToIntAction.create(pipeline, (ToIntFunction<T>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public LongStream mapToLong(ToLongFunction<? super T> mapper) {
return MutableLongStream.internalWrap(pipeline.append(MapToLongAction.create(pipeline, (ToLongFunction<T>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
return MutableDoubleStream.internalWrap(pipeline.append(MapToDoubleAction.create(pipeline, (ToDoubleFunction<T>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
return internalWrap(pipeline.append(FlatMapAction.create(pipeline, (Function<T, Stream<R>>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
return MutableIntStream.internalWrap(pipeline.append(FlatMapToIntAction.create(pipeline, (Function<T, IntStream>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
return MutableLongStream.internalWrap(pipeline.append(FlatMapToLongAction.create(pipeline, (Function<T, LongStream>) mapper)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
return MutableDoubleStream.internalWrap(pipeline.append(FlatMapToDoubleAction.create(pipeline, (Function<T, DoubleStream>) mapper)), parallel);
}
@Override
public Stream<T> distinct() {
return internalWrap(pipeline.append(DistinctAction.create(pipeline)), parallel);
}
@Override
public Stream<T> sorted() {
return internalWrap(pipeline.append(SortedAction.create(pipeline)), parallel);
}
@Override
@SuppressWarnings("unchecked")
public Stream<T> sorted(Comparator<? super T> comparator) {
return internalWrap(pipeline.append(SortedAction.create(pipeline, (Comparator<T>) comparator)), parallel);
}
@Override
public Stream<T> peek(Consumer<? super T> cnsmr) {
// Mutable Streams can not be peeked inside since they might not be
// resolved as a stream at all.
return this;
}
@Override
public Stream<T> limit(long limit) {
return internalWrap(pipeline.append(LimitAction.create(pipeline, limit)), parallel);
}
@Override
public Stream<T> skip(long skip) {
return internalWrap(pipeline.append(SkipAction.create(pipeline, skip)), parallel);
}
/**************************************************************************/
/* Terminating Actions */
/**************************************************************************/
@Override
@SuppressWarnings("unchecked")
public void forEach(Consumer<? super T> consumer) {
pipeline.execute(ForEachTerminator.create(pipeline, parallel, (Consumer<T>) consumer));
}
@Override
@SuppressWarnings("unchecked")
public void forEachOrdered(Consumer<? super T> consumer) {
pipeline.execute(ForEachOrderedTerminator.create(pipeline, parallel, (Consumer<T>) consumer));
}
@Override
public Object[] toArray() {
return pipeline.execute(ToArrayTerminator.create(pipeline, parallel, Object[]::new));
}
@Override
public <A> A[] toArray(IntFunction<A[]> instantiator) {
return pipeline.execute(ToArrayTerminator.create(pipeline, parallel, instantiator));
}
@Override
public T reduce(T identity, BinaryOperator<T> combiner) {
return pipeline.execute(ReduceTerminator.create(pipeline, parallel, identity, combiner));
}
@Override
public Optional<T> reduce(BinaryOperator<T> combiner) {
return Optional.ofNullable(pipeline.execute(ReduceTerminator.create(pipeline, parallel, combiner)));
}
@Override
@SuppressWarnings("unchecked")
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
return pipeline.execute(ReduceTerminator.create(pipeline, parallel, identity, (BiFunction<U, T, U>) accumulator, combiner));
}
@Override
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
return pipeline.execute(CollectTerminator.create(pipeline, parallel, supplier, accumulator, combiner));
}
@Override
@SuppressWarnings("unchecked")
public <R, A> R collect(Collector<? super T, A, R> collector) {
return pipeline.execute(CollectTerminator.create(pipeline, parallel, (Collector<T, A, R>) collector));
}
@Override
@SuppressWarnings("unchecked")
public Optional<T> min(Comparator<? super T> comparator) {
return pipeline.execute(MinTerminator.create(pipeline, parallel, (Comparator<T>) comparator));
}
@Override
@SuppressWarnings("unchecked")
public Optional<T> max(Comparator<? super T> comparator) {
return pipeline.execute(MaxTerminator.create(pipeline, parallel, (Comparator<T>) comparator));
}
@Override
public long count() {
return pipeline.execute(CountTerminator.create(pipeline, parallel));
}
@Override
@SuppressWarnings("unchecked")
public boolean anyMatch(Predicate<? super T> predicate) {
return pipeline.execute(AnyMatchTerminator.create(pipeline, parallel, (Predicate<T>) predicate));
}
@Override
@SuppressWarnings("unchecked")
public boolean allMatch(Predicate<? super T> predicate) {
return pipeline.execute(AllMatchTerminator.create(pipeline, parallel, (Predicate<T>) predicate));
}
@Override
@SuppressWarnings("unchecked")
public boolean noneMatch(Predicate<? super T> predicate) {
return pipeline.execute(NoneMatchTerminator.create(pipeline, parallel, (Predicate<T>) predicate));
}
@Override
public Optional<T> findFirst() {
return pipeline.execute(FindFirstTerminator.create(pipeline, parallel));
}
@Override
public Optional<T> findAny() {
return pipeline.execute(FindAnyTerminator.create(pipeline, parallel));
}
@Override
public Iterator<T> iterator() {
return pipeline.execute(IteratorTerminator.create(pipeline, parallel));
}
@Override
public Spliterator<T> spliterator() {
return pipeline.execute(SpliteratorTerminator.create(pipeline, parallel));
}
/**************************************************************************/
/* Inherited Methods from Base Stream */
/**************************************************************************/
@Override
public boolean isParallel() {
return parallel;
}
@Override
public Stream<T> sequential() {
return parallel ? internalWrap(pipeline, false) : this;
}
@Override
public Stream<T> parallel() {
return parallel ? this : internalWrap(pipeline, true);
}
@Override
public Stream<T> unordered() {
return this;
}
@Override
public Stream<T> onClose(Runnable r) {
throw new UnsupportedOperationException(
"Close listeners are not supported by this stream implementation."
);
}
@Override
public void close() {
// Do nothing since close listeners are not supported by this
// implementation of the stream API.
}
/**************************************************************************/
/* Constructor */
/**************************************************************************/
private MutableStream(HasNext<T, Stream<T>> pipeline, boolean parallel) {
this.pipeline = requireNonNull(pipeline);
this.parallel = parallel;
}
private final HasNext<T, Stream<T>> pipeline;
private final boolean parallel;
}