7e89be8199ffde443888e328830c88f73b17b60f
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / concurrent / MappingCheckedFuture.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.util.concurrent;
10
11 import com.google.common.base.Function;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.AbstractCheckedFuture;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.util.concurrent.CancellationException;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.TimeUnit;
18 import java.util.concurrent.TimeoutException;
19
20 /**
21  * An implementation of CheckedFuture that provides similar behavior for the <code>get</code> methods
22  * that the <code>checkedGet</code> methods provide.
23  *
24  * <p>For {@link CancellationException} and {@link InterruptedException}, the specified exception mapper
25  * is invoked to translate them to the checked exception type.
26  *
27  * <p>For {@link ExecutionException}, the mapper is invoked to translate the cause to the checked exception
28  * and a new ExecutionException is thrown with the translated cause.
29  *
30  * @author Thomas Pantelis
31  *
32  * @param <V> The result type returned by this Future's get method
33  * @param <X> The checked exception type
34  */
35 public final class MappingCheckedFuture<V, X extends Exception> extends AbstractCheckedFuture<V, X> {
36
37     private final Function<Exception, X> mapper;
38
39     private MappingCheckedFuture( final ListenableFuture<V> delegate, final Function<Exception, X> mapper ) {
40         super( delegate );
41         this.mapper = Preconditions.checkNotNull( mapper );
42     }
43
44     /**
45      * Creates a new <code>MappingCheckedFuture</code> that wraps the given {@link ListenableFuture}
46      * delegate.
47      *
48      * @param delegate the {@link ListenableFuture} to wrap
49      * @param mapper the mapping {@link Function} used to translate exceptions from the delegate
50      * @return a new <code>MappingCheckedFuture</code>
51      */
52     public static <V, X extends Exception> MappingCheckedFuture<V, X> create(
53             final ListenableFuture<V> delegate, final Function<Exception, X> mapper ) {
54         return new MappingCheckedFuture<>(delegate, mapper);
55     }
56
57     @Override
58     protected X mapException( final Exception e ) {
59         return mapper.apply( e );
60     }
61
62     private ExecutionException wrapInExecutionException( final String message, final Exception e ) {
63         return new ExecutionException( message, mapException( e ) );
64     }
65
66     @Override
67     public V get() throws InterruptedException, ExecutionException {
68         try {
69             return super.get();
70         } catch (final InterruptedException e) {
71             Thread.currentThread().interrupt();
72             throw wrapInExecutionException( "Operation was interrupted", e );
73         } catch (final CancellationException e) {
74             throw wrapInExecutionException( "Operation was cancelled", e );
75         } catch (final ExecutionException e) {
76             throw wrapInExecutionException( e.getMessage(), e );
77         }
78     }
79
80     @Override
81     public V get( final long timeout, final TimeUnit unit )
82             throws InterruptedException, ExecutionException, TimeoutException {
83         try {
84             return super.get( timeout, unit );
85         } catch (final InterruptedException e) {
86             Thread.currentThread().interrupt();
87             throw wrapInExecutionException( "Operation was interrupted", e );
88         } catch (final CancellationException e) {
89             throw wrapInExecutionException( "Operation was cancelled", e );
90         } catch (final ExecutionException e) {
91             throw wrapInExecutionException( e.getMessage(), e );
92         }
93     }
94 }