package org.infinispan.stream.impl.termop.object; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.BaseStream; import java.util.stream.Stream; import org.infinispan.container.entries.CacheEntry; import org.infinispan.stream.impl.intops.IntermediateOperation; /** * Terminal rehash aware operation that handles an iterator when no flat map or map intermediate operation was performed * on the stream. This is important due to the fact that we can just return the entries as is and the client can sort * out what is the key and what isn't. * @param <K> key type * @param <V> resulting value type */ public class NoMapIteratorOperation<K, V> extends MapIteratorOperation<K, V, V> { public NoMapIteratorOperation(Iterable<IntermediateOperation> intermediateOperations, Supplier<Stream<CacheEntry>> supplier, int batchSize) { super(intermediateOperations, supplier, batchSize); } @Override public boolean lostSegment(boolean stopIfLost) { // TODO: stop this early return true; } @Override public List<V> performOperation(IntermediateCollector<Collection<V>> response) { BaseStream<?, ?> stream = supplier.get(); for (IntermediateOperation intOp : intermediateOperations) { stream = intOp.perform(stream); } Stream<V> convertedStream = ((Stream<V>)stream); return actualPerformOperation(response, convertedStream); } private <R> List<R> actualPerformOperation(IntermediateCollector<Collection<R>> response, Stream<R> stream) { BiConsumer<List<R>, R> accumulator = (l, e) -> { l.add(e); if (l.size() >= batchSize) { response.sendDataResonse(l); l.clear(); } }; // We use collect instead of forEach due to the fact that forEach would require a concurrent // list to handle, where as collect will merge them together in a thread safe way List<R> list = stream.collect(ArrayList::new, accumulator, (l1, l2) -> { l2.forEach(e -> accumulator.accept(l1, e)); }); return list; } @Override public Collection<CacheEntry<K, V>> performOperationRehashAware( IntermediateCollector<Collection<CacheEntry<K, V>>> response) { // We only support sequential streams for iterator rehash aware BaseStream<?, ?> stream = supplier.get().sequential(); for (IntermediateOperation intermediateOperation : intermediateOperations) { stream = intermediateOperation.perform(stream); } return actualPerformOperation(response, (Stream<CacheEntry<K, V>>) stream); } }