com.apple.foundationdb.async.WrappingAsyncPeekIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fdb-extensions Show documentation
Show all versions of fdb-extensions Show documentation
Extensions to the FoundationDB Java API.
/*
* WrappingAsyncPeekIterator.java
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2015-2018 Apple Inc. and the FoundationDB project authors
*
* 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.apple.foundationdb.async;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An implementation of the {@link AsyncPeekIterator} interface that wraps a regular
* {@link AsyncPeekIterator}. It will return the same items as the iterator it wraps
* in the same order, but it allows for peek semantics. Users should call the
* {@link AsyncPeekIterator#wrap(AsyncIterator) wrap()} method of
* AsyncPeekIterator
instead of instantiating this class directly.
*
* @param type of elements returned by this iterator
*/
class WrappingAsyncPeekIterator implements AsyncPeekCallbackIterator {
@Nonnull
private AsyncIterator underlying;
@Nullable
private CompletableFuture hasNextFuture;
private boolean done;
private boolean hasCurrent;
@Nullable
private T nextItem;
@Nonnull
private Consumer callback;
WrappingAsyncPeekIterator(@Nonnull AsyncIterator underlying) {
this(underlying, t -> { });
}
WrappingAsyncPeekIterator(@Nonnull AsyncIterator underlying, @Nonnull Consumer callback) {
this.underlying = underlying;
this.callback = callback;
this.done = false;
this.hasCurrent = false;
}
@Override
public CompletableFuture onHasNext() {
if (done) {
return AsyncUtil.READY_FALSE;
} else if (hasCurrent) {
return AsyncUtil.READY_TRUE;
}
if (hasNextFuture == null) {
hasNextFuture = underlying.onHasNext().thenApply(doesHaveNext -> {
if (doesHaveNext) {
hasCurrent = true;
nextItem = underlying.next();
callback.accept(nextItem);
} else {
done = true;
}
return doesHaveNext;
});
}
return hasNextFuture;
}
@Override
public boolean hasNext() {
return onHasNext().join();
}
@Override
public T peek() {
if (done) {
throw new NoSuchElementException();
} else if (hasCurrent || hasNext()) {
return nextItem;
} else {
throw new NoSuchElementException();
}
}
@Override
public T next() {
T val = peek();
hasNextFuture = null;
hasCurrent = false;
return val;
}
@Override
public void cancel() {
underlying.cancel();
}
@Override
public void setCallback(@Nonnull Consumer callback) {
this.callback = callback;
}
@Override
@Nonnull
public Consumer getCallback() {
return callback;
}
}