[weld-commits] Weld SVN: r6805 - extensions/trunk/impl/src/main/java/org/jboss/weld/extensions/bean/generic.

weld-commits at lists.jboss.org weld-commits at lists.jboss.org
Sat Jul 24 12:20:43 EDT 2010


Author: pete.muir at jboss.org
Date: 2010-07-24 12:20:43 -0400 (Sat, 24 Jul 2010)
New Revision: 6805

Modified:
   extensions/trunk/impl/src/main/java/org/jboss/weld/extensions/bean/generic/GenericBeanExtension.java
Log:
reimplement GenericBeanExtension around ProcessProducer

Modified: extensions/trunk/impl/src/main/java/org/jboss/weld/extensions/bean/generic/GenericBeanExtension.java
===================================================================
--- extensions/trunk/impl/src/main/java/org/jboss/weld/extensions/bean/generic/GenericBeanExtension.java	2010-07-24 15:38:50 UTC (rev 6804)
+++ extensions/trunk/impl/src/main/java/org/jboss/weld/extensions/bean/generic/GenericBeanExtension.java	2010-07-24 16:20:43 UTC (rev 6805)
@@ -19,7 +19,6 @@
 import static org.jboss.weld.extensions.util.Reflections.getRawType;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -32,11 +31,11 @@
 import javax.enterprise.context.Dependent;
 import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.event.Observes;
-import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.spi.AfterBeanDiscovery;
 import javax.enterprise.inject.spi.AfterDeploymentValidation;
 import javax.enterprise.inject.spi.AnnotatedConstructor;
 import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMember;
 import javax.enterprise.inject.spi.AnnotatedMethod;
 import javax.enterprise.inject.spi.AnnotatedParameter;
 import javax.enterprise.inject.spi.AnnotatedType;
@@ -45,7 +44,7 @@
 import javax.enterprise.inject.spi.BeforeBeanDiscovery;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
-import javax.enterprise.inject.spi.ProcessInjectionTarget;
+import javax.enterprise.inject.spi.ProcessProducer;
 import javax.inject.Inject;
 
 import org.jboss.weld.extensions.annotated.AnnotatedTypeBuilder;
@@ -53,8 +52,6 @@
 import org.jboss.weld.extensions.bean.BeanLifecycle;
 import org.jboss.weld.extensions.util.Arrays2;
 import org.jboss.weld.extensions.util.Synthetic;
-import org.jboss.weld.extensions.util.properties.Properties;
-import org.jboss.weld.extensions.util.properties.Property;
 
 /**
  * Extension that wires in Generic Beans
@@ -66,14 +63,11 @@
 class GenericBeanExtension implements Extension
 {
 
-   // A map of generic configuration types to generic beans
-   private final Map<Class<?>, Set<AnnotatedType<?>>> genericTypes;
+   // A map of generic configuration types to generic bean types
+   private final Map<Class<?>, Set<AnnotatedType<?>>> genericBeanTypes;
 
-   // A map of classes containing producers which produce generic beans
-   private final Map<Class<?>, Map<Member, Annotation>> producers;
-
    // A map of a generic configuration types to all instances of that type found
-   private final Map<Class<?>, Set<Annotation>> concreteGenerics;
+   private final Map<Class<?>, Set<Annotation>> genericConfigurationTypes;
    
    // A map of generic configuration annotations to generic configuration beans
    private final Map<Annotation, Bean<?>> genericConfigurationBeans;
@@ -82,10 +76,9 @@
 
    GenericBeanExtension()
    {
-      this.genericTypes = new HashMap<Class<?>, Set<AnnotatedType<?>>>();
+      this.genericBeanTypes = new HashMap<Class<?>, Set<AnnotatedType<?>>>();
       this.genericConfigurationBeans = new HashMap<Annotation, Bean<?>>();
-      this.producers = new HashMap<Class<?>, Map<Member, Annotation>>();
-      this.concreteGenerics = new HashMap<Class<?>, Set<Annotation>>();
+      this.genericConfigurationTypes = new HashMap<Class<?>, Set<Annotation>>();
       this.syntheticProvider = new Synthetic.Provider("org.jboss.weld.extensions.bean.generic");
    }
 
@@ -95,91 +88,92 @@
       event.addQualifier(GenericBean.class);
    }
 
-   void processAnnotatedType(@Observes ProcessAnnotatedType<?> event)
+   <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event)
    {
       AnnotatedType<?> type = event.getAnnotatedType();
       if (type.isAnnotationPresent(Generic.class))
       {
-         Generic generic = type.getAnnotation(Generic.class);
-         if (!genericTypes.containsKey(generic.value()))
-         {
-            genericTypes.put(generic.value(), new HashSet<AnnotatedType<?>>());
-         }
-         genericTypes.get(generic.value()).add(type);
+         addGenericBeanType(type);
          // we will install (multiple copies of) this bean later
          event.veto();
 
       }
-      // make note of any producer fields that produce generic beans
-      for (AnnotatedField<?> field : type.getFields())
+   }
+   
+   private <X> void addGenericBeanType(AnnotatedType<X> type)
+   {
+      Generic generic = type.getAnnotation(Generic.class);
+      if (!genericBeanTypes.containsKey(generic.value()))
       {
-         if (field.isAnnotationPresent(Produces.class))
-         {
-            for (Annotation annotation : field.getAnnotations())
-            {
-               if (annotation.annotationType().isAnnotationPresent(GenericConfiguration.class))
-               {
-                  if (!producers.containsKey(type.getJavaClass()))
-                  {
-                     producers.put(type.getJavaClass(), new HashMap<Member, Annotation>());
-                  }
-                  if (!concreteGenerics.containsKey(annotation.annotationType()))
-                  {
-                     concreteGenerics.put(annotation.annotationType(), new HashSet<Annotation>());
-                  }
-                  producers.get(type.getJavaClass()).put(field.getJavaMember(), annotation);
-                  concreteGenerics.get(annotation.annotationType()).add(annotation);
-               }
-            }
-         }
+         Set<AnnotatedType<?>> annotatedTypes = new HashSet<AnnotatedType<?>>();
+         annotatedTypes.add(type);
+         genericBeanTypes.put(generic.value(), annotatedTypes);
       }
-
-      // make note of any producer method that produce generic beans
-      for (AnnotatedMethod<?> method : type.getMethods())
+      else
       {
-         if (method.isAnnotationPresent(Produces.class))
+         genericBeanTypes.get(generic.value()).add(type);
+      }
+   }
+   
+   <T, X> void processProducers(@Observes ProcessProducer<T, X> event, BeanManager beanManager)
+   {
+      // Only process the producer as a generic producer, if it has an annotation meta-annotated with GenericConfiguration
+      List<Annotation> genericConfigurationAnnotiations = new ArrayList<Annotation>();
+      for (Annotation annotation : event.getAnnotatedMember().getAnnotations())
+      {
+         if (annotation.annotationType().isAnnotationPresent(GenericConfiguration.class))
          {
-            for (Annotation annotation : method.getAnnotations())
-            {
-               if (annotation.annotationType().isAnnotationPresent(GenericConfiguration.class))
-               {
-                  if (!producers.containsKey(type.getJavaClass()))
-                  {
-                     producers.put(type.getJavaClass(), new HashMap<Member, Annotation>());
-                  }
-                  if (!concreteGenerics.containsKey(annotation.annotationType()))
-                  {
-                     concreteGenerics.put(annotation.annotationType(), new HashSet<Annotation>());
-                  }
-                  producers.get(type.getJavaClass()).put(method.getJavaMember(), annotation);
-                  concreteGenerics.get(annotation.annotationType()).add(annotation);
-               }
-            }
+            genericConfigurationAnnotiations.add(annotation);
          }
       }
+      
+      if (genericConfigurationAnnotiations.size() > 1)
+      {
+         throw new IllegalStateException("Can only have one generic configuration annotation on producer " + event.getAnnotatedMember());
+      }
+      else if (genericConfigurationAnnotiations.size() == 1)
+      {
+         Annotation genericConfiguration = genericConfigurationAnnotiations.get(0);
+         replaceProducer(event, genericConfiguration, beanManager);
+         addGenericConfigurationType(genericConfiguration);
+      }
    }
-
-   /**
-    * wraps InjectionTarget to initialise producer fields that produce generic
-    * beans
-    */
-   <T> void processInjectionTarget(@Observes ProcessInjectionTarget<T> event, BeanManager beanManager)
+   
+   private <X> void addGenericConfigurationType(Annotation genericConfiguration)
    {
-      Class<?> clazz = event.getAnnotatedType().getJavaClass();
-      if (producers.containsKey(clazz))
+      Class<? extends Annotation> genericConfigurationType = genericConfiguration.annotationType();
+      if (!genericConfigurationTypes.containsKey(genericConfigurationType))
       {
-         Map<Member, Annotation> producersOnClass = producers.get(clazz);
-         List<Property<Object>> setters = new ArrayList<Property<Object>>();
-         for (Member member : producersOnClass.keySet())
+         Set<Annotation> annotations = new HashSet<Annotation>();
+         annotations.add(genericConfiguration);
+         genericConfigurationTypes.put(genericConfigurationType, annotations);
+      }
+      else
+      {
+         genericConfigurationTypes.get(genericConfigurationType).add(genericConfiguration);
+      }
+   }
+   
+   private <T, X> void replaceProducer(ProcessProducer<T, X> event, Annotation genericConfigurationAnnotation, BeanManager beanManager)
+   {
+      // First, check that this producer's type is assignable from a generic bean's type
+      AnnotatedMember<T> annotatedMember = event.getAnnotatedMember();
+      Class<?> memberRawType = getRawType(annotatedMember.getBaseType());
+      for (Entry<Class<?>, Set<AnnotatedType<?>>> entry : genericBeanTypes.entrySet())
+      {
+         for (AnnotatedType<?> annotatedType : entry.getValue())
          {
-            // TODO Need a producer method property really
-            Property<Object> property = Properties.createProperty(member);
-            setters.add(property);
+            // TODO should take account of parameterized types
+            if (memberRawType.isAssignableFrom(getRawType(annotatedType.getBaseType())))
+            {
+               // This is the generic bean that this producer is making
+               event.setProducer(new GenericBeanProducer<X>(event.getProducer(), memberRawType, genericConfigurationAnnotation, syntheticProvider, beanManager));
+               // Short-circuit, they're can of course be only one matching generic bean to be produced!
+               return;
+            }
          }
-         ProducerInjectionTarget<T> it = new ProducerInjectionTarget<T>(event.getInjectionTarget(), beanManager, setters, producersOnClass, syntheticProvider);
-         event.setInjectionTarget(it);
       }
-
+      throw new IllegalStateException("Unable to find a generic bean type for " + event.getAnnotatedMember() + " amongst " + genericBeanTypes);
    }
 
    /**
@@ -187,20 +181,21 @@
     */
    void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager beanManager)
    {
-      for (Entry<Class<?>, Set<AnnotatedType<?>>> entry : genericTypes.entrySet())
+      for (Entry<Class<?>, Set<AnnotatedType<?>>> entry : genericBeanTypes.entrySet())
       {
-         Set<Annotation> concretes = concreteGenerics.get(entry.getKey());
-         if (concretes != null)
+         Set<Annotation> genericConfigurations = genericConfigurationTypes.get(entry.getKey());
+         if (genericConfigurations != null)
          {
             for (AnnotatedType<?> type : entry.getValue())
             {
-               for (Annotation concrete : concretes)
+               for (Annotation genericConfiguration : genericConfigurations)
                {
-                  event.addBean(createGenericBean(type, concrete, beanManager));
+                  event.addBean(createGenericBean(type, genericConfiguration, beanManager));
                }
             }
          }
       }
+      
       // Add all the generic configuration beans, which were created above
       for (Bean<?> bean : genericConfigurationBeans.values())
       {
@@ -312,9 +307,9 @@
    void cleanup(@Observes AfterDeploymentValidation event)
    {
       // Defensively clear maps to help with GC
-      this.concreteGenerics.clear();
+      this.genericConfigurationTypes.clear();
       this.genericConfigurationBeans.clear();
-      this.genericTypes.clear();
+      this.genericBeanTypes.clear();
       // TODO this.producers.clear();
       // TODO this.syntheticProvider.clear();
    }



More information about the weld-commits mailing list