• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 Google, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package dagger.producers.internal;
17 
18 import com.google.common.base.Function;
19 import com.google.common.collect.ImmutableSet;
20 import com.google.common.util.concurrent.FutureFallback;
21 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import dagger.producers.Produced;
24 import dagger.producers.Producer;
25 import dagger.producers.monitoring.ProducerMonitor;
26 import java.util.Set;
27 import javax.inject.Provider;
28 
29 import static com.google.common.base.Preconditions.checkNotNull;
30 
31 /**
32  * Utility methods for use in generated producer code.
33  *
34  * @author Jesse Beder
35  * @since 2.0
36  */
37 public final class Producers {
38   /**
39    * Returns a future of {@link Produced} that represents the completion (either success or failure)
40    * of the given future. If the input future succeeds, then the resulting future also succeeds with
41    * a successful {@code Produced}; if the input future fails, then the resulting future succeeds
42    * with a failing {@code Produced}.
43    *
44    * <p>Cancelling the resulting future will propagate the cancellation to the input future; but
45    * cancelling the input future will trigger the resulting future to succeed with a failing
46    * {@code Produced}.
47    */
48   // TODO(user): Document what happens with an InterruptedException after you figure out how to
49   // trigger one in a test.
createFutureProduced(ListenableFuture<T> future)50   public static <T> ListenableFuture<Produced<T>> createFutureProduced(ListenableFuture<T> future) {
51     // TODO(dpb): Switch to Futures.catchAsync once guava_jdk5 gets to v19.
52     return Futures.withFallback(
53         Futures.transform(
54             future,
55             new Function<T, Produced<T>>() {
56               @Override
57               public Produced<T> apply(final T value) {
58                 return Produced.successful(value);
59               }
60             }),
61         Producers.<T>futureFallbackForProduced());
62 
63   }
64 
65   private static final FutureFallback<Produced<Object>> FUTURE_FALLBACK_FOR_PRODUCED =
66       new FutureFallback<Produced<Object>>() {
67     @Override public ListenableFuture<Produced<Object>> create(final Throwable t) {
68       Produced<Object> produced = Produced.failed(t);
69       return Futures.immediateFuture(produced);
70     }
71   };
72 
73   @SuppressWarnings({"unchecked", "rawtypes"})  // bivariant implementation
74   private static <T> FutureFallback<Produced<T>> futureFallbackForProduced() {
75     return (FutureFallback) FUTURE_FALLBACK_FOR_PRODUCED;
76   }
77 
78   /**
79    * Returns a future of a {@code Set} that contains a single element: the result of the input
80    * future.
81    */
82   public static <T> ListenableFuture<Set<T>> createFutureSingletonSet(ListenableFuture<T> future) {
83     return Futures.transform(future, new Function<T, Set<T>>() {
84       @Override public Set<T> apply(T value) {
85         return ImmutableSet.of(value);
86       }
87     });
88   }
89 
90   /**
91    * Returns a producer that immediately executes the binding logic for the given provider every
92    * time it is called.
93    */
94   public static <T> Producer<T> producerFromProvider(final Provider<T> provider) {
95     checkNotNull(provider);
96     return new AbstractProducer<T>() {
97       @Override
98       protected ListenableFuture<T> compute(ProducerMonitor unusedMonitor) {
99         return Futures.immediateFuture(provider.get());
100       }
101     };
102   }
103 
104   /** Returns a producer that succeeds with the given value. */
105   public static <T> Producer<T> immediateProducer(final T value) {
106     return new Producer<T>() {
107       @Override
108       public ListenableFuture<T> get() {
109         return Futures.immediateFuture(value);
110       }
111     };
112   }
113 
114   /** Returns a producer that fails with the given exception. */
115   public static <T> Producer<T> immediateFailedProducer(final Throwable throwable) {
116     return new Producer<T>() {
117       @Override
118       public ListenableFuture<T> get() {
119         return Futures.immediateFailedFuture(throwable);
120       }
121     };
122   }
123 
124   private Producers() {}
125 }
126