/* * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.util.concurrent; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.AbstractCheckedFuture; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.annotation.Nonnull; /** * An implementation of CheckedFuture that provides similar behavior for the <code>get</code> methods * that the <code>checkedGet</code> methods provide. * * <p>For {@link CancellationException} and {@link InterruptedException}, the specified exception mapper * is invoked to translate them to the checked exception type. * * <p>For {@link ExecutionException}, the mapper is invoked to translate the cause to the checked exception * and a new ExecutionException is thrown with the translated cause. * * @author Thomas Pantelis * * @param <V> The result type returned by this Future's get method * @param <X> The checked exception type */ public final class MappingCheckedFuture<V, X extends Exception> extends AbstractCheckedFuture<V, X> { private final Function<Exception, X> mapper; private MappingCheckedFuture( final ListenableFuture<V> delegate, final Function<Exception, X> mapper ) { super( delegate ); this.mapper = Preconditions.checkNotNull( mapper ); } /** * Creates a new <code>MappingCheckedFuture</code> that wraps the given {@link ListenableFuture} * delegate. * * @param delegate the {@link ListenableFuture} to wrap * @param mapper the mapping {@link Function} used to translate exceptions from the delegate * @return a new <code>MappingCheckedFuture</code> */ public static <V, X extends Exception> MappingCheckedFuture<V, X> create( final ListenableFuture<V> delegate, final Function<Exception, X> mapper ) { return new MappingCheckedFuture<>(delegate, mapper); } @Override protected X mapException( @Nonnull final Exception e ) { return mapper.apply( e ); } private ExecutionException wrapInExecutionException( final String message, final Exception e ) { return new ExecutionException( message, mapException( e ) ); } @Override public V get() throws InterruptedException, ExecutionException { try { return super.get(); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); throw wrapInExecutionException( "Operation was interrupted", e ); } catch (final CancellationException e) { throw wrapInExecutionException( "Operation was cancelled", e ); } catch (final ExecutionException e) { throw wrapInExecutionException( e.getMessage(), e ); } } @Override public V get( final long timeout, @Nonnull final TimeUnit unit ) throws InterruptedException, ExecutionException, TimeoutException { try { return super.get( timeout, unit ); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); throw wrapInExecutionException( "Operation was interrupted", e ); } catch (final CancellationException e) { throw wrapInExecutionException( "Operation was cancelled", e ); } catch (final ExecutionException e) { throw wrapInExecutionException( e.getMessage(), e ); } } }