package com.softwaremill.common.util.dependency;
import com.google.common.collect.ImmutableList;
import com.softwaremill.common.util.ClassUtil;
import org.jboss.weld.context.bound.BoundRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingDeque;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class D {
private final static Logger log = LoggerFactory.getLogger(D.class);
private static Deque<DependencyProvider> providers = new LinkedBlockingDeque<DependencyProvider>();
/**
* Try to find the given dependency in the registered providers.
*
* @throws RuntimeException If the dependency is not found in any provider.
*/
public static <T> T inject(Class<T> cls, Annotation... qualifiers) {
for (DependencyProvider provider : providers) {
T result = provider.inject(cls, qualifiers);
if (result != null) {
return result;
}
}
throw new RuntimeException("No dependencies of class " + cls + " (" + Arrays.toString(qualifiers) + ") found using providers: " + providers);
}
/**
* @param provider A new dependency provider to add. The provider will be checked first when looking for
* dependencies.
*/
public static void register(DependencyProvider provider) {
log.debug("Registering " + provider);
providers.addFirst(provider);
}
public static void unregister(DependencyProvider provider) {
log.debug("Unregistering " + provider);
providers.remove(provider);
}
public static <T> T withDependencies(Object dep1, Callable<T> what) throws Exception {
return withDependencies(ImmutableList.of(dep1), what);
}
public static <T> T withDependencies(Object dep1, Object dep2,
Callable<T> what) throws Exception {
return withDependencies(ImmutableList.of(dep1, dep2), what);
}
public static <T> T withDependencies(Object dep1, Object dep2, Object dep3,
Callable<T> what) throws Exception {
return withDependencies(ImmutableList.of(dep1, dep2, dep3), what);
}
public static <T> T withDependencies(List<Object> deps, Callable<T> what) throws Exception {
ThreadLocalDependencyProvider dependencyProvider = new ThreadLocalDependencyProvider(deps);
register(dependencyProvider);
try {
return what.call();
} finally {
unregister(dependencyProvider);
}
}
public static Annotation qualifier(Class<? extends Annotation> annotationClass) {
return ClassUtil.instantiateAnnotation(annotationClass);
}
public static QualifiedDependency qualifiedDependency(Object dep, Annotation... qualifiers) {
return new QualifiedDependency(qualifiers, dep);
}
static Set<Annotation> createKeyForAnnotations(Annotation[] annotations) {
return new HashSet<Annotation>(Arrays.asList(annotations));
}
public static void inRequestContext(final Runnable function) {
inRequestContext(new HashMap<String, Object>(), function);
}
public static void inRequestContext(final Map<String, Object> context, final Runnable function) {
final BoundRequestContext requestContext = D.inject(BoundRequestContext.class);
try {
requestContext.associate(context);
requestContext.activate();
function.run();
} finally {
requestContext.invalidate();
requestContext.deactivate();
requestContext.dissociate(context);
}
}
}