package com.towel.swing.table; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.swing.table.AbstractTableModel; import com.towel.el.FieldResolver; import com.towel.el.annotation.AnnotationResolver; /** * A TableModel based on reflection. * * @author Marcos Vasconcelos */ public class ObjectTableModel<T> extends AbstractTableModel implements Iterable<T> { private List<T> data; private FieldResolver fields[]; private boolean editDefault; private Boolean editableCol[]; /** * Creates an <code>ObjectTableModel</code> using the specified * <code>AnnotationResolver</code> to resolve the columns. * * @param resolver * the annotation resolver * @param cols * columns to be resolved */ public ObjectTableModel(AnnotationResolver resolver, String cols) { data = new ArrayList<T>(); this.fields = (FieldResolver[]) resolver.resolve(cols).clone(); editDefault = false; editableCol = new Boolean[fields.length]; } /** * Creates an <code>ObjectTableModel</code> using the a AnnotationResolver * created with the clazz param to resolve columns. * * @param clazz * the clazz of type T * @param cols * columns to be resolved */ public ObjectTableModel(Class<T> clazz, String cols) { this(new AnnotationResolver(clazz), cols); } /** * Creates an <code>ObjectTableModel</code> using the specified fields. * * @param fields */ public ObjectTableModel(FieldResolver fields[]) { data = new ArrayList<T>(); this.fields = (FieldResolver[]) fields.clone(); editDefault = false; } /** * Sets the default condition for cell editing. * * @param editable * <tt>true</tt> if the cells are editable by default */ public void setEditableDefault(boolean editable) { editDefault = editable; } /** * Sets the condition for the specified column's cells editing * * @param col * the column index * @param editable * <tt>true</tt> if the cells in specified column are editable by * default */ public void setColEditable(int col, boolean editable) { editableCol[col] = editable; } /** * Returns <tt>true</tt> if the cell at specified row and column is * editable. * * @return <tt>true</tt> if the cell at specified row and column is * editable. */ public boolean isCellEditable(int i, int k) { if (editableCol == null || editableCol[k] == null) return editDefault; return editableCol[k]; } public int getColumnCount() { return fields.length; } public int getRowCount() { return data.size(); } /** * Returns the value for the cell at specified row and column. * * @param arg0 * the row whose value is to be queried * @param arg1 * the column whose value is to be queried * @return the value of the specified cell */ public Object getValueAt(int arg0, int arg1) { try { Object obj = data.get(arg0); Object obj2 = fields[arg1].getValue(obj); return obj2; } catch (Exception e) { return null; } } /** * Sets the value in the cell at specified row and column to * <code>value</code>. * * @param value * the new value * @param arg0 * the row whose value is to be changed * @param arg1 * the column whose value is to be changed */ public void setValueAt(Object value, int arg0, int arg1) { try { Object obj = data.get(arg0); fields[arg1].setValue(obj, value); fireTableCellUpdated(arg0, arg1); } catch (Exception e) { e.printStackTrace(); } } /** * Returns the value object in the specified row index. * * @param arg0 * the row index * @return the value object in the specified row index */ public T getValue(int arg0) { return data.get(arg0); } /** * Returns the name of the column at specified column index. * * @return the name of the column at specified column index */ public String getColumnName(int col) { return fields[col].getName(); } /** * Appends a value object to the end of this table model. * * @param obj * the value to be added */ public void add(T obj) { data.add(obj); // fireTableDataChanged(); int lastIndex = getRowCount() - 1; fireTableRowsInserted(lastIndex, lastIndex); } /** * Removes all the values of this table model. */ public void clear() { data = new ArrayList<T>(); fireTableDataChanged(); } /** * Sets this table model data list. * * @param data * the data list */ public void setData(List<T> data) { this.data = data; fireTableDataChanged(); } /** * Removes the value at the specified row. * * @param row * the index of the value to be removed */ public void remove(int row) { data.remove(row); // fireTableDataChanged(); fireTableRowsDeleted(row, row); } /** * Returns this table model data list * * @return this table model data list */ public List<T> getData() { return new ArrayList<T>(data); } /** * Removes all the values in the specified rows. * * @param idx * the rows to be removed */ public void remove(int idx[]) { for (int i = idx.length - 1; i >= 0; i--) { remove(idx[i]); } } /** * Removes from this table model all the values contained in the specified * list. * * @param objs * the list of values to be removed */ public void remove(List<T> objs) { for (T t : objs) remove(indexOf(t)); } /** * Removes the first occurrence of the specified value from this table * model. * * @param obj * the value to be removed */ public void remove(T obj) { remove(indexOf(obj)); } /** * Appends all of the values in the specified collection to this table * model. * * @param coll * collection of values to be added */ public void addAll(Collection<T> coll) { for (T t : coll) add(t); } /** * Returns a list containing all the values in the specified rows. * * @param idx * the rows to be returned in the list * @return the list of values */ public List<T> getList(int idx[]) { List<T> list = new ArrayList<T>(); int size = idx.length; for (int j = 0; j < size; j++) list.add(getValue(idx[j])); return list; } /** * Returns the index of the first occurrence of the specified value in this * table model, or -1 if this model does not contain the value. * * @param obj * the value to search for * @return the index of the first occurrence of the specified value or -1 if * it's not found. */ public int indexOf(T obj) { return data.indexOf(obj); } /** * Returns <tt>true</tt> if this table model contains no values * * @return <tt>true</tt> if this table model contains no values */ public boolean isEmpty() { return data.isEmpty(); } /** * Returns the field resolver associated to the specified column. * * @param colIndex * the column index * @return the field resolver associated to the specified column */ public FieldResolver getColumnResolver(int colIndex) { return fields[colIndex]; } /** * Returns the column class for all the cell values in the column. * * @param col * the index of the column * @return the column class */ public Class<?> getColumnClass(int col) { return getColumnResolver(col).getFieldType(); } @Override public Iterator<T> iterator() { return data.iterator(); } }