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