1 /* 2 * Copyright (C) 2015 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.internal.codegen; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static dagger.internal.codegen.SourceFiles.setFactoryClassName; 21 22 import com.squareup.javapoet.CodeBlock; 23 import dagger.model.DependencyRequest; 24 import dagger.producers.Produced; 25 import java.util.Optional; 26 27 /** A factory creation expression for a multibound set. */ 28 final class SetFactoryCreationExpression extends MultibindingFactoryCreationExpression { 29 30 private final ComponentImplementation componentImplementation; 31 private final BindingGraph graph; 32 private final ContributionBinding binding; 33 SetFactoryCreationExpression( ContributionBinding binding, ComponentImplementation componentImplementation, ComponentBindingExpressions componentBindingExpressions, BindingGraph graph)34 SetFactoryCreationExpression( 35 ContributionBinding binding, 36 ComponentImplementation componentImplementation, 37 ComponentBindingExpressions componentBindingExpressions, 38 BindingGraph graph) { 39 super(binding, componentImplementation, componentBindingExpressions); 40 this.binding = checkNotNull(binding); 41 this.componentImplementation = checkNotNull(componentImplementation); 42 this.graph = checkNotNull(graph); 43 } 44 45 @Override creationExpression()46 public CodeBlock creationExpression() { 47 CodeBlock.Builder builder = CodeBlock.builder().add("$T.", setFactoryClassName(binding)); 48 if (!useRawType()) { 49 SetType setType = SetType.from(binding.key()); 50 builder.add( 51 "<$T>", 52 setType.elementsAreTypeOf(Produced.class) 53 ? setType.unwrappedElementType(Produced.class) 54 : setType.elementType()); 55 } 56 57 int individualProviders = 0; 58 int setProviders = 0; 59 CodeBlock.Builder builderMethodCalls = CodeBlock.builder(); 60 String methodNameSuffix = 61 binding.bindingType().equals(BindingType.PROVISION) ? "Provider" : "Producer"; 62 63 Optional<CodeBlock> superContributions = superContributions(); 64 if (superContributions.isPresent()) { 65 // TODO(b/117833324): consider decomposing the Provider<Set<Provider>> and adding the 66 // individual contributions separately from the collection contributions. Though this may 67 // actually not be doable/desirable if the super provider instance is a DelegateFactory or 68 // another internal type that is not SetFactory 69 builderMethodCalls.add(".addCollection$N($L)", methodNameSuffix, superContributions.get()); 70 setProviders++; 71 } 72 73 for (DependencyRequest dependency : dependenciesToImplement()) { 74 ContributionType contributionType = 75 graph.contributionBindings().get(dependency.key()).contributionType(); 76 String methodNamePrefix; 77 switch (contributionType) { 78 case SET: 79 individualProviders++; 80 methodNamePrefix = "add"; 81 break; 82 case SET_VALUES: 83 setProviders++; 84 methodNamePrefix = "addCollection"; 85 break; 86 default: 87 throw new AssertionError(dependency + " is not a set multibinding"); 88 } 89 90 builderMethodCalls.add( 91 ".$N$N($L)", 92 methodNamePrefix, 93 methodNameSuffix, 94 multibindingDependencyExpression(dependency)); 95 } 96 builder.add("builder($L, $L)", individualProviders, setProviders); 97 builder.add(builderMethodCalls.build()); 98 99 componentImplementation.registerImplementedMultibinding(binding, bindingRequest()); 100 101 return builder.add(".build()").build(); 102 } 103 } 104