package org.infinispan.stream.impl.local;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Queue;
import java.util.Set;
import java.util.stream.BaseStream;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.factories.ComponentRegistry;
import org.infinispan.stream.impl.intops.IntermediateOperation;
import org.infinispan.stream.impl.intops.UnorderedOperation;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* Implements the base operations required for a local stream.
* stream is populated
*/
public abstract class AbstractLocalCacheStream<T, S extends BaseStream<T, S>, S2 extends S> implements BaseStream<T, S> {
protected final Log log = LogFactory.getLog(getClass());
protected final StreamSupplier<T, S> streamSupplier;
protected final ComponentRegistry registry;
protected final Collection<Runnable> onCloseRunnables;
protected final Queue<IntermediateOperation> intermediateOperations;
protected Set<Integer> segmentsToFilter;
protected Set<?> keysToFilter;
protected boolean parallel;
public interface StreamSupplier<T, S extends BaseStream<T, S>> {
S buildStream(Set<Integer> segmentsToFilter, Set<?> keysToFilter);
CloseableIterator<T> removableIterator(CloseableIterator<T> realIterator);
}
/**
* @param streamSupplier
* @param parallel
* @param registry
*/
public AbstractLocalCacheStream(StreamSupplier<T, S> streamSupplier, boolean parallel, ComponentRegistry registry) {
this.streamSupplier = streamSupplier;
this.registry = registry;
this.onCloseRunnables = new ArrayList<>(4);
this.intermediateOperations = new ArrayDeque<>();
this.parallel = parallel;
}
AbstractLocalCacheStream(AbstractLocalCacheStream<?, ?, ?> original) {
this.streamSupplier = (StreamSupplier<T, S>) original.streamSupplier;
this.registry = original.registry;
this.onCloseRunnables = original.onCloseRunnables;
this.intermediateOperations = original.intermediateOperations;
this.segmentsToFilter = original.segmentsToFilter;
this.keysToFilter = original.keysToFilter;
this.parallel = original.parallel;
}
protected final S createStream() {
BaseStream<?, ?> stream = streamSupplier.buildStream(segmentsToFilter, keysToFilter);
if (parallel) {
stream = stream.parallel();
}
for (IntermediateOperation intOp : intermediateOperations) {
stream = intOp.perform(stream);
}
return (S) stream;
}
@Override
public boolean isParallel() {
return parallel;
}
@Override
public S2 sequential() {
this.parallel = false;
return (S2) this;
}
@Override
public S2 parallel() {
this.parallel = true;
return (S2) this;
}
@Override
public S2 unordered() {
intermediateOperations.add(new UnorderedOperation<>());
return (S2) this;
}
@Override
public S2 onClose(Runnable closeHandler) {
onCloseRunnables.add(closeHandler);
return (S2) this;
}
@Override
public void close() {
onCloseRunnables.forEach(Runnable::run);
}
}