package org.infinispan.stream.impl.termop; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.BaseStream; import org.infinispan.stream.impl.TerminalOperation; import org.infinispan.stream.impl.intops.IntermediateOperation; /** * Runs the provided function once only and returns the result. This is useful for operations that can be performed * and its result is still valid even when a segment is lost. * @param <E> type of the output of the function * @param <R> type of the stream entries * @param <S> type of the stream itself */ public class SingleRunOperation<E, R, S extends BaseStream<R, S>, S2 extends S> extends BaseTerminalOperation implements TerminalOperation<E> { private final Function<? super S2, ? extends E> function; private transient AtomicBoolean complete; public SingleRunOperation(Iterable<IntermediateOperation> intermediateOperations, Supplier<? extends BaseStream<?, ?>> supplier, Function<? super S2, ? extends E> function) { super(intermediateOperations, supplier); this.function = function; this.complete = new AtomicBoolean(); } @Override public boolean lostSegment(boolean stopIfLost) { return !complete.get(); } @Override public E performOperation() { BaseStream<?, ?> stream = supplier.get(); for (IntermediateOperation intOp : intermediateOperations) { stream = intOp.perform(stream); } E value = function.apply((S2) stream); complete.set(true); return value; } public Function<? super S2, ? extends E> getFunction() { return function; } }