Skip to content

Commit

Permalink
Add narrowing bean
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuir committed Sep 24, 2010
1 parent e1a1612 commit e8c8a8d
Show file tree
Hide file tree
Showing 2 changed files with 332 additions and 0 deletions.
128 changes: 128 additions & 0 deletions impl/src/main/java/org/jboss/weld/extensions/bean/NarrowingBean.java
@@ -0,0 +1,128 @@
package org.jboss.weld.extensions.bean;

import static org.jboss.weld.extensions.util.Reflections.cast;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.weld.extensions.util.Reflections;

/**
* <p>
* A narrowing bean allows you to build some general purpose bean (likely a
* producer method), and register it for a narrowed type (or qualifiers). For
* example, you could create a producer method which uses an a String ID to
* located an object (the object can have any class):
* </p>
*
* <pre>
* &#064;Produces
* // Use some synthetic scope to prevent this from interfering with other resolutions
* &#064;MyProducer
* Object produce(InjectionPoint ip)
* {
* String id = ip.getAnnotated().getAnnotation(Id.class).value();
* // Lookup and return the object for the id
* }
* </pre>
*
* <p>
* You can then register a narrowing bean for each type you need:
* </p>
*
* <pre>
* event.addBean(new NarrowingBeanBuilder&lt;T&gt;(delegateBean).readFromType(type).create());
* </pre>
*
* <p>
* {@link NarrowingBean} will use the annotations on <code>defininingType</code>
* to discover the qualifiers, types, scope, stereotypes of the bean, as well as
* determine it's name (if any) and whether it is an alternative.
* </p>
*
* @author Pete Muir
* @see NarrowingBeanBuilder
*/
public class NarrowingBean<T> implements Bean<T>
{

private final Bean<Object> delegate;
private final Set<Type> types;
private final Set<Annotation> qualifiers;
private final String name;
private final Class<? extends Annotation> scope;
private final boolean alternative;
private final Set<Class<? extends Annotation>> stereotypes;

NarrowingBean(Bean<Object> loggerProducerBean, Set<Type> types, Set<Annotation> qualifiers, String name, Class<? extends Annotation> scope, boolean alternative, Set<Class<? extends Annotation>> stereotypes)
{
this.delegate = loggerProducerBean;
this.types = types;
this.qualifiers = qualifiers;
this.name = name;
this.scope = scope;
this.alternative = alternative;
this.stereotypes = stereotypes;
}

public Set<Type> getTypes()
{
return types;
}

public Set<Annotation> getQualifiers()
{
return qualifiers;
}

public String getName()
{
return name;
}

public Class<? extends Annotation> getScope()
{
return scope;
}

public T create(CreationalContext<T> creationalContext)
{
return Reflections.<T>cast(delegate.create(Reflections.<CreationalContext<Object>>cast(creationalContext)));
}

public void destroy(T instance, CreationalContext<T> creationalContext)
{
delegate.destroy(instance, Reflections.<CreationalContext<Object>>cast(creationalContext));
}

public Set<Class<? extends Annotation>> getStereotypes()
{
return stereotypes;
}

public Class<?> getBeanClass()
{
return delegate.getBeanClass();
}

public boolean isAlternative()
{
return alternative;
}

public boolean isNullable()
{
return false;
}

public Set<InjectionPoint> getInjectionPoints()
{
return delegate.getInjectionPoints();
}

}
@@ -0,0 +1,204 @@
package org.jboss.weld.extensions.bean;

import static org.jboss.weld.extensions.util.Arrays2.asSet;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Named;

import org.jboss.weld.extensions.literal.AnyLiteral;
import org.jboss.weld.extensions.literal.DefaultLiteral;

/**
* Builder for {@link NarrowingBean}
*
* @author Pete Muir
* @see NarrowingBean
*
*/
public class NarrowingBeanBuilder<T>
{

private final Bean<Object> delegate;
private Set<Type> types;
private Set<Annotation> qualifiers;
private String name;
private Class<? extends Annotation> scope;
private boolean alternative;
private Set<Class<? extends Annotation>> stereotypes;

public static <T> NarrowingBeanBuilder<T> of(Bean<Object> delegate)
{
return new NarrowingBeanBuilder<T>(delegate);
}

public NarrowingBeanBuilder(Bean<Object> delegate)
{
this.delegate = delegate;
}

public NarrowingBeanBuilder<T> readFromType(AnnotatedType<T> type, BeanManager beanManager)
{
this.types = new HashSet<Type>(type.getTypeClosure());
this.qualifiers = new HashSet<Annotation>();
this.stereotypes = new HashSet<Class<? extends Annotation>>();
String name = null;
Class<? extends Annotation> scope = Dependent.class;
for (Annotation annotation : type.getAnnotations())
{
if (beanManager.isQualifier(annotation.annotationType()))
{
this.qualifiers.add(annotation);
}
else if (annotation.annotationType().equals(Named.class))
{
name = Named.class.cast(annotation).value();
}
else if (beanManager.isScope(annotation.annotationType()))
{
scope = annotation.annotationType();
}
else if (beanManager.isStereotype(annotation.annotationType()))
{
this.stereotypes.add(annotation.annotationType());
}
}
if (qualifiers.isEmpty())
{
this.qualifiers.add(DefaultLiteral.INSTANCE);
}
this.qualifiers.add(AnyLiteral.INSTANCE);
this.name = "".equals(name) ? null : name;
this.scope = scope;
this.alternative = type.isAnnotationPresent(Alternative.class);
return this;
}

public Set<Type> getTypes()
{
return types;
}

public NarrowingBeanBuilder<T> types(Set<Type> types)
{
this.types = types;
return this;
}

public NarrowingBeanBuilder<T> types(Type... types)
{
this.types = asSet(types);
return this;
}

public NarrowingBeanBuilder<T> addType(Type type)
{
this.types.add(type);
return this;
}

public NarrowingBeanBuilder<T> addTypes(Type... types)
{
this.types.addAll(asSet(types));
return this;
}

public NarrowingBeanBuilder<T> addTypes(Collection<Type> types)
{
this.types.addAll(types);
return this;
}

public Set<Annotation> getQualifiers()
{
return qualifiers;
}

public NarrowingBeanBuilder<T> qualifiers(Set<Annotation> qualifiers)
{
this.qualifiers = qualifiers;
return this;
}

public NarrowingBeanBuilder<T> qualifiers(Annotation... qualifiers)
{
this.qualifiers = asSet(qualifiers);
return this;
}

public NarrowingBeanBuilder<T> addQualifier(Annotation qualifier)
{
this.qualifiers.add(qualifier);
return this;
}

public NarrowingBeanBuilder<T> addQualifiers(Annotation... qualifiers)
{
this.qualifiers.addAll(asSet(qualifiers));
return this;
}

public NarrowingBeanBuilder<T> addQualifiers(Collection<Annotation> qualifiers)
{
this.qualifiers.addAll(qualifiers);
return this;
}

public String getName()
{
return name;
}

public NarrowingBeanBuilder<T> name(String name)
{
this.name = name;
return this;
}

public Class<? extends Annotation> getScope()
{
return scope;
}

public NarrowingBeanBuilder<T> scope(Class<? extends Annotation> scope)
{
this.scope = scope;
return this;
}

public boolean isAlternative()
{
return alternative;
}

public NarrowingBeanBuilder<T> alternative(boolean alternative)
{
this.alternative = alternative;
return this;
}

public Set<Class<? extends Annotation>> getStereotypes()
{
return stereotypes;
}

public NarrowingBeanBuilder<T> stereotypes(Set<Class<? extends Annotation>> stereotypes)
{
this.stereotypes = stereotypes;
return this;
}

public NarrowingBean<T> create()
{
return new NarrowingBean<T>(delegate, types, qualifiers, name, scope, alternative, stereotypes);
}
}

0 comments on commit e8c8a8d

Please sign in to comment.