package org.springframework.data.mapping.model;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
enum ReflectionEntityInstantiator implements EntityInstantiator {
INSTANCE;
private static final Object[] EMPTY_ARGS = new Object[0];
@SuppressWarnings("unchecked")
public <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T createInstance(E entity,
ParameterValueProvider<P> provider) {
PreferredConstructor<? extends T, P> constructor = entity.getPersistenceConstructor();
if (constructor == null) {
try {
Class<?> clazz = entity.getType();
if (clazz.isArray()) {
Class<?> ctype = clazz;
int dims = 0;
while (ctype.isArray()) {
ctype = ctype.getComponentType();
dims++;
}
return (T) Array.newInstance(clazz, dims);
} else {
return BeanUtils.instantiateClass(entity.getType());
}
} catch (BeanInstantiationException e) {
throw new MappingInstantiationException(entity, Collections.emptyList(), e);
}
}
int parameterCount = constructor.getConstructor().getParameterCount();
Object[] params = parameterCount == 0 ? EMPTY_ARGS : new Object[parameterCount];
int i = 0;
for (Parameter<?, P> parameter : constructor.getParameters()) {
params[i++] = provider.getParameterValue(parameter);
}
try {
return BeanUtils.instantiateClass(constructor.getConstructor(), params);
} catch (BeanInstantiationException e) {
throw new MappingInstantiationException(entity, new ArrayList<>(Arrays.asList(params)), e);
}
}
}