![JAR search and dependency download from the Maven repository](/logo.png)
it.espr.injector.ClassInspector Maven / Gradle / Ivy
package it.espr.injector;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
public class ClassInspector {
private Configuration configuration;
private Utils utils;
ClassInspector(Configuration configuration) {
super();
this.configuration = configuration;
this.utils = new Utils();
}
@SuppressWarnings("unchecked")
private class MyTypeSafeMap {
private Map> map = new HashMap<>();
public void put(Class type, Bean value) {
map.put(utils.key(value.name, type), value);
}
public Bean get(Class type, String name) {
return (Bean) map.get(utils.key(name, type));
}
}
private MyTypeSafeMap cache = new MyTypeSafeMap();
public Bean inspect(Class type) throws BeanException {
return this.inspect(type, null);
}
public Bean inspect(Class type, String named) throws BeanException {
Bean bean = this.cache.get(type, named);
if (bean == null) {
if (this.configuration.instances.containsKey(utils.key(named, type))) {
bean = new Bean<>(named, utils.key(named, type), true, type, null, null, null);
} else if (this.configuration.isBound(type)) {
bean = this.inspectBindings(type, named);
} else {
String name = this.inspectName(type);
if (!utils.isEmpty(named) && (utils.isEmpty(name) || !named.equals(name))) {
return null;
}
Constructor constructor = inspectConstructors(type);
String key = utils.key(name, type);
boolean singleton = this.inspectSingleton(type);
List> constructorParameters = inspectConstructorParameters(constructor);
Map> fields = this.inspectFields(type);
bean = new Bean(name, key, singleton, type, constructor, constructorParameters, fields);
}
this.cache.put(type, bean);
}
return bean;
}
public Bean inspectBindings(Class type, String named) throws BeanException {
Collection> candidates = this.configuration.getBindings(type);
List> candidateBeans = new ArrayList<>();
for (Class candidate : candidates) {
Bean candidateBean = this.inspect(candidate, named);
if (candidateBean != null) {
candidateBeans.add(candidateBean);
}
}
if (candidateBeans.size() != 1) {
throw new BeanException("Found '" + candidateBeans.size() + "' candidates for bean for '" + type + "': Either you forgot to bind the bean or add @Named to it");
}
return candidateBeans.get(0);
}
private boolean inspectSingleton(Class> type) {
return type.isAnnotationPresent(Singleton.class);
}
private String inspectName(Class> type) {
String name = null;
Named named = type.getAnnotation(Named.class);
if (named != null && named.value() != null && !named.value().trim().equals("")) {
name = named.value();
}
return name;
}
private Map> inspectFields(Class> type) throws BeanException {
Map> fields = new LinkedHashMap<>();
Class> c = type;
while (!c.equals(Object.class)) {
Field[] declaredFields = c.getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(Inject.class)) {
fields.put(field, null);
}
}
c = c.getSuperclass();
}
for (Entry> entry : fields.entrySet()) {
Class> t = entry.getKey().getType();
Named named = entry.getKey().getAnnotation(Named.class);
String n = null;
if (named != null && !utils.isEmpty(named.value())) {
n = named.value().trim();
}
Bean> bean = this.inspect(t, n);
if (bean == null) {
throw new BeanException("Can't find a bean for type '" + t + "' @Named as '" + n + "'");
}
entry.setValue(bean);
}
return fields.isEmpty() ? null : fields;
}
private List> inspectConstructorParameters(Constructor> constructor) throws BeanException {
List> constructorParametersBeans = null;
Class>[] constructorParameters = constructor.getParameterTypes();
if (constructorParameters.length != 0) {
constructorParametersBeans = new ArrayList<>();
for (int index = 0; index < constructorParameters.length; index++) {
try {
String named = utils.getAnnotationValue(Named.class, constructor.getParameterAnnotations()[index]);
constructorParametersBeans.add(this.inspect(constructorParameters[index], named));
} catch (BeanException e) {
throw new BeanException("Problem when inspecting '" + index + "' constructor parameter of type '" + constructorParameters[index] + "'");
}
}
}
return constructorParametersBeans;
}
@SuppressWarnings("unchecked")
public Constructor inspectConstructors(Class type) throws BeanException {
List> constructors = Arrays.asList(type.getDeclaredConstructors());
Iterator> iterator = constructors.iterator();
while (iterator.hasNext()) {
Constructor> constructor = iterator.next();
List modifiers = Arrays.asList(constructor.getModifiers());
for (Integer modifier : modifiers) {
if (Modifier.isPublic(modifier)) {
break;
}
iterator.remove();
}
}
if (constructors.size() != 1) {
throw new BeanException("Found '" + constructors.size() + "' valid constructors - can resolve as a bean");
}
return (Constructor) constructors.get(0);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy