package br.com.caelum.iogi;
import br.com.caelum.iogi.exceptions.InvalidTypeException;
import br.com.caelum.iogi.parameters.Parameters;
import br.com.caelum.iogi.reflection.Target;
import br.com.caelum.iogi.spi.DependencyProvider;
import br.com.caelum.iogi.spi.ParameterNamesProvider;
public class ObjectInstantiator implements Instantiator<Object> {
private final Instantiator<Object> argumentInstantiator;
private final DependenciesInjector dependenciesInjector;
private final ParameterNamesProvider parameterNamesProvider;
public ObjectInstantiator(final Instantiator<Object> argumentInstantiator, final DependencyProvider dependencyProvider, final ParameterNamesProvider parameterNamesProvider) {
this.argumentInstantiator = argumentInstantiator;
this.dependenciesInjector = new DependenciesInjector(dependencyProvider);
this.parameterNamesProvider = parameterNamesProvider;
}
public boolean isAbleToInstantiate(final Target<?> target) {
return true;
}
public Object instantiate(final Target<?> target, final Parameters parameters) {
expectingAConcreteTarget(target);
final Parameters parametersForTarget = parameters.focusedOn(target);
return target
.constructors(parameterNamesProvider, dependenciesInjector)
.compatibleWith(parametersForTarget)
.largest()
.instantiate(argumentInstantiator)
.valueWithPropertiesSet();
}
private <T> void expectingAConcreteTarget(final Target<T> target) {
if (!target.isInstantiable())
throw new InvalidTypeException("Cannot instantiate abstract type %s", target.getClassType());
}
}