/*
* Copyright (c) 2009, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power Library 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.swingui.table;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import javax.annotation.Nullable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.apache.log4j.Logger;
/**
* This is a basic table model that takes in a result set to be displayed in a
* table. This model can export a given set of rows to a CSV or HTML file. The
* result set is not allowed to be modified in this table.
*/
public class ResultSetTableModel extends AbstractTableModel {
/**
* This result set holds the cell entries in the table.
*/
private ResultSet rs = null;
/**
* The result set passed in here must be scrollable. If it is not
* it should be wrapped in a CachedRowSet first.
*
*/
public ResultSetTableModel(@Nullable ResultSet result) {
this.rs = result;
}
/**
* Used to inject a RS when it gets available.
* @param rs
*/
public void setRs(ResultSet rs) {
this.rs = rs;
}
public int getColumnCount() {
if (rs == null) {
return 0;
}
try {
int i = 0;
while (rs.getMetaData() == null && i < 100) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// no op
}
if (rs.getMetaData()!= null) {
break;
} else {
i++;
}
}
if (rs.getMetaData()!= null) {
return rs.getMetaData().getColumnCount();
} else {
return 0;
}
} catch (SQLException e) {
throw new RuntimeException("Could not get the column count from the result set meta data.", e);
}
}
public int getRowCount() {
if (rs == null) {
return 0;
}
int newRowCount;
try {
int prevRow = rs.getRow();
rs.afterLast();
newRowCount = rs.getRow();
rs.absolute(prevRow);
} catch (SQLException e) {
throw new RuntimeException("Could not access the result set given to the table model", e);
}
return newRowCount;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (rs == null) {
return null;
}
try {
int prevRow = rs.getRow();
rs.absolute(rowIndex + 1);
Object objectAtPosition = rs.getObject(columnIndex + 1);
rs.absolute(prevRow);
return objectAtPosition;
} catch (SQLException e) {
throw new RuntimeException(" Could not access the result set given the rowIndex or columnIndex.", e);
}
}
@Override
public int findColumn(String columnName) {
if (rs == null) {
return -1;
}
try {
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
if (rs.getMetaData().getColumnName(i).equals(columnName)) {
return i;
}
}
} catch (SQLException e) {
throw new RuntimeException("Could not access the result set.", e);
}
return -1;
}
@Override
public String getColumnName(int column){
if (rs == null) {
return "";
}
try {
String colName = rs.getMetaData().getColumnLabel(column + 1);
if (colName == null || colName.equals("")) {
colName = rs.getMetaData().getColumnName(column + 1);
}
return colName;
} catch (SQLException e) {
throw new RuntimeException("Could not get the column name.", e);
}
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (rs == null) {
return Object.class;
}
try {
if (columnIndex < 0 || columnIndex >= rs.getMetaData().getColumnCount()) {
return Object.class;
}
} catch (SQLException e1) {
throw new RuntimeException(e1);
}
int columnType;
try {
columnType = rs.getMetaData().getColumnType(columnIndex + 1);
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (columnType == Types.VARCHAR) {
return String.class;
} else if (columnType == Types.BIT || columnType == Types.INTEGER || columnType == Types.SMALLINT || columnType == Types.TINYINT) {
return Integer.class;
} else if (columnType == Types.DECIMAL || columnType == Types.DOUBLE || columnType == Types.NUMERIC) {
return Double.class;
} else if (columnType == Types.FLOAT) {
return Float.class;
}
return Object.class;
}
/**
* Hook for allowing this model to properly track streaming queries. Call
* this method whenever the resultset in this model has more, less, or
* different data than before.
*/
public void dataChanged() {
if (!SwingUtilities.isEventDispatchThread()) {
// This is a runtime verification for events dispatched to
// this method from threads that are not from the vent dispatch one.
throw new RuntimeException("A call to a UI update was sent from a thread other than the event dispatch thread. See ResultSetTableModel.");
}
fireTableDataChanged();
}
public boolean isRsPresent() {
return !(this.rs == null);
}
}