xref: /aosp_15_r20/external/dagger2/java/dagger/producers/internal/Producers.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2014 The Dagger Authors.
3*f585d8a3SJacky Wang  *
4*f585d8a3SJacky Wang  * Licensed under the Apache License, Version 2.0 (the "License");
5*f585d8a3SJacky Wang  * you may not use this file except in compliance with the License.
6*f585d8a3SJacky Wang  * You may obtain a copy of the License at
7*f585d8a3SJacky Wang  *
8*f585d8a3SJacky Wang  * http://www.apache.org/licenses/LICENSE-2.0
9*f585d8a3SJacky Wang  *
10*f585d8a3SJacky Wang  * Unless required by applicable law or agreed to in writing, software
11*f585d8a3SJacky Wang  * distributed under the License is distributed on an "AS IS" BASIS,
12*f585d8a3SJacky Wang  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f585d8a3SJacky Wang  * See the License for the specific language governing permissions and
14*f585d8a3SJacky Wang  * limitations under the License.
15*f585d8a3SJacky Wang  */
16*f585d8a3SJacky Wang 
17*f585d8a3SJacky Wang package dagger.producers.internal;
18*f585d8a3SJacky Wang 
19*f585d8a3SJacky Wang import static com.google.common.base.Preconditions.checkNotNull;
20*f585d8a3SJacky Wang import static com.google.common.util.concurrent.Futures.catchingAsync;
21*f585d8a3SJacky Wang import static com.google.common.util.concurrent.Futures.transform;
22*f585d8a3SJacky Wang import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
23*f585d8a3SJacky Wang import static dagger.internal.Providers.asDaggerProvider;
24*f585d8a3SJacky Wang 
25*f585d8a3SJacky Wang import com.google.common.base.Function;
26*f585d8a3SJacky Wang import com.google.common.collect.ImmutableMap;
27*f585d8a3SJacky Wang import com.google.common.collect.ImmutableSet;
28*f585d8a3SJacky Wang import com.google.common.util.concurrent.AsyncFunction;
29*f585d8a3SJacky Wang import com.google.common.util.concurrent.Futures;
30*f585d8a3SJacky Wang import com.google.common.util.concurrent.ListenableFuture;
31*f585d8a3SJacky Wang import dagger.internal.Provider;
32*f585d8a3SJacky Wang import dagger.producers.Produced;
33*f585d8a3SJacky Wang import dagger.producers.Producer;
34*f585d8a3SJacky Wang import java.util.List;
35*f585d8a3SJacky Wang import java.util.Map;
36*f585d8a3SJacky Wang import java.util.Set;
37*f585d8a3SJacky Wang 
38*f585d8a3SJacky Wang /**
39*f585d8a3SJacky Wang  * Utility methods for use in generated producer code.
40*f585d8a3SJacky Wang  */
41*f585d8a3SJacky Wang public final class Producers {
42*f585d8a3SJacky Wang   /**
43*f585d8a3SJacky Wang    * Returns a future of {@link Produced} that represents the completion (either success or failure)
44*f585d8a3SJacky Wang    * of the given future. If the input future succeeds, then the resulting future also succeeds with
45*f585d8a3SJacky Wang    * a successful {@code Produced}; if the input future fails, then the resulting future succeeds
46*f585d8a3SJacky Wang    * with a failing {@code Produced}.
47*f585d8a3SJacky Wang    *
48*f585d8a3SJacky Wang    * <p>Cancelling the resulting future will propagate the cancellation to the input future; but
49*f585d8a3SJacky Wang    * cancelling the input future will trigger the resulting future to succeed with a failing
50*f585d8a3SJacky Wang    * {@code Produced}.
51*f585d8a3SJacky Wang    */
52*f585d8a3SJacky Wang   // TODO(beder): Document what happens with an InterruptedException after you figure out how to
53*f585d8a3SJacky Wang   // trigger one in a test.
createFutureProduced(ListenableFuture<T> future)54*f585d8a3SJacky Wang   public static <T> ListenableFuture<Produced<T>> createFutureProduced(ListenableFuture<T> future) {
55*f585d8a3SJacky Wang     return catchingAsync(
56*f585d8a3SJacky Wang         transform(future, Producers.<T>resultToProduced(), directExecutor()),
57*f585d8a3SJacky Wang         Throwable.class,
58*f585d8a3SJacky Wang         Producers.<T>futureFallbackForProduced(),
59*f585d8a3SJacky Wang         directExecutor());
60*f585d8a3SJacky Wang   }
61*f585d8a3SJacky Wang 
62*f585d8a3SJacky Wang   private static final Function<Object, Produced<Object>> RESULT_TO_PRODUCED =
63*f585d8a3SJacky Wang       new Function<Object, Produced<Object>>() {
64*f585d8a3SJacky Wang         @Override
65*f585d8a3SJacky Wang         public Produced<Object> apply(Object result) {
66*f585d8a3SJacky Wang           return Produced.successful(result);
67*f585d8a3SJacky Wang         }
68*f585d8a3SJacky Wang       };
69*f585d8a3SJacky Wang 
70*f585d8a3SJacky Wang   @SuppressWarnings({"unchecked", "rawtypes"}) // bivariant implementation
resultToProduced()71*f585d8a3SJacky Wang   private static <T> Function<T, Produced<T>> resultToProduced() {
72*f585d8a3SJacky Wang     return (Function) RESULT_TO_PRODUCED;
73*f585d8a3SJacky Wang   }
74*f585d8a3SJacky Wang 
75*f585d8a3SJacky Wang   private static final AsyncFunction<Throwable, Produced<Object>> FUTURE_FALLBACK_FOR_PRODUCED =
76*f585d8a3SJacky Wang       new AsyncFunction<Throwable, Produced<Object>>() {
77*f585d8a3SJacky Wang         @Override
78*f585d8a3SJacky Wang         public ListenableFuture<Produced<Object>> apply(Throwable t) throws Exception {
79*f585d8a3SJacky Wang           Produced<Object> produced = Produced.failed(t);
80*f585d8a3SJacky Wang           return Futures.immediateFuture(produced);
81*f585d8a3SJacky Wang         }
82*f585d8a3SJacky Wang       };
83*f585d8a3SJacky Wang 
84*f585d8a3SJacky Wang   @SuppressWarnings({"unchecked", "rawtypes"}) // bivariant implementation
futureFallbackForProduced()85*f585d8a3SJacky Wang   private static <T> AsyncFunction<Throwable, Produced<T>> futureFallbackForProduced() {
86*f585d8a3SJacky Wang     return (AsyncFunction) FUTURE_FALLBACK_FOR_PRODUCED;
87*f585d8a3SJacky Wang   }
88*f585d8a3SJacky Wang 
89*f585d8a3SJacky Wang   /**
90*f585d8a3SJacky Wang    * Returns a future of a {@code Set} that contains a single element: the result of the input
91*f585d8a3SJacky Wang    * future.
92*f585d8a3SJacky Wang    */
createFutureSingletonSet(ListenableFuture<T> future)93*f585d8a3SJacky Wang   public static <T> ListenableFuture<Set<T>> createFutureSingletonSet(ListenableFuture<T> future) {
94*f585d8a3SJacky Wang     return transform(
95*f585d8a3SJacky Wang         future,
96*f585d8a3SJacky Wang         new Function<T, Set<T>>() {
97*f585d8a3SJacky Wang           @Override
98*f585d8a3SJacky Wang           public Set<T> apply(T value) {
99*f585d8a3SJacky Wang             return ImmutableSet.of(value);
100*f585d8a3SJacky Wang           }
101*f585d8a3SJacky Wang         },
102*f585d8a3SJacky Wang         directExecutor());
103*f585d8a3SJacky Wang   }
104*f585d8a3SJacky Wang 
105*f585d8a3SJacky Wang   /**
106*f585d8a3SJacky Wang    * Creates a new {@code ListenableFuture} whose value is a set containing the values of all its
107*f585d8a3SJacky Wang    * input futures, if all succeed. If any input fails, the returned future fails immediately.
108*f585d8a3SJacky Wang    *
109*f585d8a3SJacky Wang    * <p>This is the set equivalent of {@link Futures#allAsList}.
110*f585d8a3SJacky Wang    */
111*f585d8a3SJacky Wang   public static <T> ListenableFuture<Set<T>> allAsSet(
112*f585d8a3SJacky Wang       Iterable<? extends ListenableFuture<? extends T>> futures) {
113*f585d8a3SJacky Wang     return transform(
114*f585d8a3SJacky Wang         Futures.allAsList(futures),
115*f585d8a3SJacky Wang         new Function<List<T>, Set<T>>() {
116*f585d8a3SJacky Wang           @Override
117*f585d8a3SJacky Wang           public Set<T> apply(List<T> values) {
118*f585d8a3SJacky Wang             return ImmutableSet.copyOf(values);
119*f585d8a3SJacky Wang           }
120*f585d8a3SJacky Wang         },
121*f585d8a3SJacky Wang         directExecutor());
122*f585d8a3SJacky Wang   }
123*f585d8a3SJacky Wang 
124*f585d8a3SJacky Wang   /**
125*f585d8a3SJacky Wang    * Returns a producer that immediately executes the binding logic for the given provider every
126*f585d8a3SJacky Wang    * time it is called.
127*f585d8a3SJacky Wang    */
128*f585d8a3SJacky Wang   public static <T> Producer<T> producerFromProvider(final Provider<T> provider) {
129*f585d8a3SJacky Wang     checkNotNull(provider);
130*f585d8a3SJacky Wang     return new CompletedProducer<T>() {
131*f585d8a3SJacky Wang       @Override
132*f585d8a3SJacky Wang       public ListenableFuture<T> get() {
133*f585d8a3SJacky Wang         return Futures.immediateFuture(provider.get());
134*f585d8a3SJacky Wang       }
135*f585d8a3SJacky Wang     };
136*f585d8a3SJacky Wang   }
137*f585d8a3SJacky Wang 
138*f585d8a3SJacky Wang   /**
139*f585d8a3SJacky Wang    * Legacy javax version of the method to support libraries compiled with an older version of
140*f585d8a3SJacky Wang    * Dagger. Do not use directly.
141*f585d8a3SJacky Wang    */
142*f585d8a3SJacky Wang   @Deprecated
143*f585d8a3SJacky Wang   public static <T> Producer<T> producerFromProvider(final javax.inject.Provider<T> provider) {
144*f585d8a3SJacky Wang     return producerFromProvider(asDaggerProvider(provider));
145*f585d8a3SJacky Wang   }
146*f585d8a3SJacky Wang 
147*f585d8a3SJacky Wang   /**
148*f585d8a3SJacky Wang    * Returns a producer that succeeds with the given value.
149*f585d8a3SJacky Wang    *
150*f585d8a3SJacky Wang    * @deprecated Prefer the non-internal version of this method: {@link
151*f585d8a3SJacky Wang    * dagger.producers.Producers#immediateProducer(Object)}.
152*f585d8a3SJacky Wang    */
153*f585d8a3SJacky Wang   @Deprecated
154*f585d8a3SJacky Wang   public static <T> Producer<T> immediateProducer(T value) {
155*f585d8a3SJacky Wang     return dagger.producers.Producers.immediateProducer(value);
156*f585d8a3SJacky Wang   }
157*f585d8a3SJacky Wang 
158*f585d8a3SJacky Wang   /**
159*f585d8a3SJacky Wang    * Returns a producer that fails with the given exception.
160*f585d8a3SJacky Wang    *
161*f585d8a3SJacky Wang    * @deprecated Prefer the non-internal version of this method: {@link
162*f585d8a3SJacky Wang    * dagger.producers.Producers#immediateFailedProducer(Throwable)}.
163*f585d8a3SJacky Wang    */
164*f585d8a3SJacky Wang   @Deprecated
165*f585d8a3SJacky Wang   public static <T> Producer<T> immediateFailedProducer(Throwable throwable) {
166*f585d8a3SJacky Wang     return dagger.producers.Producers.immediateFailedProducer(throwable);
167*f585d8a3SJacky Wang   }
168*f585d8a3SJacky Wang 
169*f585d8a3SJacky Wang   /**
170*f585d8a3SJacky Wang    * Returns a new view of the given {@code producer} if and only if it is a {@link
171*f585d8a3SJacky Wang    * CancellableProducer}. Cancelling the returned producer's future will not cancel the underlying
172*f585d8a3SJacky Wang    * task for the given producer.
173*f585d8a3SJacky Wang    *
174*f585d8a3SJacky Wang    * @throws IllegalArgumentException if {@code producer} is not a {@code CancellableProducer}
175*f585d8a3SJacky Wang    */
176*f585d8a3SJacky Wang   public static <T> Producer<T> nonCancellationPropagatingViewOf(Producer<T> producer) {
177*f585d8a3SJacky Wang     // This is a hack until we change the types of Producer fields to be CancellableProducer or
178*f585d8a3SJacky Wang     // some other type.
179*f585d8a3SJacky Wang     if (producer instanceof CancellableProducer) {
180*f585d8a3SJacky Wang       return ((CancellableProducer<T>) producer).newDependencyView();
181*f585d8a3SJacky Wang     }
182*f585d8a3SJacky Wang     throw new IllegalArgumentException(
183*f585d8a3SJacky Wang         "nonCancellationPropagatingViewOf called with non-CancellableProducer: " + producer);
184*f585d8a3SJacky Wang   }
185*f585d8a3SJacky Wang 
186*f585d8a3SJacky Wang   /**
187*f585d8a3SJacky Wang    * Returns a new view of the given {@code producer} for use as an entry point in a production
188*f585d8a3SJacky Wang    * component, if and only if it is a {@link CancellableProducer}. When the returned producer's
189*f585d8a3SJacky Wang    * future is cancelled, the given {@code cancellable} will also be cancelled.
190*f585d8a3SJacky Wang    *
191*f585d8a3SJacky Wang    * @throws IllegalArgumentException if {@code producer} is not a {@code CancellableProducer}
192*f585d8a3SJacky Wang    */
193*f585d8a3SJacky Wang   public static <T> Producer<T> entryPointViewOf(
194*f585d8a3SJacky Wang       Producer<T> producer, CancellationListener cancellationListener) {
195*f585d8a3SJacky Wang     // This is a hack until we change the types of Producer fields to be CancellableProducer or
196*f585d8a3SJacky Wang     // some other type.
197*f585d8a3SJacky Wang     if (producer instanceof CancellableProducer) {
198*f585d8a3SJacky Wang       return ((CancellableProducer<T>) producer).newEntryPointView(cancellationListener);
199*f585d8a3SJacky Wang     }
200*f585d8a3SJacky Wang     throw new IllegalArgumentException(
201*f585d8a3SJacky Wang         "entryPointViewOf called with non-CancellableProducer: " + producer);
202*f585d8a3SJacky Wang   }
203*f585d8a3SJacky Wang 
204*f585d8a3SJacky Wang   /**
205*f585d8a3SJacky Wang    * Calls {@code cancel} on the given {@code producer} if it is a {@link CancellableProducer}.
206*f585d8a3SJacky Wang    *
207*f585d8a3SJacky Wang    * @throws IllegalArgumentException if {@code producer} is not a {@code CancellableProducer}
208*f585d8a3SJacky Wang    */
209*f585d8a3SJacky Wang   public static void cancel(Producer<?> producer, boolean mayInterruptIfRunning) {
210*f585d8a3SJacky Wang     // This is a hack until we change the types of Producer fields to be CancellableProducer or
211*f585d8a3SJacky Wang     // some other type.
212*f585d8a3SJacky Wang     if (producer instanceof CancellableProducer) {
213*f585d8a3SJacky Wang       ((CancellableProducer<?>) producer).cancel(mayInterruptIfRunning);
214*f585d8a3SJacky Wang     } else {
215*f585d8a3SJacky Wang       throw new IllegalArgumentException("cancel called with non-CancellableProducer: " + producer);
216*f585d8a3SJacky Wang     }
217*f585d8a3SJacky Wang   }
218*f585d8a3SJacky Wang 
219*f585d8a3SJacky Wang   private static final Producer<Map<Object, Object>> EMPTY_MAP_PRODUCER =
220*f585d8a3SJacky Wang       dagger.producers.Producers.<Map<Object, Object>>immediateProducer(ImmutableMap.of());
221*f585d8a3SJacky Wang 
222*f585d8a3SJacky Wang   @SuppressWarnings("unchecked") // safe contravariant cast
223*f585d8a3SJacky Wang   public static <K, V> Producer<Map<K, V>> emptyMapProducer() {
224*f585d8a3SJacky Wang     return (Producer<Map<K, V>>) (Producer) EMPTY_MAP_PRODUCER;
225*f585d8a3SJacky Wang   }
226*f585d8a3SJacky Wang 
227*f585d8a3SJacky Wang   /**
228*f585d8a3SJacky Wang    * A {@link CancellableProducer} which can't be cancelled because it represents an
229*f585d8a3SJacky Wang    * already-completed task.
230*f585d8a3SJacky Wang    */
231*f585d8a3SJacky Wang   private abstract static class CompletedProducer<T> implements CancellableProducer<T> {
232*f585d8a3SJacky Wang     @Override
233*f585d8a3SJacky Wang     public void cancel(boolean mayInterruptIfRunning) {}
234*f585d8a3SJacky Wang 
235*f585d8a3SJacky Wang     @Override
236*f585d8a3SJacky Wang     public Producer<T> newDependencyView() {
237*f585d8a3SJacky Wang       return this;
238*f585d8a3SJacky Wang     }
239*f585d8a3SJacky Wang 
240*f585d8a3SJacky Wang     @Override
241*f585d8a3SJacky Wang     public Producer<T> newEntryPointView(CancellationListener cancellationListener) {
242*f585d8a3SJacky Wang       return this;
243*f585d8a3SJacky Wang     }
244*f585d8a3SJacky Wang   }
245*f585d8a3SJacky Wang 
246*f585d8a3SJacky Wang   private Producers() {}
247*f585d8a3SJacky Wang }
248