Home | History | Annotate | Download | only in spi
      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 (at) 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 
     42   public MembersInjectorLookup(Object source, TypeLiteral<T> type) {
     43     this.source = checkNotNull(source, "source");
     44     this.type = checkNotNull(type, "type");
     45   }
     46 
     47   public Object getSource() {
     48     return source;
     49   }
     50 
     51   /**
     52    * Gets the type containing the members to be injected.
     53    */
     54   public TypeLiteral<T> getType() {
     55     return type;
     56   }
     57 
     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    */
     67   public void initializeDelegate(MembersInjector<T> delegate) {
     68     checkState(this.delegate == null, "delegate already initialized");
     69     this.delegate = checkNotNull(delegate, "delegate");
     70   }
     71 
     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    */
     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    */
     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 }