peer-at-code-framework/src/dev/peerat/framework/DependencyInjector.java

66 lines
1.9 KiB
Java

package dev.peerat.framework;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
public class DependencyInjector{
private Map<String, Object> map;
private List<BiFunction<Constructor<?>, Parameter, Object>> builders;
private Object[] injections;
public DependencyInjector(){
this.map = new HashMap<>();
this.builders = new ArrayList<>();
}
public DependencyInjector of(String name, Object value){
this.map.put(name, value);
return this;
}
public DependencyInjector of(BiFunction<Constructor<?>, Parameter, Object> builder){
this.builders.add(builder);
return this;
}
public DependencyInjector of(Object... injections){
if(this.injections == null){
this.injections = injections;
return this;
}
Object[] copy = new Object[this.injections.length+injections.length];
System.arraycopy(this.injections, 0, copy, 0, this.injections.length);
System.arraycopy(injections, 0, copy, this.injections.length, injections.length);
this.injections = copy;
return this;
}
Object applyDependency(Constructor<?> constructor, Parameter parameter, Map<Class<?>, Object> cache){
Injection annotation = parameter.getAnnotation(Injection.class);
if(annotation != null) return this.map.get(annotation.name());
for(BiFunction<Constructor<?>, Parameter, Object> function : builders){
Object result = function.apply(constructor, parameter);
if(result != null) return result;
}
if(this.injections == null) return null;
Class<?> type = parameter.getType();
Object result = null;
for(Object injection : injections){
if(type.isAssignableFrom(injection.getClass())){
if(cache.containsKey(type)){
throw new IllegalArgumentException("Double dependency for type "+type);
}else{
cache.put(type, injection);
result = injection;
}
}
}
return result;
}
}