/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.client.dataflow;
import com.eas.client.metadata.Field;
import com.eas.client.metadata.Fields;
import com.eas.client.metadata.JdbcField;
import com.eas.script.Scripts;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Wrapper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Reader for jdbc result sets sources. Performs reading of a whole rowset and
* particular subset of rows for the rowset. Reading utilizes converters to
* produce application-specific data while reading.
*
* @author mg
*/
public class JdbcReader {
public interface GeometryReader {
public String readGeometry(Wrapper aRs, int aColumnIndex, Connection aConnection) throws SQLException;
}
public interface TypesResolver {
public String toApplicationType(int aJdbcType, String aRDBMSType);
}
protected static final String RESULTSET_MISSING_EXCEPTION_MSG = "aResultSet argument must be non null";
protected Fields expectedFields;
protected GeometryReader gReader;
protected TypesResolver resolver;
/**
*
* @param aReader
* @param aResolver
*/
protected JdbcReader(GeometryReader aReader, TypesResolver aResolver) {
super();
gReader = aReader;
resolver = aResolver;
}
/**
*
* @param aExpectedFields Fields expected to be in read rowset
* @param aReader
* @param aResolver
*/
public JdbcReader(Fields aExpectedFields, GeometryReader aReader, TypesResolver aResolver) {
this(aReader, aResolver);
expectedFields = aExpectedFields;
}
/**
* Reads data from ResultSet object and creates new Rowset based on the
* data. Warning! The rowset returned doesn't log it's changes.
*
* @param aPageSize Page size of reading process. May be less then zero to
* indicate that whole data should be fetched.
* @param aResultSet
* @return New Rowset object created.
* @throws SQLException
*/
public Collection<Map<String, Object>> readRowset(ResultSet aResultSet, int aPageSize) throws SQLException {
try {
if (aResultSet != null) {
ResultSetMetaData lowLevelJdbcFields = aResultSet.getMetaData();
Fields readFields = readFields(lowLevelJdbcFields);
return readRows(expectedFields != null && !expectedFields.isEmpty() ? expectedFields : readFields, readFields, aResultSet, aPageSize, aResultSet.getStatement().getConnection());
} else {
throw new SQLException(RESULTSET_MISSING_EXCEPTION_MSG);
}
} catch (Exception ex) {
if (ex instanceof SQLException) {
throw (SQLException) ex;
} else {
throw new SQLException(ex);
}
}
}
public Fields readFields(ResultSetMetaData jdbcFields) throws SQLException {
Fields appFields = new Fields();
for (int i = 1; i <= jdbcFields.getColumnCount(); i++) {
Field appField = new JdbcField();
String columnLabel = jdbcFields.getColumnLabel(i);// Column label in jdbc is the name of platypus property
String columnName = jdbcFields.getColumnName(i);
appField.setName(columnLabel != null && !columnLabel.isEmpty() ? columnLabel : columnName);
appField.setOriginalName(columnName);
appField.setNullable(jdbcFields.isNullable(i) == ResultSetMetaData.columnNullable);
appField.setType(resolver.toApplicationType(jdbcFields.getColumnType(i), jdbcFields.getColumnTypeName(i)));
String schemaName = jdbcFields.getSchemaName(i);
String tableName = jdbcFields.getTableName(i);
if (schemaName != null && !schemaName.isEmpty()) {
tableName = schemaName + "." + tableName;
}
appField.setTableName(tableName);
appFields.add(appField);
}
return appFields;
}
/**
* Reads all rows from result set, returning them as an ArrayList
* collection.
*
* @param aExpectedFields
* @param aReadFields Fields instance to be used as rowset's metadata.
* @param aResultSet A result set to read from.
* @param aPageSize Page size of reading process. May be less then zero to
* indicate that whole data should be fetched.
* @return Array of rows had been read.
* @throws SQLException
*/
protected Collection<Map<String, Object>> readRows(Fields aExpectedFields, Fields aReadFields, ResultSet aResultSet, int aPageSize, Connection aConnection) throws SQLException {
try {
if (aResultSet != null) {
Collection<Map<String, Object>> oRows = new ArrayList<>();
while ((aPageSize <= 0 || oRows.size() < aPageSize) && aResultSet.next()) {
Map<String, Object> jsRow = readRow(aExpectedFields, aReadFields, aResultSet, aConnection);
oRows.add(jsRow);
}
return oRows;
} else {
throw new SQLException(RESULTSET_MISSING_EXCEPTION_MSG);
}
} catch (Exception ex) {
if (ex instanceof SQLException) {
throw (SQLException) ex;
} else {
throw new SQLException(ex);
}
}
}
/**
* Reads single row from result set, returning it as a result.
*
* @param aExpectedFields
* @param aReadFields
* @param aResultSet Result set to read from.
* @return The row had been read.
* @throws SQLException
*/
protected Map<String, Object> readRow(Fields aExpectedFields, Fields aReadFields, ResultSet aResultSet, Connection aConnection) throws SQLException {
if (aResultSet != null) {
assert aExpectedFields != null;
Map<String, Object> row = new HashMap<>();
for (int i = 1; i <= aReadFields.getFieldsCount(); i++) {
Field readField = aReadFields.get(i);
Field expectedField = aExpectedFields.get(readField.getName());
Field field = expectedField != null ? expectedField : readField;
Object appObject;
if (Scripts.GEOMETRY_TYPE_NAME.equals(field.getType())) {
appObject = gReader.readGeometry(aResultSet, i, aConnection);
} else {
appObject = JdbcFlowProvider.get(aResultSet, i);
}
row.put(field.getName(), appObject);
}
return row;
}
return null;
}
}