Home | History | Annotate | Download | only in internal
      1 /**
      2  * Copyright (C) 2008 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.internal;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.collect.ImmutableSet;
     22 import com.google.inject.Binder;
     23 import com.google.inject.ConfigurationException;
     24 import com.google.inject.Key;
     25 import com.google.inject.Provider;
     26 import com.google.inject.TypeLiteral;
     27 import com.google.inject.binder.AnnotatedBindingBuilder;
     28 import com.google.inject.binder.ScopedBindingBuilder;
     29 import com.google.inject.spi.Element;
     30 import com.google.inject.spi.InjectionPoint;
     31 import com.google.inject.spi.Message;
     32 
     33 import java.lang.annotation.Annotation;
     34 import java.lang.reflect.Constructor;
     35 import java.util.List;
     36 import java.util.Set;
     37 
     38 /**
     39  * Bind a non-constant key.
     40  *
     41  * @author jessewilson (at) google.com (Jesse Wilson)
     42  */
     43 public class BindingBuilder<T> extends AbstractBindingBuilder<T>
     44     implements AnnotatedBindingBuilder<T> {
     45 
     46   public BindingBuilder(Binder binder, List<Element> elements, Object source, Key<T> key) {
     47     super(binder, elements, source, key);
     48   }
     49 
     50   public BindingBuilder<T> annotatedWith(Class<? extends Annotation> annotationType) {
     51     annotatedWithInternal(annotationType);
     52     return this;
     53   }
     54 
     55   public BindingBuilder<T> annotatedWith(Annotation annotation) {
     56     annotatedWithInternal(annotation);
     57     return this;
     58   }
     59 
     60   public BindingBuilder<T> to(Class<? extends T> implementation) {
     61     return to(Key.get(implementation));
     62   }
     63 
     64   public BindingBuilder<T> to(TypeLiteral<? extends T> implementation) {
     65     return to(Key.get(implementation));
     66   }
     67 
     68   public BindingBuilder<T> to(Key<? extends T> linkedKey) {
     69     checkNotNull(linkedKey, "linkedKey");
     70     checkNotTargetted();
     71     BindingImpl<T> base = getBinding();
     72     setBinding(new LinkedBindingImpl<T>(
     73         base.getSource(), base.getKey(), base.getScoping(), linkedKey));
     74     return this;
     75   }
     76 
     77   public void toInstance(T instance) {
     78     checkNotTargetted();
     79 
     80     // lookup the injection points, adding any errors to the binder's errors list
     81     Set<InjectionPoint> injectionPoints;
     82     if (instance != null) {
     83       try {
     84         injectionPoints = InjectionPoint.forInstanceMethodsAndFields(instance.getClass());
     85       } catch (ConfigurationException e) {
     86         copyErrorsToBinder(e);
     87         injectionPoints = e.getPartialValue();
     88       }
     89     } else {
     90       binder.addError(BINDING_TO_NULL);
     91       injectionPoints = ImmutableSet.of();
     92     }
     93 
     94     BindingImpl<T> base = getBinding();
     95     setBinding(new InstanceBindingImpl<T>(
     96         base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance));
     97   }
     98 
     99   public BindingBuilder<T> toProvider(Provider<? extends T> provider) {
    100     return toProvider((javax.inject.Provider<T>) provider);
    101   }
    102 
    103   public BindingBuilder<T> toProvider(javax.inject.Provider<? extends T> provider) {
    104     checkNotNull(provider, "provider");
    105     checkNotTargetted();
    106 
    107     // lookup the injection points, adding any errors to the binder's errors list
    108     Set<InjectionPoint> injectionPoints;
    109     try {
    110       injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
    111     } catch (ConfigurationException e) {
    112       copyErrorsToBinder(e);
    113       injectionPoints = e.getPartialValue();
    114     }
    115 
    116     BindingImpl<T> base = getBinding();
    117     setBinding(new ProviderInstanceBindingImpl<T>(
    118         base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider));
    119     return this;
    120   }
    121 
    122   public BindingBuilder<T> toProvider(
    123       Class<? extends javax.inject.Provider<? extends T>> providerType) {
    124     return toProvider(Key.get(providerType));
    125   }
    126 
    127   public BindingBuilder<T> toProvider(
    128       TypeLiteral<? extends javax.inject.Provider<? extends T>> providerType) {
    129     return toProvider(Key.get(providerType));
    130   }
    131 
    132   public BindingBuilder<T> toProvider(
    133       Key<? extends javax.inject.Provider<? extends T>> providerKey) {
    134     checkNotNull(providerKey, "providerKey");
    135     checkNotTargetted();
    136 
    137     BindingImpl<T> base = getBinding();
    138     setBinding(new LinkedProviderBindingImpl<T>(
    139         base.getSource(), base.getKey(), base.getScoping(), providerKey));
    140     return this;
    141   }
    142 
    143   public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor) {
    144     return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass()));
    145   }
    146 
    147   public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor,
    148       TypeLiteral<? extends S> type) {
    149     checkNotNull(constructor, "constructor");
    150     checkNotNull(type, "type");
    151     checkNotTargetted();
    152 
    153     BindingImpl<T> base = getBinding();
    154 
    155     Set<InjectionPoint> injectionPoints;
    156     try {
    157       injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type);
    158     } catch (ConfigurationException e) {
    159       copyErrorsToBinder(e);
    160       injectionPoints = e.getPartialValue();
    161     }
    162 
    163     try {
    164       InjectionPoint constructorPoint = InjectionPoint.forConstructor(constructor, type);
    165       setBinding(new ConstructorBindingImpl<T>(base.getKey(), base.getSource(), base.getScoping(),
    166           constructorPoint, injectionPoints));
    167     } catch (ConfigurationException e) {
    168       copyErrorsToBinder(e);
    169     }
    170 
    171     return this;
    172   }
    173 
    174   @Override public String toString() {
    175     return "BindingBuilder<" + getBinding().getKey().getTypeLiteral() + ">";
    176   }
    177 
    178   private void copyErrorsToBinder(ConfigurationException e) {
    179     for (Message message : e.getErrorMessages()) {
    180       binder.addError(message);
    181     }
    182   }
    183 }
    184