package org.sdif4j.cdi;
import org.sdif4j.InjectContext;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.inject.Provider;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.Set;
/**
* Base CDI InjectContext implementation
*
* @author Sergey Chernov
*/
public abstract class AbstractCdiInjectContext implements InjectContext {
protected abstract BeanManager getBeanManager();
protected abstract CreationalContext getCreationalContext();
public <T> T getInstance(Class<T> clazz) {
final BeanManager bm = getBeanManager();
final Bean<?> bean = getBean(bm, clazz);
return getReference(bm, clazz, bean);
}
public <T> Provider<T> getProvider(final Class<T> clazz) {
final BeanManager bm = getBeanManager();
final Bean<?> bean = getBean(bm, clazz);
return new Provider<T>() {
public T get() {
return getReference(bm, clazz, bean);
}
};
}
public <T> T getInstance(Class<T> clazz, String name) {
final BeanManager bm = getBeanManager();
final Bean<?> bean = getBean(bm, clazz, name);
return getReference(bm, clazz, bean);
}
@SuppressWarnings("unchecked")
public void injectMembers(Object instance) {
final BeanManager bm = getBeanManager();
final CreationalContext creationalContext = getCreationalContext();
InjectionTarget<Object> injectionTarget = (InjectionTarget<Object>) bm.createInjectionTarget(
bm.createAnnotatedType(instance.getClass()));
injectionTarget.inject(instance, creationalContext);
}
private <T> T getReference(BeanManager bm, Class<T> clazz, Bean<?> bean) {
final CreationalContext<?> ctx = bm.createCreationalContext(bean);
return clazz.cast(bm.getReference(bean, clazz, ctx));
// do NOT call this
// ctx.release();
}
private <T> Bean<?> getBean(BeanManager bm, Class<T> clazz) {
final Set<Bean<?>> beans = bm.getBeans(clazz);
if (beans.isEmpty()) {
// not sure this is good idea, but it should work for jars without beans.xml file
// return clazz.newInstance();
throw new IllegalStateException("No beans of type " + clazz);
}
final Iterator<Bean<?>> itr = beans.iterator();
final Bean<?> bean = itr.next();
if (itr.hasNext()) {
throw new IllegalStateException("Non-unique bean instance of type " + clazz);
}
return bean;
}
private <T> Bean<?> getBean(BeanManager bm, Class<T> clazz, String name) {
final Set<Bean<?>> beans = bm.getBeans(clazz);
if (beans.isEmpty()) {
throw new IllegalStateException("No beans of type " + clazz);
}
for (Bean<?> bean : beans) {
final Set<Annotation> qualifiers = bean.getQualifiers();
if (qualifiers.contains(new NamedImpl(name))) {
return bean;
}
}
throw new IllegalStateException("No beans of type " + clazz + " named [" + name + "]");
}
}