1 /**
2  * Copyright (C) 2009 Google Inc.
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 com.google.inject.spi;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21 
22 import com.google.inject.Binder;
23 import com.google.inject.MembersInjector;
24 import com.google.inject.TypeLiteral;
25 
26 /**
27  * A lookup of the members injector for a type. Lookups are created explicitly in a module using
28  * {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements:
29  * <pre>
30  *     MembersInjector&lt;PaymentService&gt; membersInjector
31  *         = getMembersInjector(PaymentService.class);</pre>
32  *
33  * @author crazybob@google.com (Bob Lee)
34  * @since 2.0
35  */
36 public final class MembersInjectorLookup<T> implements Element {
37 
38   private final Object source;
39   private final TypeLiteral<T> type;
40   private MembersInjector<T> delegate;
41 
MembersInjectorLookup(Object source, TypeLiteral<T> type)42   public MembersInjectorLookup(Object source, TypeLiteral<T> type) {
43     this.source = checkNotNull(source, "source");
44     this.type = checkNotNull(type, "type");
45   }
46 
getSource()47   public Object getSource() {
48     return source;
49   }
50 
51   /**
52    * Gets the type containing the members to be injected.
53    */
getType()54   public TypeLiteral<T> getType() {
55     return type;
56   }
57 
acceptVisitor(ElementVisitor<T> visitor)58   public <T> T acceptVisitor(ElementVisitor<T> visitor) {
59     return visitor.visit(this);
60   }
61 
62   /**
63    * Sets the actual members injector.
64    *
65    * @throws IllegalStateException if the delegate is already set
66    */
initializeDelegate(MembersInjector<T> delegate)67   public void initializeDelegate(MembersInjector<T> delegate) {
68     checkState(this.delegate == null, "delegate already initialized");
69     this.delegate = checkNotNull(delegate, "delegate");
70   }
71 
applyTo(Binder binder)72   public void applyTo(Binder binder) {
73     initializeDelegate(binder.withSource(getSource()).getMembersInjector(type));
74   }
75 
76   /**
77    * Returns the delegate members injector, or {@code null} if it has not yet been initialized.
78    * The delegate will be initialized when this element is processed, or otherwise used to create
79    * an injector.
80    */
getDelegate()81   public MembersInjector<T> getDelegate() {
82     return delegate;
83   }
84 
85   /**
86    * Returns the looked up members injector. The result is not valid until this lookup has been
87    * initialized, which usually happens when the injector is created. The members injector will
88    * throw an {@code IllegalStateException} if you try to use it beforehand.
89    */
getMembersInjector()90   public MembersInjector<T> getMembersInjector() {
91     return new MembersInjector<T>() {
92       public void injectMembers(T instance) {
93         checkState(delegate != null,
94             "This MembersInjector cannot be used until the Injector has been created.");
95         delegate.injectMembers(instance);
96       }
97 
98       @Override public String toString() {
99         return "MembersInjector<" + type + ">";
100       }
101     };
102   }
103 }