Revision: 1293
Author: sberlin
Date: Sat Oct 16 18:28:06 2010
Log: patch from ramakrishna (with very minor changes from me) for an extension SPI for assisted inject.
http://code.google.com/p/google-guice/source/detail?r=1293

Added:
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java /trunk/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java
Modified:
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java

=======================================
--- /dev/null
+++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java Sat Oct 16 18:28:06 2010
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.assistedinject;
+
+import com.google.inject.Key;
+
+import java.util.Collection;
+
+/**
+ * A binding for a factory created by FactoryModuleBuilder.
+ *
+ * @param <T> The fully qualified type of the factory.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectBinding<T> {
+
+  /** Returns the {...@link Key} for the factory binding. */
+  Key<T> getKey();
+
+  /** Returns an {...@link AssistedMethod} for each method in the factory. */
+  Collection<AssistedMethod> getAssistedMethods();
+}
=======================================
--- /dev/null
+++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java Sat Oct 16 18:28:06 2010
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.assistedinject;
+
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for the AssistedInject extension.
+ * <p>
+ * If your {...@link BindingTargetVisitor} implements this interface, bindings created by using
+ * {...@link FactoryModuleBuilder} will be visited through this interface.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectTargetVisitor<T, V> extends BindingTargetVisitor<T, V> {
+
+  /**
+ * Visits an {...@link AssistedInjectBinding} created through {...@link FactoryModuleBuilder}.
+   */
+  V visit(AssistedInjectBinding<? extends T> assistedInjectBinding);
+}
=======================================
--- /dev/null
+++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java Sat Oct 16 18:28:06 2010
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.assistedinject;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Dependency;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Details about how a method in an assisted inject factory will be assisted.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedMethod {
+
+  /**
+   * Returns the factory method that is being assisted.
+   */
+  Method getFactoryMethod();
+
+  /**
+ * Returns the implementation type that will be created when the method is
+   * used.
+   */
+  TypeLiteral<?> getImplementationType();
+
+  /**
+ * Returns the constructor that will be used to construct instances of the
+   * implementation.
+   */
+  Constructor<?> getImplementationConstructor();
+
+  /**
+   * Returns all non-assisted dependencies required to construct and inject
+   * the implementation.
+   */
+  Set<Dependency<?>> getDependencies();
+}
=======================================
--- /dev/null
+++ /trunk/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java Sat Oct 16 18:28:06 2010
@@ -0,0 +1,221 @@
+/**
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.assistedinject;
+
+import static com.google.inject.name.Names.named;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Stage;
+import com.google.inject.internal.util.ImmutableList;
+import com.google.inject.internal.util.ImmutableSet;
+import com.google.inject.internal.util.Iterables;
+import com.google.inject.internal.util.Lists;
+import com.google.inject.name.Named;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Tests for AssistedInject Spi.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public class ExtensionSpiTest extends TestCase {
+
+  public final void testSpiOnElements() throws Exception {
+    AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+    Integer count = 0;
+    for(Element element : Elements.getElements(new Module())) {
+      if(element instanceof Binding) {
+ assertEquals(count++, ((Binding<?>)element).acceptTargetVisitor(visitor));
+      }
+    }
+    validateVisitor(visitor);
+  }
+
+  public void testSpiOnVisitor() throws Exception {
+    AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+    Integer count = 0;
+    Injector injector = Guice.createInjector(new Module());
+    for(Binding<?> binding : injector.getBindings().values()) {
+      assertEquals(count++, binding.acceptTargetVisitor(visitor));
+    }
+    validateVisitor(visitor);
+  }
+
+ private void validateVisitor(AssistedInjectSpiVisitor visitor) throws Exception {
+    assertEquals(1, visitor.assistedBindingCount);
+    List<AssistedMethod> assistedMethods =
+        Lists.newArrayList(Iterables.getOnlyElement(
+            visitor.assistedInjectBindings).getAssistedMethods());
+    assertEquals(7, assistedMethods.size());
+    assertEquals(1, visitor.assistedBindingCount);
+    assertEquals(1, visitor.assistedInjectBindings.size());
+
+    // Validate for each of the methods in AnimalFactory
+    validateCreateAStrangeCatAsAnimal(assistedMethods.get(0));
+ validatecreateStrangeCatWithConstructorForOwner(assistedMethods.get(1));
+    validatecreateStrangeCatWithConstructorForAge(assistedMethods.get(2));
+    validateCreateCatWithANonAssistedDependency(assistedMethods.get(3));
+    validateCreateCat(assistedMethods.get(4));
+    validateCreateASimpleCatAsAnimal(assistedMethods.get(5));
+    validateCreateCatWithNonAssistedDependencies(assistedMethods.get(6));
+
+  }
+
+ private void validateCreateAStrangeCatAsAnimal(AssistedMethod assistedMethod) {
+    validateAssistedMethod(assistedMethod, "createAStrangeCatAsAnimal",
+      StrangeCat.class, ImmutableList.<Key<?>>of());
+  }
+
+ private void validatecreateStrangeCatWithConstructorForOwner(AssistedMethod assistedMethod) { + validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForOwner",
+      StrangeCat.class, ImmutableList.<Key<?>>of());
+  }
+
+ private void validatecreateStrangeCatWithConstructorForAge(AssistedMethod assistedMethod) { + validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForAge",
+      StrangeCat.class, ImmutableList.<Key<?>>of());
+  }
+
+ private void validateCreateCatWithANonAssistedDependency(AssistedMethod assistedMethod)
+      throws Exception {
+ validateAssistedMethod(assistedMethod, "createCatWithANonAssistedDependency", + CatWithAName.class, ImmutableList.<Key<?>>of(Key.get(String.class, named("catName2"))));
+  }
+
+ private void validateCreateCat(AssistedMethod assistedMethod) throws Exception { + validateAssistedMethod(assistedMethod, "createCat", Cat.class, ImmutableList.<Key<?>>of());
+  }
+
+ private void validateCreateASimpleCatAsAnimal(AssistedMethod assistedMethod) { + validateAssistedMethod(assistedMethod, "createASimpleCatAsAnimal", SimpleCat.class,
+        ImmutableList.<Key<?>>of());
+  }
+
+ private void validateCreateCatWithNonAssistedDependencies(AssistedMethod assistedMethod) {
+    List<Key<?>> dependencyKeys = ImmutableList.<Key<?>>of(
+        Key.get(String.class, named("catName1")),
+        Key.get(String.class, named("petName")),
+        Key.get(Integer.class, named("age")));
+ validateAssistedMethod(assistedMethod, "createCatWithNonAssistedDependencies",
+      ExplodingCat.class, dependencyKeys);
+  }
+
+ private void validateAssistedMethod(AssistedMethod assistedMethod, String factoryMethodName, + Class clazz, List<Key<?>> dependencyKeys){ + assertEquals(factoryMethodName, assistedMethod.getFactoryMethod().getName()); + assertEquals(clazz, assistedMethod.getImplementationConstructor().getDeclaringClass()); + assertEquals(dependencyKeys.size(), assistedMethod.getDependencies().size());
+    for (Dependency<?> dependency : assistedMethod.getDependencies()) {
+      assertTrue(dependencyKeys.contains(dependency.getKey()));
+    }
+    assertEquals(clazz, assistedMethod.getImplementationType().getType());
+  }
+
+
+  interface AnimalFactory {
+    Cat createCat(String owner);
+    CatWithAName createCatWithANonAssistedDependency(String owner);
+    @Named("SimpleCat") Animal createASimpleCatAsAnimal(String owner);
+    Animal createAStrangeCatAsAnimal(String owner);
+    StrangeCat createStrangeCatWithConstructorForOwner(String owner);
+    StrangeCat createStrangeCatWithConstructorForAge(Integer age);
+    ExplodingCat createCatWithNonAssistedDependencies(String owner);
+  }
+
+  interface Animal {}
+
+  private static class Cat implements Animal {
+    @Inject Cat(@Assisted String owner) {}
+  }
+
+  private static class SimpleCat implements Animal {
+    @Inject SimpleCat(@Assisted String owner) {
+    }
+  }
+
+  private static class StrangeCat implements Animal {
+    @AssistedInject StrangeCat(@Assisted String owner) {}
+    @AssistedInject StrangeCat(@Assisted Integer age) {}
+  }
+
+  private static class ExplodingCat implements Animal {
+ @Inject public ExplodingCat(@Named("catName1") String name, @Assisted String owner, + @Named("age") Integer age, @Named("petName") String petName) {}
+  }
+
+  private static class CatWithAName extends Cat {
+ @Inject CatWithAName(@Assisted String owner, @Named("catName2") String name) {
+      super(owner);
+    }
+  }
+
+  public class Module extends AbstractModule{
+    @Override
+    protected void configure() {
+ bind(String.class).annotatedWith(named("catName1")).toInstance("kitty1"); + bind(String.class).annotatedWith(named("catName2")).toInstance("kitty2"); + bind(String.class).annotatedWith(named("petName")).toInstance("pussy");
+      bind(Integer.class).annotatedWith(named("age")).toInstance(12);
+      install(new FactoryModuleBuilder()
+        .implement(Animal.class, StrangeCat.class)
+        .implement(Animal.class, named("SimpleCat"), SimpleCat.class)
+        .build(AnimalFactory.class));
+    }
+  }
+
+ public class AssistedInjectSpiVisitor extends DefaultBindingTargetVisitor<Object, Integer>
+      implements AssistedInjectTargetVisitor<Object, Integer>  {
+
+    private final Set<Class> allowedClasses =
+      ImmutableSet.<Class> of(
+        Injector.class, Stage.class, Logger.class,
+        String.class, Integer.class);
+
+    private int assistedBindingCount = 0;
+    private int currentCount = 0;
+ private List<AssistedInjectBinding<?>> assistedInjectBindings = Lists.newArrayList();
+
+    public Integer visit(AssistedInjectBinding assistedInjectBinding) {
+      assistedInjectBindings.add(assistedInjectBinding);
+      assistedBindingCount++;
+      return currentCount++;
+    }
+
+    @Override
+    protected Integer visitOther(Binding<? extends Object> binding) {
+ if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) { + throw new AssertionFailedError("invalid other binding: " + binding);
+      }
+      return currentCount++;
+    }
+  }
+}
=======================================
--- /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java Sat Jul 31 09:08:27 2010 +++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java Sat Oct 16 18:28:06 2010
@@ -310,7 +310,7 @@
   public <F> Module build(final Key<F> factoryInterface) {
     return new AbstractModule() {
       @Override protected void configure() {
- Provider<F> provider = new FactoryProvider2<F>(factoryInterface.getTypeLiteral(), bindings); + Provider<F> provider = new FactoryProvider2<F>(factoryInterface, bindings);
         bind(factoryInterface).toProvider(provider);
       }
     };
=======================================
--- /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java Sat Jul 3 08:51:31 2010 +++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java Sat Oct 16 18:28:06 2010
@@ -192,7 +192,7 @@
         }
       }

-      return new FactoryProvider2<F>(factoryType, collector);
+      return new FactoryProvider2<F>(Key.get(factoryType), collector);
     }
   }

=======================================
--- /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java Wed Sep 22 20:16:22 2010 +++ /trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java Sat Oct 16 18:28:06 2010
@@ -16,6 +16,9 @@

 package com.google.inject.assistedinject;

+import static com.google.inject.internal.util.Iterables.getOnlyElement;
+import static com.google.inject.internal.util.Preconditions.checkState;
+
 import com.google.inject.AbstractModule;
 import com.google.inject.Binder;
 import com.google.inject.Binding;
@@ -27,7 +30,7 @@
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
 import com.google.inject.TypeLiteral;
-import static com.google.inject.internal.Annotations.getKey;
+import com.google.inject.internal.Annotations;
 import com.google.inject.internal.BytecodeGen;
 import com.google.inject.internal.Errors;
 import com.google.inject.internal.ErrorsException;
@@ -36,18 +39,18 @@
 import com.google.inject.internal.util.ImmutableMap;
 import com.google.inject.internal.util.ImmutableSet;
 import com.google.inject.internal.util.Iterables;
-import com.google.inject.internal.util.ToStringBuilder;
-
-import static com.google.inject.internal.util.Iterables.getOnlyElement;
 import com.google.inject.internal.util.Lists;
-import static com.google.inject.internal.util.Preconditions.checkState;
-
+import com.google.inject.internal.util.ToStringBuilder;
+import com.google.inject.spi.BindingTargetVisitor;
 import com.google.inject.spi.Dependency;
 import com.google.inject.spi.HasDependencies;
 import com.google.inject.spi.InjectionPoint;
 import com.google.inject.spi.Message;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
 import com.google.inject.spi.Toolable;
 import com.google.inject.util.Providers;
+
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
@@ -71,7 +74,8 @@
  * @author schm...@google.com (Peter Schmitt)
  * @author sa...@google.com (Sam Berlin)
  */
-final class FactoryProvider2<F> implements InvocationHandler, Provider<F>, HasDependencies {
+final class FactoryProvider2 <F> implements InvocationHandler,
+ ProviderWithExtensionVisitor<F>, HasDependencies, AssistedInjectBinding<F> {

/** if a factory method parameter isn't annotated, it gets this annotation. */
   static final Assisted DEFAULT_ANNOTATION = new Assisted() {
@@ -96,36 +100,42 @@
       return "@" + Assisted.class.getName() + "(value=)";
     }
   };
-
+
   /** All the data necessary to perform an assisted inject. */
-  private static class AssistData {
+  private static class AssistData implements AssistedMethod {
     /** the constructor the implementation is constructed with. */
     final Constructor<?> constructor;
/** the return type in the factory method that the constructor is bound to. */
     final Key<?> returnType;
     /** the parameters in the factory method associated with this data. */
     final ImmutableList<Key<?>> paramTypes;
-
+    /** the type of the implementation constructed */
+    final TypeLiteral<?> implementationType;
+
     /** All non-assisted dependencies required by this method. */
     final Set<Dependency<?>> dependencies;
-
+    /** The factory method associated with this data*/
+    final Method factoryMethod;
+
     /** true if {...@link #validForOptimizedAssistedInject} returned true. */
     final boolean optimized;
     /** the list of optimized providers, empty if not optimized. */
     final List<ThreadLocalProvider> providers;
     /** used to perform optimized factory creations. */
     volatile Binding<?> cachedBinding; // TODO: volatile necessary?
-
-    AssistData(Constructor<?> constructor, Key<?> returnType,
-        ImmutableList<Key<?>> paramTypes, boolean optimized,
-        List<ThreadLocalProvider> providers,
-        Set<Dependency<?>> dependencies) {
+
+ AssistData(Constructor<?> constructor, Key<?> returnType, ImmutableList<Key<?>> paramTypes,
+        TypeLiteral<?> implementationType, Method factoryMethod,
+        Set<Dependency<?>> dependencies,
+        boolean optimized, List<ThreadLocalProvider> providers) {
       this.constructor = constructor;
       this.returnType = returnType;
       this.paramTypes = paramTypes;
+      this.implementationType = implementationType;
+      this.factoryMethod = factoryMethod;
+      this.dependencies = dependencies;
       this.optimized = optimized;
       this.providers = providers;
-      this.dependencies = dependencies;
     }

     @Override
@@ -134,33 +144,53 @@
         .add("ctor", constructor)
         .add("return type", returnType)
         .add("param type", paramTypes)
+        .add("implementation type", implementationType)
+        .add("dependencies", dependencies)
+        .add("factory method", factoryMethod)
         .add("optimized", optimized)
         .add("providers", providers)
         .add("cached binding", cachedBinding)
-        .add("dependencies", dependencies)
         .toString();
-
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+      return dependencies;
+    }
+
+    public Method getFactoryMethod() {
+      return factoryMethod;
+    }
+
+    public Constructor<?> getImplementationConstructor() {
+      return constructor;
+    }
+
+    public TypeLiteral<?> getImplementationType() {
+      return implementationType;
     }
   }

-  /** the produced type, or null if all methods return concrete types */
-  private final BindingCollector collector;
-  private final ImmutableMap<Method, AssistData> assistDataByMethod;
+ /** Mapping from method to the data about how the method will be assisted. */
+  private final ImmutableMap<Method, AssistData> assistDataByMethod;

   /** the hosting injector, or null if we haven't been initialized yet */
   private Injector injector;

   /** the factory interface, implemented and provided */
   private final F factory;
+
+  /** The key that this is bound to. */
+  private final Key<F> factoryKey;

   /**
* @param factoryType a Java interface that defines one or more create methods. * @param collector binding configuration that maps method return types to
    *    implementation types.
    */
- FactoryProvider2(TypeLiteral<F> factoryType, BindingCollector collector) {
-    this.collector = collector;
-
+  FactoryProvider2(Key<F> factoryKey, BindingCollector collector) {
+    this.factoryKey = factoryKey;
+
+    TypeLiteral<F> factoryType = factoryKey.getTypeLiteral();
     Errors errors = new Errors();

@SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class<T>
@@ -173,7 +203,7 @@
TypeLiteral<?> returnTypeLiteral = factoryType.getReturnType(method);
         Key<?> returnType;
         try {
- returnType = getKey(returnTypeLiteral, method, method.getAnnotations(), errors); + returnType = Annotations.getKey(returnTypeLiteral, method, method.getAnnotations(), errors);
         } catch(ConfigurationException ce) {
// If this was an error due to returnTypeLiteral not being specified, rephrase // it as our factory not being specified, so it makes more sense to users.
@@ -188,7 +218,7 @@
         int p = 0;
         List<Key<?>> keys = Lists.newArrayList();
         for (TypeLiteral<?> param : params) {
- Key<?> paramKey = getKey(param, method, paramAnnotations[p++], errors); + Key<?> paramKey = Annotations.getKey(param, method, paramAnnotations[p++], errors); Class<?> underlylingType = paramKey.getTypeLiteral().getRawType();
           if (underlylingType.equals(Provider.class)
               || underlylingType.equals(javax.inject.Provider.class)) {
@@ -199,7 +229,7 @@
           keys.add(assistKey(method, paramKey, errors));
         }
ImmutableList<Key<?>> immutableParamList = ImmutableList.copyOf(keys);
-
+
         // try to match up the method to the constructor
TypeLiteral<?> implementation = collector.getBindings().get(returnType);
         if(implementation == null) {
@@ -207,13 +237,13 @@
         }
         InjectionPoint ctorInjectionPoint;
         try {
-          ctorInjectionPoint =
+          ctorInjectionPoint =
findMatchingConstructorInjectionPoint(method, returnType, implementation, immutableParamList);
         } catch(ErrorsException ee) {
           errors.merge(ee.getErrors());
           continue;
         }
-
+
Constructor<?> constructor = (Constructor)ctorInjectionPoint.getMember();
         List<ThreadLocalProvider> providers = Collections.emptyList();
Set<Dependency<?>> deps = getDependencies(ctorInjectionPoint, implementation);
@@ -232,8 +262,8 @@
           optimized = true;
         }
         assistDataBuilder.put(method,
-            new AssistData(constructor, returnType, immutableParamList,
-                optimized, providers, removeAssistedDeps(deps)));
+ new AssistData(constructor, returnType, immutableParamList, implementation,
+                method, removeAssistedDeps(deps), optimized, providers));
       }

// If we generated any errors (from finding matching constructors, for instance), throw an exception.
@@ -245,7 +275,7 @@
     } catch (ErrorsException e) {
       throw new ConfigurationException(e.getErrors().getMessages());
     }
-
+
factory = factoryRawType.cast(Proxy.newProxyInstance(BytecodeGen.getClassLoader(factoryRawType),
         new Class[] { factoryRawType }, this));
   }
@@ -253,7 +283,7 @@
   public F get() {
     return factory;
   }
-
+
   public Set<Dependency<?>> getDependencies() {
     Set<Dependency<?>> combinedDeps = new HashSet<Dependency<?>>();
     for(AssistData data : assistDataByMethod.values()) {
@@ -261,6 +291,25 @@
     }
     return ImmutableSet.copyOf(combinedDeps);
   }
+
+  public Key<F> getKey() {
+    return factoryKey;
+  }
+
+ // safe cast because values are typed to AssistedData, which is an AssistedMethod
+  @SuppressWarnings("unchecked")
+  public Collection<AssistedMethod> getAssistedMethods() {
+    return (Collection)assistDataByMethod.values();
+  }
+
+  @SuppressWarnings("unchecked")
+ public <V, T> V acceptExtensionVisitor(BindingTargetVisitor<T, V> visitor,
+      ProviderInstanceBinding<? extends T> binding) {
+    if (visitor instanceof AssistedInjectTargetVisitor) {
+ return ((AssistedInjectTargetVisitor<T, V>)visitor).visit((AssistedInjectBinding<T>)this);
+    }
+    return visitor.visit(binding);
+  }

   /**
* Returns true if the ConfigurationException is due to an error of TypeLiteral not being fully
@@ -293,7 +342,7 @@
     } else {
       errors = errors.withSource(returnType).withSource(implementation);
     }
-
+
     Class<?> rawType = implementation.getRawType();
     if (Modifier.isInterface(rawType.getModifiers())) {
       errors.addMessage(
@@ -309,7 +358,7 @@
       errors.cannotInjectInnerClass(rawType);
       throw errors.toException();
     }
-
+
     Constructor<?> matchingConstructor = null;
     boolean anyAssistedInjectConstructors = false;
     // Look for AssistedInject constructors...
@@ -330,7 +379,7 @@
         }
       }
     }
-
+
     if(!anyAssistedInjectConstructors) {
       // If none existed, use @Inject.
       try {
@@ -371,7 +420,7 @@
     int p = 0;
     List<Key<?>> constructorKeys = Lists.newArrayList();
     for (TypeLiteral<?> param : params) {
-      Key<?> paramKey = getKey(param, constructor, paramAnnotations[p++],
+ Key<?> paramKey = Annotations.getKey(param, constructor, paramAnnotations[p++],
           errors);
       constructorKeys.add(paramKey);
     }
@@ -403,7 +452,7 @@
     }
     return builder.build();
   }
-
+
   /** Return all non-assisted dependencies. */
   private Set<Dependency<?>> removeAssistedDeps(Set<Dependency<?>> deps) {
     ImmutableSet.Builder<Dependency<?>> builder = ImmutableSet.builder();
@@ -415,7 +464,7 @@
     }
     return builder.build();
   }
-
+
   /**
* Returns true if all dependencies are suitable for the optimized version of AssistedInject. The * optimized version caches the binding & uses a ThreadLocal Provider, so can only be applied if
@@ -430,7 +479,7 @@
     }
     return true;
   }
-
+
   /**
* Returns true if the dependency is for {...@link Injector} or if the dependency * is a {...@link Provider} for a parameter that is {...@literal @}...@link Assisted}.
@@ -521,18 +570,14 @@
binder.bind((Key) paramKey).toProvider(data.providers.get(p++));
           }
         }
-
+
         Constructor constructor = data.constructor;
         // Constructor *should* always be non-null here,
         // but if it isn't, we'll end up throwing a fairly good error
         // message for the user.
         if(constructor != null) {
- TypeLiteral implementation = collector.getBindings().get(returnType);
-          if (implementation != null) {
- binder.bind(assistedReturnType).toConstructor(constructor, implementation);
-          } else {
- binder.bind(assistedReturnType).toConstructor(constructor, (TypeLiteral) returnType.getTypeLiteral());
-          }
+          binder.bind(assistedReturnType).toConstructor(
+              constructor, (TypeLiteral)data.implementationType);
         }
       }
     };
@@ -541,7 +586,7 @@
     Binding binding = forCreate.getBinding(assistedReturnType);
// If we have providers cached in data, cache the binding for future optimizations.
     if(data.optimized) {
-      data.cachedBinding = binding;
+      data.cachedBinding = binding;
     }
     return binding;
   }
@@ -607,9 +652,9 @@

     return false;
   }
-
+
// not <T> because we'll never know and this is easier than suppressing warnings. - private static class ThreadLocalProvider extends ThreadLocal<Object> implements Provider<Object> { + private static class ThreadLocalProvider extends ThreadLocal<Object> implements Provider<Object> {
     @Override
     protected Object initialValue() {
       throw new IllegalStateException(

--
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to google-guice-...@googlegroups.com.
To unsubscribe from this group, send email to 
google-guice-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en.

Reply via email to