package org.infinispan.stream.impl;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.concurrent.TimeUnit;
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 org.infinispan.BaseCacheStream;
import org.infinispan.Cache;
import org.infinispan.CacheStream;
import org.infinispan.DoubleCacheStream;
import org.infinispan.IntCacheStream;
import org.infinispan.LongCacheStream;
import org.infinispan.stream.impl.local.LocalCacheStream;
import org.infinispan.util.function.SerializableBiConsumer;
import org.infinispan.util.function.SerializableBiFunction;
import org.infinispan.util.function.SerializableBinaryOperator;
import org.infinispan.util.function.SerializableComparator;
import org.infinispan.util.function.SerializableConsumer;
import org.infinispan.util.function.SerializableFunction;
import org.infinispan.util.function.SerializableIntFunction;
import org.infinispan.util.function.SerializablePredicate;
import org.infinispan.util.function.SerializableSupplier;
import org.infinispan.util.function.SerializableToDoubleFunction;
import org.infinispan.util.function.SerializableToIntFunction;
import org.infinispan.util.function.SerializableToLongFunction;
/**
* An intermediate cache stream used when an intermediate operation that requires both a remote and local portion
*/
public class IntermediateCacheStream<R> implements CacheStream<R> {
private BaseCacheStream remoteStream;
private final IntermediateType type;
private LocalCacheStream<R> localStream;
private final IntermediateCacheStreamSupplier supplier;
public IntermediateCacheStream(DistributedCacheStream<R> remoteStream) {
this.remoteStream = remoteStream;
this.type = IntermediateType.REF;
this.supplier = new IntermediateCacheStreamSupplier(type, remoteStream);
this.localStream = new LocalCacheStream<>(supplier, remoteStream.parallel,
remoteStream.registry);
}
public IntermediateCacheStream(BaseCacheStream remoteStream, IntermediateType type,
LocalCacheStream<R> localStream, IntermediateCacheStreamSupplier supplier) {
this.remoteStream = remoteStream;
this.type = type;
this.localStream = localStream;
this.supplier = supplier;
}
@Override
public CacheStream<R> sequentialDistribution() {
remoteStream = remoteStream.sequentialDistribution();
return this;
}
@Override
public CacheStream<R> parallelDistribution() {
remoteStream = remoteStream.parallelDistribution();
return this;
}
@Override
public CacheStream<R> filterKeySegments(Set<Integer> segments) {
remoteStream = remoteStream.filterKeySegments(segments);
return this;
}
@Override
public CacheStream<R> filterKeys(Set<?> keys) {
remoteStream = remoteStream.filterKeys(keys);
return this;
}
@Override
public CacheStream<R> distributedBatchSize(int batchSize) {
remoteStream = remoteStream.distributedBatchSize(batchSize);
return this;
}
@Override
public CacheStream<R> segmentCompletionListener(SegmentCompletionListener listener) {
throw new UnsupportedOperationException("Segment completion listener is only supported when no intermediate " +
"operation is provided (sorted, distinct, limit, skip)");
}
@Override
public CacheStream<R> disableRehashAware() {
remoteStream = remoteStream.disableRehashAware();
return this;
}
@Override
public CacheStream<R> timeout(long timeout, TimeUnit unit) {
remoteStream = remoteStream.timeout(timeout, unit);
return this;
}
@Override
public boolean isParallel() {
return localStream.isParallel();
}
@Override
public CacheStream<R> sorted() {
localStream = localStream.sorted();
return this;
}
@Override
public CacheStream<R> sorted(Comparator<? super R> comparator) {
localStream = localStream.sorted(comparator);
return this;
}
@Override
public CacheStream<R> sorted(SerializableComparator<? super R> comparator) {
return sorted((Comparator<? super R>) comparator);
}
@Override
public CacheStream<R> limit(long maxSize) {
localStream = localStream.limit(maxSize);
return this;
}
@Override
public CacheStream<R> skip(long n) {
localStream = localStream.skip(n);
return this;
}
@Override
public CacheStream<R> peek(Consumer<? super R> action) {
localStream = localStream.peek(action);
return this;
}
@Override
public CacheStream<R> peek(SerializableConsumer<? super R> action) {
return peek((Consumer<? super R>) action);
}
@Override
public CacheStream<R> distinct() {
localStream = localStream.distinct();
return this;
}
@Override
public CacheStream<R> filter(Predicate<? super R> predicate) {
localStream = localStream.filter(predicate);
return this;
}
@Override
public CacheStream<R> filter(SerializablePredicate<? super R> predicate) {
return filter((Predicate<? super R>) predicate);
}
@Override
public <R1> CacheStream<R1> map(Function<? super R, ? extends R1> mapper) {
localStream = (LocalCacheStream<R>) localStream.map(mapper);
return (CacheStream<R1>) this;
}
@Override
public <R1> CacheStream<R1> map(SerializableFunction<? super R, ? extends R1> mapper) {
return map((Function<? super R, ? extends R1>) mapper);
}
@Override
public DoubleCacheStream mapToDouble(ToDoubleFunction<? super R> mapper) {
return new IntermediateDoubleCacheStream(remoteStream, type, localStream.mapToDouble(mapper), supplier);
}
@Override
public DoubleCacheStream mapToDouble(SerializableToDoubleFunction<? super R> mapper) {
return mapToDouble((ToDoubleFunction<? super R>) mapper);
}
@Override
public IntCacheStream mapToInt(ToIntFunction<? super R> mapper) {
return new IntermediateIntCacheStream(remoteStream, type, localStream.mapToInt(mapper), supplier);
}
@Override
public IntCacheStream mapToInt(SerializableToIntFunction<? super R> mapper) {
return mapToInt((ToIntFunction<? super R>) mapper);
}
@Override
public LongCacheStream mapToLong(ToLongFunction<? super R> mapper) {
return new IntermediateLongCacheStream(remoteStream, type, localStream.mapToLong(mapper), supplier);
}
@Override
public LongCacheStream mapToLong(SerializableToLongFunction<? super R> mapper) {
return mapToLong((ToLongFunction<? super R>) mapper);
}
@Override
public <R1> CacheStream<R1> flatMap(Function<? super R, ? extends Stream<? extends R1>> mapper) {
localStream = (LocalCacheStream<R>) localStream.flatMap(mapper);
return (CacheStream<R1>) this;
}
@Override
public <R1> CacheStream<R1> flatMap(SerializableFunction<? super R, ? extends Stream<? extends R1>> mapper) {
return flatMap((Function<? super R, ? extends Stream<? extends R1>>) mapper);
}
@Override
public DoubleCacheStream flatMapToDouble(Function<? super R, ? extends DoubleStream> mapper) {
return new IntermediateDoubleCacheStream(remoteStream, type, localStream.flatMapToDouble(mapper), supplier);
}
@Override
public DoubleCacheStream flatMapToDouble(SerializableFunction<? super R, ? extends DoubleStream> mapper) {
return flatMapToDouble((Function<? super R, ? extends DoubleStream>) mapper);
}
@Override
public IntCacheStream flatMapToInt(Function<? super R, ? extends IntStream> mapper) {
return new IntermediateIntCacheStream(remoteStream, type, localStream.flatMapToInt(mapper), supplier);
}
@Override
public IntCacheStream flatMapToInt(SerializableFunction<? super R, ? extends IntStream> mapper) {
return flatMapToInt((Function<? super R, ? extends IntStream>) mapper);
}
@Override
public LongCacheStream flatMapToLong(Function<? super R, ? extends LongStream> mapper) {
return new IntermediateLongCacheStream(remoteStream, type, localStream.flatMapToLong(mapper), supplier);
}
@Override
public LongCacheStream flatMapToLong(SerializableFunction<? super R, ? extends LongStream> mapper) {
return flatMapToLong((Function<? super R, ? extends LongStream>) mapper);
}
@Override
public CacheStream<R> parallel() {
remoteStream = (BaseCacheStream) remoteStream.parallel();
localStream = (LocalCacheStream) localStream.parallel();
return this;
}
@Override
public CacheStream<R> sequential() {
remoteStream = (BaseCacheStream) remoteStream.sequential();
localStream = (LocalCacheStream) localStream.sequential();
return this;
}
@Override
public CacheStream<R> unordered() {
localStream = (LocalCacheStream<R>) localStream.unordered();
return this;
}
@Override
public void forEach(Consumer<? super R> action) {
localStream.forEach(action);
}
@Override
public void forEach(SerializableConsumer<? super R> action) {
forEach((Consumer<? super R>) action);
}
@Override
public void forEachOrdered(Consumer<? super R> action) {
localStream.forEachOrdered(action);
}
@Override
public <K, V> void forEach(BiConsumer<Cache<K, V>, ? super R> action) {
localStream.forEach(action);
}
@Override
public <K, V> void forEach(SerializableBiConsumer<Cache<K, V>, ? super R> action) {
forEach((BiConsumer<Cache<K, V>, ? super R>) action);
}
@Override
public R reduce(R identity, BinaryOperator<R> accumulator) {
return localStream.reduce(identity, accumulator);
}
@Override
public R reduce(R identity, SerializableBinaryOperator<R> accumulator) {
return reduce(identity, (BinaryOperator<R>) accumulator);
}
@Override
public Optional<R> reduce(BinaryOperator<R> accumulator) {
return localStream.reduce(accumulator);
}
@Override
public Optional<R> reduce(SerializableBinaryOperator<R> accumulator) {
return reduce((BinaryOperator<R>) accumulator);
}
@Override
public <U> U reduce(U identity, BiFunction<U, ? super R, U> accumulator, BinaryOperator<U> combiner) {
return localStream.reduce(identity, accumulator, combiner);
}
@Override
public <U> U reduce(U identity, SerializableBiFunction<U, ? super R, U> accumulator, SerializableBinaryOperator<U> combiner) {
return reduce(identity, (BiFunction<U, ? super R, U>) accumulator, combiner);
}
@Override
public <R1, A> R1 collect(Collector<? super R, A, R1> collector) {
return localStream.collect(collector);
}
@Override
public <R1> R1 collect(Supplier<R1> supplier, BiConsumer<R1, ? super R> accumulator, BiConsumer<R1, R1> combiner) {
return localStream.collect(supplier, accumulator, combiner);
}
@Override
public <R1> R1 collect(SerializableSupplier<R1> supplier, SerializableBiConsumer<R1, ? super R> accumulator,
SerializableBiConsumer<R1, R1> combiner) {
return collect((Supplier<R1>) supplier, accumulator, combiner);
}
@Override
public Optional<R> max(Comparator<? super R> comparator) {
return localStream.max(comparator);
}
@Override
public Optional<R> max(SerializableComparator<? super R> comparator) {
return max((Comparator<? super R>) comparator);
}
@Override
public Optional<R> min(Comparator<? super R> comparator) {
return localStream.min(comparator);
}
@Override
public Optional<R> min(SerializableComparator<? super R> comparator) {
return min((Comparator<? super R>) comparator);
}
@Override
public long count() {
return localStream.count();
}
@Override
public boolean anyMatch(Predicate<? super R> predicate) {
return localStream.anyMatch(predicate);
}
@Override
public boolean anyMatch(SerializablePredicate<? super R> predicate) {
return anyMatch((Predicate<? super R>) predicate);
}
@Override
public boolean allMatch(Predicate<? super R> predicate) {
return localStream.allMatch(predicate);
}
@Override
public boolean allMatch(SerializablePredicate<? super R> predicate) {
return allMatch((Predicate<? super R>) predicate);
}
@Override
public boolean noneMatch(Predicate<? super R> predicate) {
return localStream.noneMatch(predicate);
}
@Override
public boolean noneMatch(SerializablePredicate<? super R> predicate) {
return noneMatch((Predicate<? super R>) predicate);
}
@Override
public Optional<R> findFirst() {
return localStream.findFirst();
}
@Override
public Optional<R> findAny() {
return localStream.findAny();
}
@Override
public Iterator<R> iterator() {
return localStream.iterator();
}
@Override
public Spliterator<R> spliterator() {
return localStream.spliterator();
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <A> A[] toArray(IntFunction<A[]> generator) {
return localStream.toArray(generator);
}
@Override
public <A> A[] toArray(SerializableIntFunction<A[]> generator) {
return toArray((IntFunction<A[]>) generator);
}
@Override
public CacheStream<R> onClose(Runnable closeHandler) {
remoteStream = (BaseCacheStream) remoteStream.onClose(closeHandler);
return this;
}
@Override
public void close() {
localStream.close();
remoteStream.close();
}
}