package br.com.caelum.iogi.collections; import java.lang.reflect.Array; import java.util.Collection; import java.util.TreeSet; import br.com.caelum.iogi.Instantiator; import br.com.caelum.iogi.parameters.Parameters; import br.com.caelum.iogi.reflection.Target; public class ArrayInstantiator implements Instantiator<Object> { private final Instantiator<Object> elementInstantiator; public ArrayInstantiator(final Instantiator<Object> elementInstantiator) { this.elementInstantiator = elementInstantiator; } public boolean isAbleToInstantiate(final Target<?> target) { return target.getClassType().isArray(); } public Object instantiate(final Target<?> target, final Parameters parameters) { final ParametersByIndex parametersByIndex = new ParametersByIndex(parameters, target); final ArrayFactory factory = new ArrayFactory(target, parametersByIndex); return factory.getArray(); } private class ArrayFactory { private final ParametersByIndex parametersByIndex; private final Target<?> arrayTarget; public ArrayFactory(final Target<?> target, final ParametersByIndex parametersByIndex) { this.arrayTarget = target; this.parametersByIndex = parametersByIndex; } public Object getArray() { final Object array = makeArray(); int indexIntoTheArray = 0; final Collection<Integer> orderedIndexes = new TreeSet<Integer>(parametersByIndex.indexes()); for (final int indexOfTheParameters : orderedIndexes) { final Parameters parameters = parametersByIndex.at(indexOfTheParameters); Array.set(array, indexIntoTheArray++, instantiateArrayElement(parameters)); } return array; } private Object makeArray() { final int arrayLength = parametersByIndex.count(); return Array.newInstance(arrayTarget.arrayElementType(), arrayLength); } private Object instantiateArrayElement(final Parameters parameters) { final Target<?> elementTarget = arrayTarget.arrayElementTarget(); return elementInstantiator.instantiate(elementTarget, parameters); } } }