/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.collector.jdbc.extract;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* <p>Title: ProcessedResultSet</p>
* <p>Description: A navigatable and DB detached container for a {@link ResultSet}.</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.collectors.jdbc.extract.ProcessedResultSet</code></p>
* @todo: <ol>
* <li>Prefetch</li>
* <li>Externalizable</li>
* <li>Clob/Blob Support</li>
* <li>DB MetaData</li>
* <li>Session ID</li>
* <li>Cursor Name</li>
* </ol>
*/
public class ProcessedResultSet implements IProcessedResultSet, IReadOnlyProcessedResultSet {
protected IResultSetExtractor rsetExtractor = new ResultSetExtractorImpl();
protected ThreadLocal<Integer> index = new ThreadLocal<Integer>() {
protected synchronized Integer initialValue() {
return -1;
}
};
protected int rowCount = 0;
protected int colCount = 0;
protected Map<String, Integer> nameToIndex = null;
protected Map<Integer, String> columnNames = null;
protected Map<Integer, Integer> jdbcTypes = null;
protected Map<Integer, String> jdbcTypeNames = null;
protected Map<Integer, String> jdbcClassNames = null;
protected Map<Integer, String> dbTypeNames = null;
protected Map<Integer, Map<Integer, Object>> values = null;
protected String queryName = null;
protected long timeToGet = 0;
/**
* @param rset
* @throws SQLException
* @throws IOException
*/
public ProcessedResultSet(ResultSet rset) throws SQLException, IOException {
this(rset, -1, true);
}
/**
* @param rset
* @param maxRows
* @throws SQLException
* @throws IOException
*/
public ProcessedResultSet(ResultSet rset, int maxRows) throws SQLException, IOException {
this(rset, maxRows , true);
}
/**
* @param rset
* @param maxRows
* @param useStrings
* @throws SQLException
* @throws IOException
*/
public ProcessedResultSet(ResultSet rset, int maxRows, boolean useStrings) throws SQLException, IOException {
long start = System.currentTimeMillis();
values = rsetExtractor.processResultSet(rset, maxRows, useStrings);
timeToGet = System.currentTimeMillis()-start;
ResultSetMetaData rsmd = rset.getMetaData();
colCount = rsmd.getColumnCount();
nameToIndex = new HashMap<String, Integer>(colCount);
jdbcTypes = new HashMap<Integer,Integer>(colCount);
jdbcTypeNames = new HashMap<Integer,String>(colCount);
jdbcClassNames = new HashMap<Integer,String>(colCount);
dbTypeNames = new HashMap<Integer,String>(colCount);
columnNames = new HashMap<Integer,String>(colCount);
for(int i = 1; i <= colCount; i++) {
nameToIndex.put(rsmd.getColumnName(i), i-1);
jdbcTypes.put(i, rsmd.getColumnType(i));
jdbcTypeNames.put(i-1, rsmd.getColumnTypeName(i));
jdbcClassNames.put(i-1, rsmd.getColumnClassName(i));
dbTypeNames.put(i-1, rsmd.getColumnTypeName(i));
columnNames.put(i-1, rsmd.getColumnName(i));
}
rowCount = values.size();
}
/**
* Increment the thread local index counter.
* @return true if the counter was incremented, false if it is at max.
*/
protected boolean incr() {
int i = index.get();
if(i==rowCount-1) return false;
i++; index.set(i);
return true;
}
/**
* Decrement the thread local index counter.
* @return true if the counter was decremented, false if it is at zero.
*/
protected boolean decr() {
int i = index.get();
if(i==0) return false;
i--; index.set(i);
return true;
}
/**
*
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#first()
*/
public void first() {
index.set(0);
}
/**
*
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#beforeFirst()
*/
public void beforeFirst() {
index.set(-1);
}
/**
* @param colId
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#flat(int)
*/
public String flat(int colId, String delim) {
if(colId < 0 || colId > colCount) throw new RuntimeException("Requested column Id out of range. " + colId + " not in [0-" + colCount + "]");
StringBuilder b = new StringBuilder(10*rowCount);
for(Map<Integer, Object> row: values.values()) {
b.append(row.get(colId).toString()).append(delim);
}
return b.toString();
}
/**
* @param colId
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#flat(int)
*/
public String flat(int colId) {
return flat(colId, "");
}
/**
* @param colName
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#flat(java.lang.String)
*/
public String flat(String colName) {
return flat(colName, "");
}
/**
* @param colName
* @param delim
* @return
*/
public String flat(String colName, String delim) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return flat(i, delim);
}
/**
* @param colId
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#get(int)
*/
public Object get(int colId) {
if(colId < 0 || colId > colCount) throw new RuntimeException("Requested column Id out of range. " + colId + " not in [0-" + colCount + "]");
return values.get(index.get()).get(colId);
}
/**
* @param colName
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#get(java.lang.String)
*/
public Object get(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return values.get(index.get()).get(i);
}
/**
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#getColumnCount()
*/
public int getColumnCount() {
return colCount;
}
/**
* Retrieves the JDBC <code>java.sql.Types</code> type code for the passed column id.
* @param col The column id.
* @return the JDBC <code>java.sql.Types</code> type code
*/
public int getColumnType(int col) {
return jdbcTypes.get(col);
}
/**
* Retrieves the JDBC type name for the passed column id.
* @param col The column id.
* @return the JDBC type name
*/
public String getColumnTypeName(int col) {
return jdbcTypeNames.get(col);
}
/**
* Retrieves the Java class name for the passed column id.
* @param col The column id.
* @return The Java Class Name.
*/
public String getColumnClassName(int col) {
return jdbcClassNames.get(col);
}
/**
* Retrieves the Java class name for the passed column name.
* @param col The column name.
* @return The Java Class Name.
*/
public String getColumnClassName(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return jdbcClassNames.get(i);
}
/**
* Retrieves the JDBC <code>java.sql.Types</code> type code for the passed column name.
* @param col The column name.
* @return the JDBC <code>java.sql.Types</code> type code
*/
public int getColumnType(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return jdbcTypes.get(i);
}
/**
* Retrieves the JDBC type name for the passed column name.
* @param col The column name.
* @return the JDBC type name
*/
public String getColumnTypeName(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return jdbcTypeNames.get(i);
}
/**
* Retrieves the database specific type name for the passed column id.
* @param col The column id.
* @return The database specific type Name.
*/
public String getDbTypeName(int col) {
return dbTypeNames.get(col);
}
/**
* Retrieves the database specific type name for the passed column name.
* @param col The column name.
* @return The database specific type Name.
*/
public String getDbTypeName(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return dbTypeNames.get(i);
}
/**
* Retrieves the database column name for the passed column id.
* @param col The column id.
* @return The database column Name.
*/
public String getColumnName(int col) {
return columnNames.get(col);
}
/**
* Retrieves the database column name for the passed column name.
* @param col The column name.
* @return The database column Name.
*/
public String getColumnName(String colName) {
Integer i = nameToIndex.get(colName);
if(i==null) throw new RuntimeException("Could not get column index for name [" + colName + "]");
return columnNames.get(i);
}
/**
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#getRowCount()
*/
public int getRowCount() {
return rowCount;
}
/**
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#next()
*/
public boolean next() {
return incr();
}
/**
* @return
* @see org.helios.collectors.jdbc.extract.IProcessedResultSet#prev()
*/
public boolean prev() {
return decr();
}
/**
* @return the timeToGet
*/
public long getTimeToGet() {
return timeToGet;
}
/**
* Gets the name of the query this result was geneated for.
* @return the name of the query this result was geneated for.
*/
public String getQueryName() {
return queryName;
}
/**
* Sets the name of the query this result was geneated for.
* @param queryName the name of the query this result was geneated for.
*/
public void setQueryName(String queryName) {
this.queryName = queryName;
}
}