001/*
002 * Copyright 2002-2016 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
021/**
022 * Abstract class that adapts a {@link ListenableFuture} parameterized over S into a
023 * {@code ListenableFuture} parameterized over T. All methods are delegated to the
024 * adaptee, where {@link #get()}, {@link #get(long, java.util.concurrent.TimeUnit)},
025 * and {@link ListenableFutureCallback#onSuccess(Object)} call {@link #adapt(Object)}
026 * on the adaptee's result.
027 *
028 * @author Arjen Poutsma
029 * @since 4.0
030 * @param <T> the type of this {@code Future}
031 * @param <S> the type of the adaptee's {@code Future}
032 */
033public abstract class ListenableFutureAdapter<T, S> extends FutureAdapter<T, S> implements ListenableFuture<T> {
034
035        /**
036         * Construct a new {@code ListenableFutureAdapter} with the given adaptee.
037         * @param adaptee the future to adapt to
038         */
039        protected ListenableFutureAdapter(ListenableFuture<S> adaptee) {
040                super(adaptee);
041        }
042
043
044        @Override
045        public void addCallback(final ListenableFutureCallback<? super T> callback) {
046                addCallback(callback, callback);
047        }
048
049        @Override
050        public void addCallback(final SuccessCallback<? super T> successCallback, final FailureCallback failureCallback) {
051                ListenableFuture<S> listenableAdaptee = (ListenableFuture<S>) getAdaptee();
052                listenableAdaptee.addCallback(new ListenableFutureCallback<S>() {
053                        @Override
054                        public void onSuccess(S result) {
055                                T adapted;
056                                try {
057                                        adapted = adaptInternal(result);
058                                }
059                                catch (ExecutionException ex) {
060                                        Throwable cause = ex.getCause();
061                                        onFailure(cause != null ? cause : ex);
062                                        return;
063                                }
064                                catch (Throwable ex) {
065                                        onFailure(ex);
066                                        return;
067                                }
068                                successCallback.onSuccess(adapted);
069                        }
070                        @Override
071                        public void onFailure(Throwable ex) {
072                                failureCallback.onFailure(ex);
073                        }
074                });
075        }
076
077}