package io.ebeaninternal.server.dto;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.server.type.TypeManager;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.sql.SQLException;
class DtoMetaConstructor {
private final Class<?>[] types;
private final MethodHandle handle;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private final ScalarType<?>[] scalarTypes;
DtoMetaConstructor(TypeManager typeManager, Constructor<?> constructor, Class<?> someClass) throws NoSuchMethodException, IllegalAccessException {
this.types = constructor.getParameterTypes();
this.scalarTypes = new ScalarType[types.length];
for (int i = 0; i < types.length; i++) {
scalarTypes[i] = typeManager.getScalarType(types[i]);
}
this.handle = LOOKUP.findConstructor(someClass, typeFor(types));
}
private MethodType typeFor(Class<?>[] types) {
return MethodType.methodType(void.class, types);
}
Class<?>[] getTypes() {
return types;
}
int getArgCount() {
return types.length;
}
Object defaultConstructor() {
try {
return handle.invokeWithArguments();
} catch (Throwable e) {
throw new RuntimeException("Unexpected error invoking constructor", e);
}
}
public Object process(DataReader dataReader) throws SQLException {
Object[] values = new Object[scalarTypes.length];
for (int i = 0; i < scalarTypes.length; i++) {
values[i] = scalarTypes[i].read(dataReader);
}
return invoke(values);
}
private Object invoke(Object... args) {
try {
return handle.invokeWithArguments(args);
} catch (Throwable e) {
throw new RuntimeException("Unexpected error invoking constructor", e);
}
}
}