package org.jdbi.v3.core.array;
import java.lang.reflect.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import org.jdbi.v3.core.mapper.ColumnMapper;
import org.jdbi.v3.core.statement.StatementContext;
class ArrayColumnMapper implements ColumnMapper<Object> {
private static final CopyOnWriteArraySet<Integer> UNSUPPORTED_TYPES = new CopyOnWriteArraySet<>();
private final ColumnMapper<?> elementMapper;
private final Class<?> componentType;
ArrayColumnMapper(ColumnMapper<?> elementMapper,
Class<?> componentType) {
this.elementMapper = elementMapper;
this.componentType = componentType;
}
@Override
public Object map(ResultSet r, int columnNumber, StatementContext ctx) throws SQLException {
java.sql.Array array = r.getArray(columnNumber);
if (array == null) {
return null;
}
try {
return buildArray(array, ctx);
} finally {
array.free();
}
}
private Object buildArray(java.sql.Array array, StatementContext ctx) throws SQLException {
if (!UNSUPPORTED_TYPES.contains(array.getBaseType())) {
try {
Object ary = array.getArray();
if (componentType.equals(ary.getClass().getComponentType())) {
return ary;
}
} catch (SQLException ignore) {
}
}
UNSUPPORTED_TYPES.add(array.getBaseType());
return buildFromResultSet(array, ctx);
}
private Object buildFromResultSet(java.sql.Array array, StatementContext ctx) throws SQLException {
List<Object> list = new ArrayList<>();
try (ResultSet rs = array.getResultSet()) {
while (rs.next()) {
list.add(elementMapper.map(rs, 2, ctx));
}
}
Object ary = Array.newInstance(componentType, list.size());
if (componentType.isPrimitive()) {
for (int i = 0; i < list.size(); i++) {
Array.set(ary, i, list.get(i));
}
return ary;
}
return list.toArray((Object[]) ary);
}
}