package hirondelle.web4j.database;
import java.util.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.ResultSetMetaData;
import hirondelle.web4j.BuildImpl;
import hirondelle.web4j.util.Args;
/**
Translates a <tt>ResultSet</tt> row into a <tt>Map</tt>.
<P>The returned {@code Map<String, Object>} has :
<ul>
<li>key - column name.
<li>value - column value as an unformatted object. The class of each object is controlled
by the class array passed to the constructor.
</ul>
*/
final class ReportBuilderUnformatted extends ModelBuilder<Map<String, Object>> {
/**
Constructor for applying some processing to raw column values.
<P><tt>aColumnTypes</tt> is used to convert each column into an <tt>Object</tt>.
The supported types are the same as for {@link ConvertColumn}.
@param aColumnTypes defines the type of each column, in order from left to right, as
they appear in the <tt>ResultSet</tt>; contains <tt>N</tt> class literals,
where <tt>N</tt> is the number of columns in the <tt>ResultSet</tt>; contains only
the classes supported by {@link ConvertColumn}; this constructor will create a defensive
copy of this parameter.
*/
ReportBuilderUnformatted(Class<?>[] aColumnTypes){
Args.checkForPositive(aColumnTypes.length);
fColumnTypes = defensiveCopy(aColumnTypes);
fColumnToObject = BuildImpl.forConvertColumn();
}
/**
Returns an unmodifiable <tt>Map</tt>.
<P>See class constructor.
*/
Map<String, Object> build(ResultSet aRow) throws SQLException {
LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();
Object value = null;
ResultSetMetaData metaData = aRow.getMetaData();
for (int columnIdx = 1; columnIdx <= metaData.getColumnCount(); ++columnIdx) {
if ( fColumnTypes.length != metaData.getColumnCount() ) {
throw new IllegalArgumentException(
"Class[] has different number of elements than ResultSet: " + fColumnTypes.length +
" versus " + metaData.getColumnCount () + ", respectively."
);
}
value = getUnformattedObject(aRow, columnIdx);
result.put(metaData.getColumnName(columnIdx), value);
}
return Collections.unmodifiableMap(result);
}
// PRIVATE //
/** The types to which ResultSet columns will be converted. */
private Class<?>[] fColumnTypes;
/** Translates ResultSet columns into desired Objects. */
private ConvertColumn fColumnToObject;
private Class[] defensiveCopy(Class[] aClassArray){
Class[] result = new Class[aClassArray.length];
System.arraycopy(aClassArray, 0, result, 0, aClassArray.length);
return result;
}
private Object getUnformattedObject(ResultSet aRow, int aColumnIdx) throws SQLException {
return fColumnToObject.convert(aRow, aColumnIdx, fColumnTypes[aColumnIdx-1]);
}
}