• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *
30  * <pre>
31  *     MembersInjector&lt;PaymentService&gt; membersInjector
32  *         = getMembersInjector(PaymentService.class);</pre>
33  *
34  * @author crazybob@google.com (Bob Lee)
35  * @since 2.0
36  */
37 public final class MembersInjectorLookup<T> implements Element {
38 
39   private final Object source;
40   private final TypeLiteral<T> type;
41   private MembersInjector<T> delegate;
42 
MembersInjectorLookup(Object source, TypeLiteral<T> type)43   public MembersInjectorLookup(Object source, TypeLiteral<T> type) {
44     this.source = checkNotNull(source, "source");
45     this.type = checkNotNull(type, "type");
46   }
47 
48   @Override
getSource()49   public Object getSource() {
50     return source;
51   }
52 
53   /** Gets the type containing the members to be injected. */
getType()54   public TypeLiteral<T> getType() {
55     return type;
56   }
57 
58   @Override
acceptVisitor(ElementVisitor<T> visitor)59   public <T> T acceptVisitor(ElementVisitor<T> visitor) {
60     return visitor.visit(this);
61   }
62 
63   /**
64    * Sets the actual members injector.
65    *
66    * @throws IllegalStateException if the delegate is already set
67    */
initializeDelegate(MembersInjector<T> delegate)68   public void initializeDelegate(MembersInjector<T> delegate) {
69     checkState(this.delegate == null, "delegate already initialized");
70     this.delegate = checkNotNull(delegate, "delegate");
71   }
72 
73   @Override
applyTo(Binder binder)74   public void applyTo(Binder binder) {
75     initializeDelegate(binder.withSource(getSource()).getMembersInjector(type));
76   }
77 
78   /**
79    * Returns the delegate members injector, or {@code null} if it has not yet been initialized. The
80    * delegate will be initialized when this element is processed, or otherwise used to create an
81    * injector.
82    */
getDelegate()83   public MembersInjector<T> getDelegate() {
84     return delegate;
85   }
86 
87   /**
88    * Returns the looked up members injector. The result is not valid until this lookup has been
89    * initialized, which usually happens when the injector is created. The members injector will
90    * throw an {@code IllegalStateException} if you try to use it beforehand.
91    */
getMembersInjector()92   public MembersInjector<T> getMembersInjector() {
93     return new MembersInjector<T>() {
94       @Override
95       public void injectMembers(T instance) {
96         MembersInjector<T> local = delegate;
97         if (local == null) {
98           throw new IllegalStateException(
99               "This MembersInjector cannot be used until the Injector has been created.");
100         }
101         local.injectMembers(instance);
102       }
103 
104       @Override
105       public String toString() {
106         return "MembersInjector<" + type + ">";
107       }
108     };
109   }
110 }
111