• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Dagger Authors.
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 
17 package dagger.functional.producers.subcomponent;
18 
19 import com.google.common.util.concurrent.ListenableFuture;
20 import dagger.Component;
21 import dagger.Module;
22 import dagger.Provides;
23 import dagger.producers.ProducerModule;
24 import dagger.producers.Produces;
25 import dagger.producers.Production;
26 import dagger.producers.ProductionComponent;
27 import dagger.producers.ProductionSubcomponent;
28 import java.util.concurrent.Executor;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import javax.inject.Inject;
31 import javax.inject.Provider;
32 import javax.inject.Qualifier;
33 
34 final class SubcomponentsWithBoundExecutor {
35   @Qualifier
36   @interface FromParent {}
37 
38   @Qualifier
39   @interface FromChild {}
40 
41   @Qualifier
42   @interface FromGrandchild {}
43 
44   static final class CountingExecutor implements Executor {
45     private final AtomicInteger executionCount;
46 
CountingExecutor(AtomicInteger executionCount)47     CountingExecutor(AtomicInteger executionCount) {
48       this.executionCount = executionCount;
49     }
50 
51     @Override
execute(Runnable runnable)52     public void execute(Runnable runnable) {
53       executionCount.incrementAndGet();
54       runnable.run();
55     }
56   }
57 
58   @Module
59   static final class ExecutorModule {
60     private final AtomicInteger constructionCount;
61     private final AtomicInteger executionCount;
62 
ExecutorModule(AtomicInteger constructionCount, AtomicInteger executionCount)63     ExecutorModule(AtomicInteger constructionCount, AtomicInteger executionCount) {
64       this.constructionCount = constructionCount;
65       this.executionCount = executionCount;
66     }
67 
68     @Provides
69     @Production
executor()70     Executor executor() {
71       constructionCount.incrementAndGet();
72       return new CountingExecutor(executionCount);
73     }
74   }
75 
76   @Module
77   static final class ParentModule {
78     @Provides
79     @FromParent
fromParent()80     static String fromParent() {
81       return "parent";
82     }
83   }
84 
85   @Component(modules = {ParentModule.class, ExecutorModule.class})
86   interface ParentComponent {
injectsChildBuilder()87     InjectsChildBuilder injectsChildBuilder();
88 
newChildComponentBuilder()89     ChildComponent.Builder newChildComponentBuilder();
90   }
91 
92   @ProducerModule
93   static final class ParentProducerModule {
94     @Produces
95     @FromParent
fromParent()96     static String fromParent() {
97       return "parentproduction";
98     }
99   }
100 
101   @ProductionComponent(modules = {ParentProducerModule.class, ExecutorModule.class})
102   interface ParentProductionComponent {
newChildComponentBuilder()103     ChildComponent.Builder newChildComponentBuilder();
104 
105     @ProductionComponent.Builder
106     interface Builder {
executorModule(ExecutorModule executorModule)107       Builder executorModule(ExecutorModule executorModule);
108 
build()109       ParentProductionComponent build();
110     }
111   }
112 
113   @ProducerModule
114   static final class ChildProducerModule {
115     @Produces
116     @FromChild
fromChild(@romParent String fromParent)117     static String fromChild(@FromParent String fromParent) {
118       return "child:" + fromParent;
119     }
120   }
121 
122   @ProductionSubcomponent(modules = ChildProducerModule.class)
123   interface ChildComponent {
124     @FromChild
fromChild()125     ListenableFuture<String> fromChild();
126 
newGrandchildComponentBuilder()127     GrandchildComponent.Builder newGrandchildComponentBuilder();
newGrandchildComponent()128     GrandchildComponentWithoutBuilder newGrandchildComponent();
129 
130     @ProductionSubcomponent.Builder
131     interface Builder {
build()132       ChildComponent build();
133     }
134   }
135 
136   static final class InjectsChildBuilder {
137     private final Provider<ChildComponent.Builder> childBuilder;
138 
139     @Inject
InjectsChildBuilder(Provider<ChildComponent.Builder> childBuilder)140     InjectsChildBuilder(Provider<ChildComponent.Builder> childBuilder) {
141       this.childBuilder = childBuilder;
142     }
143 
childBuilder()144     ChildComponent.Builder childBuilder() {
145       return childBuilder.get();
146     }
147   }
148 
149   @ProducerModule
150   static final class GrandchildProducerModule {
151     @Produces
152     @FromGrandchild
fromGranchild(@romChild String fromChild)153     static String fromGranchild(@FromChild String fromChild) {
154       return "grandchild:" + fromChild;
155     }
156   }
157 
158   @ProductionSubcomponent(modules = GrandchildProducerModule.class)
159   interface GrandchildComponent {
160     @FromGrandchild
fromGrandchild()161     ListenableFuture<String> fromGrandchild();
162 
163     @ProductionSubcomponent.Builder
164     interface Builder {
build()165       GrandchildComponent build();
166     }
167   }
168 
169   @ProductionSubcomponent(modules = GrandchildProducerModule.class)
170   interface GrandchildComponentWithoutBuilder {
171     @FromGrandchild
fromGrandchild()172     ListenableFuture<String> fromGrandchild();
173   }
174 
SubcomponentsWithBoundExecutor()175   private SubcomponentsWithBoundExecutor() {}
176 }
177