package info.ata4.util.gui; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ListTableModel extends RowTableModel<List> { /** * Initialize the List with null values. This will set the size of the List * and will prevent an IndexOutOfBoundsException when trying to access an * Element in the List. * * @param size the number of Elements to add to the List * */ protected static List<String> newList(int size) { ArrayList<String> list = new ArrayList<>(size); for (int i = 0; i < size; i++) { list.add(null); } return list; } /** * Constructs an empty * <code>ListTableModel</code> with default column names for the specified * number of * <code>columns</code>. * * @param columns the number of columns the table holds */ public ListTableModel(int columns) { super(newList(columns)); setRowClass(List.class); } /** * Constructs an empty * <code>ListTableModel</code> with customized column names. The number of * columns is determined bye the number of items in the * <code>columnNames</code> List. * * @param columnNames * <code>List</code> containing the names of the new columns */ public ListTableModel(List<String> columnNames) { super(columnNames); setRowClass(List.class); } /** * Constructs a * <code>ListTableModel</code> with the specified number of rows. Default * column names will be used for the specified number of * <code>columns</code>. * * @param rows the number of initially empty rows to create * @param columns the number of columns the table holds */ public ListTableModel(int rows, int columns) { super(newList(columns)); setRowClass(List.class); List<List> data = new ArrayList<>(rows); for (int i = 0; i < rows; i++) { data.add(new ArrayList(columns)); } insertRows(0, data); } /** * Constructs a * <code>ListTableModel</code> with initial data and customized column * names. * * Each item in the * <code>modelData</code> List must also be a List Object containing items * for each column of the row. * * Each column's name will be taken from the * <code>columnNames</code> List and the number of colums is determined by * thenumber of items in the * <code>columnNames</code> List. * * @param modelData the data of the table * @param columnNames * <code>List</code> containing the names of the new columns */ public ListTableModel(List<List> modelData, List<String> columnNames) { super(modelData, columnNames); setRowClass(List.class); } // // Implement the TableModel interface // /** * Returns an attribute value for the cell at * <code>row</code> and * <code>column</code>. * * @param row the row whose value is to be queried * @param column the column whose value is to be queried * @return the value Object at the specified cell * @exception IndexOutOfBoundsException if an invalid row or column was * given */ @Override public Object getValueAt(int row, int column) { List rowData = getRow(row); return rowData.get(column); } /** * Sets the object value for the cell at * <code>column</code> and * <code>row</code>. * <code>value</code> is the new value. This method will generate a * <code>tableChanged</code> notification. * * @param value the new value; this can be null * @param row the row whose value is to be changed * @param column the column whose value is to be changed * @exception IndexOutOfBoundsException if an invalid row or column was * given */ @SuppressWarnings("unchecked") @Override public void setValueAt(Object value, int row, int column) { List rowData = getRow(row); rowData.set(column, value); fireTableCellUpdated(row, column); } /** * Insert a row of data at the * <code>row</code> location in the model. Notification of the row being * added will be generated. * * @param row row in the model where the data will be inserted * @param rowData data of the row being added */ @Override public void insertRow(int row, List rowData) { justifyRow(rowData); super.insertRow(row, rowData); } /** * Insert multiple rows of data at the * <code>row</code> location in the model. Notification of the row being * added will be generated. * * @param row row in the model where the data will be inserted * @param rowList each item in the list is a separate row of data */ @Override public void insertRows(int row, List<List> rowList) { for (List rowData : rowList) { justifyRow(rowData); } super.insertRows(row, rowList); } /* * Make sure each List row contains the required number of columns. */ @SuppressWarnings("unchecked") private void justifyRow(List rowData) { for (int i = rowData.size(); i < getColumnCount(); i++) { rowData.add(null); } } /** * Adds a row of data to the end of the model. Notification of the row being * added will be generated. * * @param rowData data of the row being added */ public void addRow(Object[] rowData) { insertRow(getRowCount(), rowData); } /** * Insert a row of data at the * <code>row</code> location in the model. Notification of the row being * added will be generated. * * @param row row in the model where the data will be inserted * @param rowData data of the row being added */ public void insertRow(int row, Object[] rowData) { insertRow(row, copyToList(rowData)); } /** * Insert multiple rows of data at the * <code>row</code> location in the model. Notification of the row being * added will be generated. * * @param row row in the model where the data will be inserted * @param rowArray each item in the Array is a separate row of data */ public void insertRows(int row, Object[][] rowArray) { List<List> data = new ArrayList<>(rowArray.length); for (int i = 0; i < rowArray.length; i++) { data.add(copyToList(rowArray[i])); } insertRows(row, data); } /* * Copy the information in the Array to a List so a List can be added to the * model */ private List copyToList(Object[] rowData) { List<Object> row = new ArrayList<>(rowData.length); row.addAll(Arrays.asList(rowData)); return row; } /** * Create a ListTableModel given a specific ResultSet. * * The column names and class type will be retrieved from the * ResultSetMetaData. The data is retrieved from each row found in the * ResultSet. The class of * * @param resultSet ResultSet containing results of a database query * @return a newly created ListTableModel * @exception SQLException when an SQL error is encountered */ public static ListTableModel createModelFromResultSet(ResultSet resultSet) throws SQLException { ResultSetMetaData metaData = resultSet.getMetaData(); int columns = metaData.getColumnCount(); // Create empty model using the column names ArrayList<String> columnNames = new ArrayList<>(); for (int i = 1; i <= columns; i++) { String columnName = metaData.getColumnName(i); String columnLabel = metaData.getColumnLabel(i); if (columnLabel.equals(columnName)) { columnNames.add(formatColumnName(columnName)); } else { columnNames.add(columnLabel); } } ListTableModel model = new ListTableModel(columnNames); model.setModelEditable(false); // Assign the class of each column for (int i = 1; i <= columns; i++) { try { String className = metaData.getColumnClassName(i); model.setColumnClass(i - 1, Class.forName(className)); } catch (Exception exception) { } } // Get row data ArrayList<List> data = new ArrayList<>(); while (resultSet.next()) { ArrayList<Object> row = new ArrayList<>(columns); for (int i = 1; i <= columns; i++) { Object o = resultSet.getObject(i); row.add(o); } data.add(row); } model.insertRows(0, data); return model; } }