|
|
@@ -2,11 +2,16 @@ package net.ranides.assira.system.impl;
|
|
|
|
|
|
import net.ranides.assira.collection.maps.OpenMap;
|
|
|
import net.ranides.assira.collection.maps.TypeMap;
|
|
|
+import net.ranides.assira.collection.query.CQuery;
|
|
|
+import net.ranides.assira.generic.Ref;
|
|
|
+import net.ranides.assira.reflection.IAttribute;
|
|
|
import net.ranides.assira.reflection.IClass;
|
|
|
+import net.ranides.assira.reflection.IConstructor;
|
|
|
import net.ranides.assira.system.HostContext;
|
|
|
import net.ranides.assira.trace.LoggerUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
|
+import java.util.Comparator;
|
|
|
import java.util.Map;
|
|
|
import java.util.NoSuchElementException;
|
|
|
|
|
|
@@ -28,7 +33,7 @@ public class HostSimpleContext implements HostContext {
|
|
|
return name2instance.get(name);
|
|
|
}
|
|
|
if(name2prototype.containsKey(name)) {
|
|
|
- return name2prototype.get(name).construct();
|
|
|
+ return construct(name2prototype.get(name));
|
|
|
}
|
|
|
throw new NoSuchElementException("No bean with name: " + name);
|
|
|
}
|
|
|
@@ -39,11 +44,17 @@ public class HostSimpleContext implements HostContext {
|
|
|
return type.cast(type2instance.match(type));
|
|
|
}
|
|
|
if(type2prototype.matches(type)) {
|
|
|
- return type.cast(type2prototype.match(type).construct());
|
|
|
+ Object o = construct(type2prototype.match(type));
|
|
|
+ return type.cast(o);
|
|
|
}
|
|
|
throw new NoSuchElementException("No bean with type: " + type);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public <T> T getBean(Class<T> type) {
|
|
|
+ return getBean(IClass.typeinfo(type));
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public boolean isPrototype(String name) {
|
|
|
return name2prototype.containsKey(name);
|
|
|
@@ -64,6 +75,11 @@ public class HostSimpleContext implements HostContext {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void registerPrototype(String name, Class<?> type) {
|
|
|
+ registerPrototype(name, IClass.typeinfo(type));
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void registerSingleton(String name, Object instance) {
|
|
|
type2instance.add(IClass.typefor(instance), instance);
|
|
|
@@ -73,4 +89,42 @@ public class HostSimpleContext implements HostContext {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private Object construct(IClass<?> type) {
|
|
|
+ return type.constructors()
|
|
|
+ .require(IAttribute.PUBLIC)
|
|
|
+ .stream()
|
|
|
+ .sort(Comparator.comparingInt(v -> v.arguments().count()))
|
|
|
+ .reverse()
|
|
|
+ .map(c -> construct(c))
|
|
|
+ .filter(o -> o.isPresent())
|
|
|
+ .first()
|
|
|
+ .orElseThrow(() -> new NoSuchElementException("There is no constructor for bean prototype " + type))
|
|
|
+ .orElseThrow(() -> new NoSuchElementException("There is no constructor for bean prototype " + type));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Ref<Object> construct(IConstructor<?> ctor) {
|
|
|
+ final Object[] args;
|
|
|
+ try {
|
|
|
+ args = ctor.arguments().stream().map(a -> {
|
|
|
+ if(a.type().isPrimitive() || a.type().isArray()) {
|
|
|
+ // skip if argument is not bean
|
|
|
+ throw new NoSuchElementException("primitive");
|
|
|
+ }
|
|
|
+ if(a.type().isSuper(ctor.parent())) {
|
|
|
+ // skip if argument is super class of requested bean
|
|
|
+ // (it's heuristic: we ignore "copying constructors")
|
|
|
+ throw new NoSuchElementException("copy");
|
|
|
+ }
|
|
|
+ return getBean(a.type());
|
|
|
+ }).array();
|
|
|
+ } catch (Exception e) {
|
|
|
+ return Ref.empty();
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return Ref.of(ctor.apply(args));
|
|
|
+ } catch (Exception e) {
|
|
|
+ return Ref.empty();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|