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