net.javacrumbs.futureconverter.guavacommon.GuavaFutureUtils Maven / Gradle / Ivy
/*
* Copyright © 2014-2019 the original author or 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 net.javacrumbs.futureconverter.guavacommon;
import org.apache.rocketmq.shaded.com.google.common.util.concurrent.FutureCallback;
import org.apache.rocketmq.shaded.com.google.common.util.concurrent.Futures;
import org.apache.rocketmq.shaded.com.google.common.util.concurrent.ListenableFuture;
import org.apache.rocketmq.shaded.com.google.common.util.concurrent.MoreExecutors;
import net.javacrumbs.futureconverter.common.internal.FutureWrapper;
import net.javacrumbs.futureconverter.common.internal.ValueSource;
import net.javacrumbs.futureconverter.common.internal.ValueSourceFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
public class GuavaFutureUtils {
// *************************************** Converting to ListenableFuture ******************************************
/**
* Creates listenable future from ValueSourceFuture. We have to send all Future API calls to ValueSourceFuture.
*/
public static ListenableFuture createListenableFuture(ValueSourceFuture valueSourceFuture) {
if (valueSourceFuture instanceof ListenableFutureBackedValueSourceFuture) {
return ((ListenableFutureBackedValueSourceFuture) valueSourceFuture).getWrappedFuture();
} else {
return new ValueSourceFutureBackedListenableFuture<>(valueSourceFuture);
}
}
public static ListenableFuture createListenableFuture(ValueSource valueSource) {
if (valueSource instanceof ListenableFutureBackedValueSourceFuture) {
return ((ListenableFutureBackedValueSourceFuture) valueSource).getWrappedFuture();
} else {
return new ValueSourceBackedListenableFuture<>(valueSource);
}
}
/**
* If we have ValueSourceFuture, we can use it as the implementation and this class only converts
* listener registration.
*/
private static class ValueSourceFutureBackedListenableFuture extends FutureWrapper implements ListenableFuture {
ValueSourceFutureBackedListenableFuture(ValueSourceFuture valueSourceFuture) {
super(valueSourceFuture);
}
@Override
protected ValueSourceFuture getWrappedFuture() {
return (ValueSourceFuture) super.getWrappedFuture();
}
@Override
public void addListener(Runnable listener, Executor executor) {
getWrappedFuture().addCallbacks(value -> executor.execute(listener), ex -> executor.execute(listener));
}
}
/**
* If we only get ValueSource we have to create a ValueSourceFuture. Here we wrap Guavas SettableFuture
* and use it for listener handling and value storage.
*/
private static class ValueSourceBackedListenableFuture extends FutureWrapper implements ListenableFuture {
private final ValueSource valueSource;
private ValueSourceBackedListenableFuture(ValueSource valueSource) {
super(org.apache.rocketmq.shaded.com.google.common.util.concurrent.SettableFuture.create());
this.valueSource = valueSource;
valueSource.addCallbacks(value -> getWrappedFuture().set(value), ex -> getWrappedFuture().setException(ex));
}
@Override
public void addListener(Runnable listener, Executor executor) {
getWrappedFuture().addListener(listener, executor);
}
@Override
protected org.apache.rocketmq.shaded.com.google.common.util.concurrent.SettableFuture getWrappedFuture() {
return (org.apache.rocketmq.shaded.com.google.common.util.concurrent.SettableFuture) super.getWrappedFuture();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
valueSource.cancel(mayInterruptIfRunning);
return super.cancel(mayInterruptIfRunning);
}
private ValueSource getValueSource() {
return valueSource;
}
}
// *************************************** Converting from ListenableFuture ******************************************
public static ValueSourceFuture createValueSourceFuture(ListenableFuture listenableFuture) {
if (listenableFuture instanceof ValueSourceFutureBackedListenableFuture) {
return ((ValueSourceFutureBackedListenableFuture) listenableFuture).getWrappedFuture();
} else {
return new ListenableFutureBackedValueSourceFuture<>(listenableFuture);
}
}
public static ValueSource createValueSource(ListenableFuture listenableFuture) {
if (listenableFuture instanceof ValueSourceBackedListenableFuture) {
return ((ValueSourceBackedListenableFuture) listenableFuture).getValueSource();
} else {
return new ListenableFutureBackedValueSourceFuture<>(listenableFuture);
}
}
/**
* Wraps ListenableFuture and exposes it as ValueSourceFuture.
*/
private static class ListenableFutureBackedValueSourceFuture extends ValueSourceFuture {
private ListenableFutureBackedValueSourceFuture(ListenableFuture wrappedFuture) {
super(wrappedFuture);
}
@Override
public void addCallbacks(Consumer successCallback, Consumer failureCallback) {
Futures.addCallback(getWrappedFuture(), new FutureCallback() {
@Override
public void onSuccess(T result) {
successCallback.accept(result);
}
@Override
public void onFailure(Throwable t) {
failureCallback.accept(t);
}
}, MoreExecutors.directExecutor());
}
@Override
protected ListenableFuture getWrappedFuture() {
return (ListenableFuture) super.getWrappedFuture();
}
}
}