ch.jalu.injector.extras.handlers.AllInstancesAnnotationHandler Maven / Gradle / Ivy
package ch.jalu.injector.extras.handlers;
import ch.jalu.injector.context.ObjectIdentifier;
import ch.jalu.injector.context.ResolutionContext;
import ch.jalu.injector.context.ResolutionType;
import ch.jalu.injector.exceptions.InjectorException;
import ch.jalu.injector.extras.AllInstances;
import ch.jalu.injector.handlers.dependency.TypeSafeAnnotationHandler;
import ch.jalu.injector.handlers.instantiation.Resolution;
import ch.jalu.injector.utils.InjectorUtils;
import ch.jalu.injector.utils.ReflectionUtils;
import org.reflections.Reflections;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Handler for {@link AllInstances}. Finds all subtypes of the given dependency,
* instantiates them and assigns the collection to the given dependency.
*
* Requires that you add the reflections project
* as dependency to be able to use this.
*/
public class AllInstancesAnnotationHandler extends TypeSafeAnnotationHandler {
private Reflections reflections;
public AllInstancesAnnotationHandler(String rootPackage) {
reflections = new Reflections(rootPackage);
}
@Override
protected Class getAnnotationType() {
return AllInstances.class;
}
@Override
public Resolution> resolveValueSafely(ResolutionContext context, AllInstances annotation) {
// The raw type, e.g. List or array
final Class> rawType = context.getIdentifier().getTypeAsClass();
// The type of the collection, e.g. String for List or String[]
final Class genericType = ReflectionUtils.getCollectionType(rawType, context.getIdentifier().getType());
if (genericType == null) {
throw new InjectorException("Unsupported dependency of type '" + rawType
+ "' annotated with @AllInstances. (Or did you forget the generic type?)");
}
@SuppressWarnings("unchecked")
Set> subTypes = reflections.getSubTypesOf(genericType);
ResolutionType resolutionType = context.getIdentifier().getResolutionType();
List dependencies = subTypes.stream()
.filter(InjectorUtils::canInstantiate)
.map(clazz -> new ObjectIdentifier(resolutionType, clazz))
.collect(Collectors.toList());
return new AllInstancesInstantiation(rawType, dependencies);
}
private static final class AllInstancesInstantiation implements Resolution