001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.util.concurrent;
018
019import java.util.concurrent.ExecutionException;
020
021import org.springframework.lang.Nullable;
022
023/**
024 * Abstract class that adapts a {@link ListenableFuture} parameterized over S into a
025 * {@code ListenableFuture} parameterized over T. All methods are delegated to the
026 * adaptee, where {@link #get()}, {@link #get(long, java.util.concurrent.TimeUnit)},
027 * and {@link ListenableFutureCallback#onSuccess(Object)} call {@link #adapt(Object)}
028 * on the adaptee's result.
029 *
030 * @author Arjen Poutsma
031 * @since 4.0
032 * @param <T> the type of this {@code Future}
033 * @param <S> the type of the adaptee's {@code Future}
034 */
035public abstract class ListenableFutureAdapter<T, S> extends FutureAdapter<T, S> implements ListenableFuture<T> {
036
037        /**
038         * Construct a new {@code ListenableFutureAdapter} with the given adaptee.
039         * @param adaptee the future to adapt to
040         */
041        protected ListenableFutureAdapter(ListenableFuture<S> adaptee) {
042                super(adaptee);
043        }
044
045
046        @Override
047        public void addCallback(final ListenableFutureCallback<? super T> callback) {
048                addCallback(callback, callback);
049        }
050
051        @Override
052        public void addCallback(final SuccessCallback<? super T> successCallback, final FailureCallback failureCallback) {
053                ListenableFuture<S> listenableAdaptee = (ListenableFuture<S>) getAdaptee();
054                listenableAdaptee.addCallback(new ListenableFutureCallback<S>() {
055                        @Override
056                        public void onSuccess(@Nullable S result) {
057                                T adapted = null;
058                                if (result != null) {
059                                        try {
060                                                adapted = adaptInternal(result);
061                                        }
062                                        catch (ExecutionException ex) {
063                                                Throwable cause = ex.getCause();
064                                                onFailure(cause != null ? cause : ex);
065                                                return;
066                                        }
067                                        catch (Throwable ex) {
068                                                onFailure(ex);
069                                                return;
070                                        }
071                                }
072                                successCallback.onSuccess(adapted);
073                        }
074                        @Override
075                        public void onFailure(Throwable ex) {
076                                failureCallback.onFailure(ex);
077                        }
078                });
079        }
080
081}