package com.hackerdude.apps.sqlide.components;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.table.AbstractTableModel;
import com.hackerdude.apps.sqlide.dataaccess.QueryResults;
/**
* Table Model for a Scrollable ResultSet.
*
* <P>This table model uses a JDBC 2.0 resultset of type TYPE_SCROLL*.
*
* @author David Martinez <A HREF="mailto:david@hackerdude.com">david@hackerdude.com</A>
* @version 1.0
*/
public class ScrollableResultSetTableModel extends AbstractTableModel {
QueryResults queryResults;
int rowCount;
String[] columnNames;
Class[] columnClasses;
ResultSet resultSet;
ArrayList insertBuffers = new ArrayList();
public ScrollableResultSetTableModel(QueryResults queryResults) {
this.queryResults = queryResults;
resultSet = queryResults.getResultSet();
columnNames = queryResults.getColumnNames();
columnClasses = queryResults.getColumnClasses();
setRowCountFromResultSet();
}
private void setRowCountFromResultSet() {
// Since this is a scrollable cursor it's okay to go to the bottom right away.
try {
resultSet.last();
rowCount = resultSet.getRow();
} catch (SQLException exc) {
exc.printStackTrace();
rowCount = 0;
}
}
public int getColumnCount() {
return columnNames.length;
}
public Class getColumnClass(int col) {
return columnClasses[col];
}
public void setValueAt(Object obj, int row, int column) {
if ( row < rowCount ) {
try {
if (resultSet == null)
return;
resultSet.absolute(row + 1);
resultSet.updateString(column + 1, obj.toString());
resultSet.updateRow();
} catch (SQLException exc) {
exc.printStackTrace();
}
} else {
setInsertBufferValueAt(obj, row-rowCount, column);
}
}
public void setInsertBufferValueAt(Object obj, int row, int column) {
RowInserting currentRow = (RowInserting)insertBuffers.get(row);
currentRow.values[column] = obj;
}
public Object getInsertBufferValueAt(int row, int column) {
RowInserting currentRow = (RowInserting)insertBuffers.get(row);
return currentRow.values[column];
}
public Object getValueAt(int row, int column) {
Object result = null;
if ( row < rowCount ) {
try {
if (resultSet == null)
return null;
resultSet.absolute(row + 1);
result = resultSet.getObject(column + 1);
if (result == null)
result = resultSet.getString(column + 1);
} catch (SQLException exc) {
resultSet = null;
return "SQLException";
}
} else {
return getInsertBufferValueAt(row-rowCount, column);
}
return result;
}
public int getRowCount() {
return rowCount+insertBuffers.size();
}
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
public boolean isCellEditable(int row, int column) {
if ( resultSet == null ) return false;
try {
boolean isResultSetEditable = (resultSet.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
return isResultSetEditable;
}
catch (SQLException ex) {
return false;
}
}
public void prepareInsertRow() {
RowInserting newRow = new RowInserting();
newRow.values = new Object[columnNames.length];
insertBuffers.add(newRow);
fireTableRowsInserted(rowCount, rowCount+1);
}
private void insertRow(RowInserting row) throws SQLException {
rowCount++;
resultSet.moveToInsertRow(); // moves cursor to the insert row
for ( int i=0; i<row.values.length; i++ ) {
resultSet.updateObject(i+1, row.values[i]);
}
resultSet.insertRow();
// if ( ! wasEmpty ) resultSet.moveToCurrentRow();
}
class RowInserting {
Object[] values;
}
public synchronized void saveInsertions() throws SQLException {
// boolean wasEmpty = rowCount == 0;
Iterator iterator = insertBuffers.iterator();
while ( iterator.hasNext() ) {
RowInserting row = (RowInserting)iterator.next();
insertRow(row);// , wasEmpty);
}
}
public void deleteRow(int row) throws SQLException {
if ( row < rowCount ) {
resultSet.absolute(row + 1);
resultSet.deleteRow();
} else {
insertBuffers.remove(row-rowCount);
}
rowCount--;
fireTableDataChanged();
}
public synchronized void rollBack() throws SQLException {
insertBuffers.clear();
resultSet.getStatement().getConnection().rollback();
resultSet = null;
rowCount = 0;
fireTableDataChanged();
}
}