xref: /aosp_15_r20/external/dagger2/java/dagger/producers/internal/AbstractProducesMethodProducer.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2018 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 dagger.internal.Preconditions.checkNotNull;
20*f585d8a3SJacky Wang import static dagger.internal.Providers.asDaggerProvider;
21*f585d8a3SJacky Wang 
22*f585d8a3SJacky Wang import com.google.common.util.concurrent.AsyncFunction;
23*f585d8a3SJacky Wang import com.google.common.util.concurrent.Futures;
24*f585d8a3SJacky Wang import com.google.common.util.concurrent.ListenableFuture;
25*f585d8a3SJacky Wang import dagger.internal.Provider;
26*f585d8a3SJacky Wang import dagger.producers.monitoring.ProducerMonitor;
27*f585d8a3SJacky Wang import dagger.producers.monitoring.ProducerToken;
28*f585d8a3SJacky Wang import dagger.producers.monitoring.ProductionComponentMonitor;
29*f585d8a3SJacky Wang import java.util.concurrent.Executor;
30*f585d8a3SJacky Wang import org.checkerframework.checker.nullness.compatqual.NullableDecl;
31*f585d8a3SJacky Wang 
32*f585d8a3SJacky Wang /**
33*f585d8a3SJacky Wang  * An {@link AbstractProducer} for all {@link dagger.producers.Produces} methods.
34*f585d8a3SJacky Wang  *
35*f585d8a3SJacky Wang  * @param <D> the type of asynchronous dependencies. These will be collected in {@link
36*f585d8a3SJacky Wang  *     #collectDependencies()} and then made available to the {@code @Produces method in} {@link
37*f585d8a3SJacky Wang  *     #callProducesMethod(Object)}. If there is only one asynchronous dependency, {@code D} can be
38*f585d8a3SJacky Wang  *     the key for that dependency. If there are multiple, they should be wrapped in a list and
39*f585d8a3SJacky Wang  *     unwrapped in {@link #callProducesMethod(Object)}.
40*f585d8a3SJacky Wang  * @param <T> the produced type
41*f585d8a3SJacky Wang  */
42*f585d8a3SJacky Wang public abstract class AbstractProducesMethodProducer<D, T> extends AbstractProducer<T>
43*f585d8a3SJacky Wang     implements AsyncFunction<D, T>, Executor {
44*f585d8a3SJacky Wang   private final Provider<ProductionComponentMonitor> monitorProvider;
45*f585d8a3SJacky Wang   @NullableDecl private final ProducerToken token;
46*f585d8a3SJacky Wang   private final Provider<Executor> executorProvider;
47*f585d8a3SJacky Wang   private volatile ProducerMonitor monitor = null;
48*f585d8a3SJacky Wang 
AbstractProducesMethodProducer( Provider<ProductionComponentMonitor> monitorProvider, @NullableDecl ProducerToken token, Provider<Executor> executorProvider)49*f585d8a3SJacky Wang   protected AbstractProducesMethodProducer(
50*f585d8a3SJacky Wang       Provider<ProductionComponentMonitor> monitorProvider,
51*f585d8a3SJacky Wang       @NullableDecl ProducerToken token,
52*f585d8a3SJacky Wang       Provider<Executor> executorProvider) {
53*f585d8a3SJacky Wang     this.monitorProvider = checkNotNull(monitorProvider);
54*f585d8a3SJacky Wang     this.token = token;
55*f585d8a3SJacky Wang     this.executorProvider = checkNotNull(executorProvider);
56*f585d8a3SJacky Wang   }
57*f585d8a3SJacky Wang 
58*f585d8a3SJacky Wang   /**
59*f585d8a3SJacky Wang    * Legacy javax version of the method to support libraries compiled with an older version of
60*f585d8a3SJacky Wang    * Dagger. Do not use directly.
61*f585d8a3SJacky Wang    */
62*f585d8a3SJacky Wang   @Deprecated
AbstractProducesMethodProducer( javax.inject.Provider<ProductionComponentMonitor> monitorProvider, @NullableDecl ProducerToken token, javax.inject.Provider<Executor> executorProvider)63*f585d8a3SJacky Wang   protected AbstractProducesMethodProducer(
64*f585d8a3SJacky Wang       javax.inject.Provider<ProductionComponentMonitor> monitorProvider,
65*f585d8a3SJacky Wang       @NullableDecl ProducerToken token,
66*f585d8a3SJacky Wang       javax.inject.Provider<Executor> executorProvider) {
67*f585d8a3SJacky Wang     this(asDaggerProvider(monitorProvider), token, asDaggerProvider(executorProvider));
68*f585d8a3SJacky Wang   }
69*f585d8a3SJacky Wang 
70*f585d8a3SJacky Wang   @Override
compute()71*f585d8a3SJacky Wang   protected final ListenableFuture<T> compute() {
72*f585d8a3SJacky Wang     monitor = monitorProvider.get().producerMonitorFor(token);
73*f585d8a3SJacky Wang     monitor.requested();
74*f585d8a3SJacky Wang     ListenableFuture<T> result = Futures.transformAsync(collectDependencies(), this, this);
75*f585d8a3SJacky Wang     monitor.addCallbackTo(result);
76*f585d8a3SJacky Wang     return result;
77*f585d8a3SJacky Wang   }
78*f585d8a3SJacky Wang 
79*f585d8a3SJacky Wang   /**
80*f585d8a3SJacky Wang    * Collects the asynchronous dependencies to be passed to {@link
81*f585d8a3SJacky Wang    * Futures#transformAsync(ListenableFuture, AsyncFunction, Executor)}.
82*f585d8a3SJacky Wang    */
collectDependencies()83*f585d8a3SJacky Wang   protected abstract ListenableFuture<D> collectDependencies();
84*f585d8a3SJacky Wang 
85*f585d8a3SJacky Wang   /** @deprecated this may only be called from the internal {@link #compute()} */
86*f585d8a3SJacky Wang   @Deprecated
87*f585d8a3SJacky Wang   @Override
apply(D asyncDependencies)88*f585d8a3SJacky Wang   public final ListenableFuture<T> apply(D asyncDependencies) throws Exception {
89*f585d8a3SJacky Wang     // NOTE(beder): We don't worry about catching exceptions from the monitor methods themselves
90*f585d8a3SJacky Wang     // because we'll wrap all monitoring in non-throwing monitors before we pass them to the
91*f585d8a3SJacky Wang     // factories.
92*f585d8a3SJacky Wang     monitor.methodStarting();
93*f585d8a3SJacky Wang     try {
94*f585d8a3SJacky Wang       return callProducesMethod(asyncDependencies);
95*f585d8a3SJacky Wang     } finally {
96*f585d8a3SJacky Wang       monitor.methodFinished();
97*f585d8a3SJacky Wang     }
98*f585d8a3SJacky Wang   }
99*f585d8a3SJacky Wang 
100*f585d8a3SJacky Wang   /**
101*f585d8a3SJacky Wang    * Calls the {@link dagger.producers.Produces} method. This will always be called on the {@link
102*f585d8a3SJacky Wang    * Executor} provided to this producer.
103*f585d8a3SJacky Wang    */
callProducesMethod(D asyncDependencies)104*f585d8a3SJacky Wang   protected abstract ListenableFuture<T> callProducesMethod(D asyncDependencies) throws Exception;
105*f585d8a3SJacky Wang 
106*f585d8a3SJacky Wang   /** @deprecated this may only be called from the internal {@link #compute()} */
107*f585d8a3SJacky Wang   @Deprecated
108*f585d8a3SJacky Wang   @Override
execute(Runnable runnable)109*f585d8a3SJacky Wang   public final void execute(Runnable runnable) {
110*f585d8a3SJacky Wang     monitor.ready();
111*f585d8a3SJacky Wang     executorProvider.get().execute(runnable);
112*f585d8a3SJacky Wang   }
113*f585d8a3SJacky Wang }
114