1 /* 2 * Copyright (C) 2014 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.binding; 18 19 import static com.google.common.base.Suppliers.memoize; 20 import static dagger.internal.codegen.xprocessing.XElements.isAbstract; 21 import static dagger.internal.codegen.xprocessing.XElements.isStatic; 22 23 import com.google.common.base.Supplier; 24 import com.google.common.collect.ImmutableSet; 25 import com.google.common.collect.Sets; 26 import dagger.internal.codegen.model.BindingKind; 27 import dagger.internal.codegen.model.DependencyRequest; 28 import dagger.internal.codegen.model.Scope; 29 import java.util.Optional; 30 31 /** 32 * An abstract type for classes representing a Dagger binding. Particularly, contains the element 33 * that generated the binding and the {@link DependencyRequest} instances that are required to 34 * satisfy the binding, but leaves the specifics of the <i>mechanism</i> of the binding to the 35 * subtypes. 36 */ 37 public abstract class Binding extends BindingDeclaration { 38 39 /** 40 * Returns {@code true} if using this binding requires an instance of the {@link 41 * #contributingModule()}. 42 */ requiresModuleInstance()43 public boolean requiresModuleInstance() { 44 return contributingModule().isPresent() 45 && bindingElement().isPresent() 46 && !isAbstract(bindingElement().get()) 47 && !isStatic(bindingElement().get()); 48 } 49 50 /** 51 * Returns {@code true} if this binding may provide {@code null} instead of an instance of {@link 52 * #key()}. Nullable bindings cannot be requested from {@linkplain DependencyRequest#isNullable() 53 * non-nullable dependency requests}. 54 */ isNullable()55 public abstract boolean isNullable(); 56 57 /** The kind of binding this instance represents. */ kind()58 public abstract BindingKind kind(); 59 60 /** The {@link BindingType} of this binding. */ bindingType()61 public abstract BindingType bindingType(); 62 63 /** The {@link FrameworkType} of this binding. */ frameworkType()64 public final FrameworkType frameworkType() { 65 return FrameworkType.forBindingType(bindingType()); 66 } 67 68 /** 69 * The explicit set of {@link DependencyRequest dependencies} required to satisfy this binding as 70 * defined by the user-defined injection sites. 71 */ explicitDependencies()72 public abstract ImmutableSet<DependencyRequest> explicitDependencies(); 73 74 /** 75 * The set of {@link DependencyRequest dependencies} that are added by the framework rather than a 76 * user-defined injection site. This returns an unmodifiable set. 77 */ implicitDependencies()78 public ImmutableSet<DependencyRequest> implicitDependencies() { 79 return ImmutableSet.of(); 80 } 81 82 private final Supplier<ImmutableSet<DependencyRequest>> dependencies = 83 memoize( 84 () -> { 85 ImmutableSet<DependencyRequest> implicitDependencies = implicitDependencies(); 86 return ImmutableSet.copyOf( 87 implicitDependencies.isEmpty() 88 ? explicitDependencies() 89 : Sets.union(implicitDependencies, explicitDependencies())); 90 }); 91 92 /** 93 * The set of {@link DependencyRequest dependencies} required to satisfy this binding. This is the 94 * union of {@link #explicitDependencies()} and {@link #implicitDependencies()}. This returns an 95 * unmodifiable set. 96 */ dependencies()97 public final ImmutableSet<DependencyRequest> dependencies() { 98 return dependencies.get(); 99 } 100 101 /** 102 * If this binding's key's type parameters are different from those of the {@link 103 * #bindingTypeElement()}, this is the binding for the {@link #bindingTypeElement()}'s unresolved 104 * type. 105 */ unresolved()106 public abstract Optional<? extends Binding> unresolved(); 107 scope()108 public Optional<Scope> scope() { 109 return Optional.empty(); 110 } 111 } 112