Class HeaderDetailTableModel<T>

  • Type Parameters:
    T - the type of the group bean (typically the header)
    All Implemented Interfaces:
    BeanTableModel<T>, ColumnIdentifier, MixedRowTableModel, java.io.Serializable, javax.swing.table.TableModel
    Direct Known Subclasses:
    BufferedHeaderDetailTableModel

    public class HeaderDetailTableModel<T>
    extends javax.swing.table.AbstractTableModel
    implements MixedRowTableModel, BeanTableModel<T>
    A MixedRowTableModel for which the groups contain a header row followed by one or more detail rows. Multiple detail types are supported. A DetailAdapter is used to determine a detail's type and to access the detail beans within a group. A set of ColumnAdapters must be provided for the header and for each detail type. The header ColumnAdapters operate on the group bean and the detail ColumnAdapters operate on the detail bean returned by the DetailAdapter.

    To improve performance, the row indices of the group beans are kept in a lookup table. The key for this lookup table is provided by a Function. Function.identity() can be used for that purpose if all group instances are guaranteed to be unique (i.e. multiple instances of a group can't exist) or if the group class overrides Object.equals(Object) and Object.hashCode(). Important: The ID of a group must not be modified after the group is added to the model, and any fields used for that ID should not be editable in the UI. See HashList for further details.

    This class implements BeanTableModel for compatibility with BeanModelRowSorter. The implementation of the interface allows sorting and filtering of the group beans in the view.

    See Also:
    Serialized Form
    • Field Summary

      Fields 
      Modifier and Type Field Description
      protected DetailAdapter<T> detailAdapter  
      • Fields inherited from class javax.swing.table.AbstractTableModel

        listenerList
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      protected HeaderDetailTableModel​(DetailAdapter<T> detailAdapter, java.util.function.Function<? super T,​?> idFunction)
      Partial constructor for sub-classes.
        HeaderDetailTableModel​(DetailAdapter<T> detailAdapter, java.util.function.Function<? super T,​?> idFunction, java.util.List<? extends ColumnAdapter<T,​?>> columnAdapters, java.util.List<? extends java.util.List<? extends ColumnAdapter<?,​?>>> detailColumnAdapters)  
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void addBean​(int index, T bean)
      Insert a group in the table at the specified group index.
      void fireTableRowsDeleted​(int firstRow, int lastRow)
      Overridden to update group row offsets.
      void fireTableRowsInserted​(int firstRow, int lastRow)
      Overridden to update group row offsets.
      T getBean​(int index)
      Get the group bean at the specified index.
      T getBeanAtRow​(int rowIndex)
      Get the group at the specified row.
      int getBeanCount()
      Get the number of groups.
      java.util.List<T> getBeans()
      Get the group beans.
      java.lang.Class<?> getCellClass​(int rowIndex, int columnIndex)  
      ColumnAdapter<T,​?> getColumnAdapter​(int index)
      Get a header ColumnAdapter.
      java.lang.Class<?> getColumnClass​(int columnIndex)  
      java.lang.Class<?> getColumnClass​(int typeIndex, int columnIndex)  
      int getColumnCount()  
      ColumnAdapter<T,​?> getColumnIdentifier​(int columnIndex)  
      ColumnAdapter<?,​?> getColumnIdentifier​(int typeIndex, int columnIndex)  
      int getColumnIndex​(ColumnAdapter<T,​?> identifier)
      Get the column index for a header ColumnAdapter.
      java.lang.String getColumnName​(int columnIndex)  
      java.lang.String getColumnName​(int typeIndex, int columnIndex)  
      java.awt.Cursor getCursor​(java.awt.event.MouseEvent event, javax.swing.JTable table, int rowIndex, int columnIndex)
      Get the mouse cursor to display for a cell.
      protected ColumnAdapter<java.lang.Object,​java.lang.Object> getDetailColumnAdapter​(int typeIndex, int columnIndex)  
      int getDetailColumnIndex​(int subRowType, ColumnAdapter<?,​?> adapter)
      Get the column index for a detail ColumnAdapter.
      protected java.lang.Object getDetailValueAt​(java.lang.Object detail, int typeIndex, int columnIndex)
      Get the detail value for the specified detail type and column.
      int getGroupNumber​(int rowIndex)  
      protected int getInsertionIndex​(T bean)
      Get the index at which a bean should be inserted.
      int getLeadRowForGroup​(int beanIndex)  
      int getRowCount()  
      int getRowCount​(int beanIndex)  
      int getRowTypeCount()  
      int getRowTypeIndex​(int rowIndex)  
      int getSubRowIndex​(int rowIndex)  
      java.lang.Object getValue​(T bean, int columnIndex)
      Get a column cell value for a bean.
      java.lang.Object getValueAt​(int rowIndex, int columnIndex)  
      void handleClick​(java.awt.event.MouseEvent event, javax.swing.JTable table, int rowIndex, int columnIndex)
      Handle a mouse click on a cell.
      int indexOf​(java.util.function.Predicate<T> condition)  
      int indexOf​(T bean)
      Get thd index of a group in the list of groups.
      boolean isCellEditable​(int rowIndex, int columnIndex)
      Delegates to the header/detail column adapters.
      boolean isSubRow​(int rowIndex)  
      void removeAll​(java.util.List<T> rowBeans)
      Clear the table data.
      void removeBean​(T bean)
      Remove a group from the table.
      int rowIndexOf​(T bean)
      Get the row index of the header of a group.
      void setBean​(int index, T bean)
      Replace a group in the table.
      void setBeans​(java.util.Collection<T> beans)
      Replace the list of groups.
      protected void setCellValue​(java.lang.Object value, int rowIndex, int columnIndex)
      Set a value on a header or detail.
      protected void setColumnAdapters​(java.util.List<? extends ColumnAdapter<T,​?>> columnAdapters)
      Set the header ColumnAdapters.
      protected void setDetailColumnAdapters​(java.util.List<? extends java.util.List<? extends ColumnAdapter<?,​?>>> detailColumnAdapters)
      Set the detail ColumnAdapters.
      void updateBeans​(java.util.Collection<T> beans, java.util.function.BiPredicate<T,​T> isEqual)
      Update existing rows and add missing rows to the table model.
      protected void updateRowOffsets​(int beanIndex)
      Update the group row offsets starting with the specified group.
      • Methods inherited from class javax.swing.table.AbstractTableModel

        addTableModelListener, findColumn, fireTableCellUpdated, fireTableChanged, fireTableDataChanged, fireTableRowsUpdated, fireTableStructureChanged, getListeners, getTableModelListeners, removeTableModelListener, setValueAt
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • Methods inherited from interface javax.swing.table.TableModel

        addTableModelListener, removeTableModelListener, setValueAt
    • Constructor Detail

      • HeaderDetailTableModel

        protected HeaderDetailTableModel​(DetailAdapter<T> detailAdapter,
                                         java.util.function.Function<? super T,​?> idFunction)
        Partial constructor for sub-classes. The ColumnAdapters must be set to complete construction. Mostly intended to allow ColumnAdapters to be defined as non-static inner classes of the model.
        Parameters:
        detailAdapter - the DetailAdapter for accessing detail rows
        idFunction - the Function for supplying the ID of a group.
      • HeaderDetailTableModel

        public HeaderDetailTableModel​(DetailAdapter<T> detailAdapter,
                                      java.util.function.Function<? super T,​?> idFunction,
                                      java.util.List<? extends ColumnAdapter<T,​?>> columnAdapters,
                                      java.util.List<? extends java.util.List<? extends ColumnAdapter<?,​?>>> detailColumnAdapters)
        Parameters:
        detailAdapter - the DetailAdapter for accessing detail rows
        idFunction - the Function for supplying the ID of a group.
        columnAdapters - the ColumnAdapters for the group header row
        detailColumnAdapters - the ColumnAdapters for the group detail rows
    • Method Detail

      • getColumnAdapter

        public ColumnAdapter<T,​?> getColumnAdapter​(int index)
        Get a header ColumnAdapter.
        Parameters:
        index - the column index
      • setDetailColumnAdapters

        protected void setDetailColumnAdapters​(java.util.List<? extends java.util.List<? extends ColumnAdapter<?,​?>>> detailColumnAdapters)
        Set the detail ColumnAdapters. The list must contain a list of ColumnAdapters for each detail type. The list should be ordered to correspond with DetailAdapter.getDetailTypeIndex(Object, int).
        Throws:
        java.lang.NullPointerException - if called before setColumnAdapters(List)
        java.lang.IllegalArgumentException - if the number of adapters for any detail type doesn't match the number of header adapters
      • getRowTypeCount

        public int getRowTypeCount()
        Specified by:
        getRowTypeCount in interface MixedRowTableModel
        Returns:
        thw number of row types defined by this model.
      • getColumnCount

        public int getColumnCount()
        Specified by:
        getColumnCount in interface javax.swing.table.TableModel
      • getDetailColumnIndex

        public int getDetailColumnIndex​(int subRowType,
                                        ColumnAdapter<?,​?> adapter)
        Get the column index for a detail ColumnAdapter.
        Parameters:
        subRowType - the detail type index
        adapter - the detail ColumnAdapter
      • getBeans

        public java.util.List<T> getBeans()
        Get the group beans.
      • setBeans

        public void setBeans​(java.util.Collection<T> beans)
        Replace the list of groups. The groups will be added in iteration order.
        Specified by:
        setBeans in interface BeanTableModel<T>
        Parameters:
        beans - the new rows
      • updateBeans

        public void updateBeans​(java.util.Collection<T> beans,
                                java.util.function.BiPredicate<T,​T> isEqual)
        Description copied from interface: BeanTableModel
        Update existing rows and add missing rows to the table model.
        Specified by:
        updateBeans in interface BeanTableModel<T>
        Parameters:
        beans - beans to update/append
        isEqual - used to determine if a row is already in the model
      • getBean

        public T getBean​(int index)
        Get the group bean at the specified index.
        Specified by:
        getBean in interface BeanTableModel<T>
        Parameters:
        index - the index of the group in the bean list
      • getBeanAtRow

        public T getBeanAtRow​(int rowIndex)
        Get the group at the specified row.
        Parameters:
        rowIndex - the index of a row in the table
      • addBean

        public void addBean​(int index,
                            T bean)
        Insert a group in the table at the specified group index.
        Parameters:
        index - the insertion point in the list of groups
        bean - the group to add
      • fireTableRowsInserted

        public void fireTableRowsInserted​(int firstRow,
                                          int lastRow)
        Overridden to update group row offsets.
        Overrides:
        fireTableRowsInserted in class javax.swing.table.AbstractTableModel
      • fireTableRowsDeleted

        public void fireTableRowsDeleted​(int firstRow,
                                         int lastRow)
        Overridden to update group row offsets.
        Overrides:
        fireTableRowsDeleted in class javax.swing.table.AbstractTableModel
      • setBean

        public void setBean​(int index,
                            T bean)
        Replace a group in the table.
        Parameters:
        index - the index in the list of groups.
        bean - the replacement group
      • removeBean

        public void removeBean​(T bean)
        Remove a group from the table.
        Parameters:
        bean - the group to remove
      • removeAll

        public void removeAll​(java.util.List<T> rowBeans)
        Clear the table data.
      • updateRowOffsets

        protected void updateRowOffsets​(int beanIndex)
        Update the group row offsets starting with the specified group.
        Parameters:
        beanIndex - the index of the first group to be updated
      • getRowCount

        public int getRowCount​(int beanIndex)
        Specified by:
        getRowCount in interface MixedRowTableModel
        Parameters:
        beanIndex - the group index.
        Returns:
        the number of rows in the group.
      • indexOf

        public int indexOf​(T bean)
        Get thd index of a group in the list of groups.
        Parameters:
        bean - the group
      • indexOf

        public int indexOf​(java.util.function.Predicate<T> condition)
      • rowIndexOf

        public int rowIndexOf​(T bean)
        Get the row index of the header of a group.
        Parameters:
        bean - the group
      • getLeadRowForGroup

        public int getLeadRowForGroup​(int beanIndex)
        Specified by:
        getLeadRowForGroup in interface MixedRowTableModel
        Parameters:
        beanIndex - the index of the group.
        Returns:
        the index of the first row of the group.
      • getRowCount

        public int getRowCount()
        Specified by:
        getRowCount in interface javax.swing.table.TableModel
      • getCellClass

        public java.lang.Class<?> getCellClass​(int rowIndex,
                                               int columnIndex)
        Specified by:
        getCellClass in interface MixedRowTableModel
        Parameters:
        rowIndex - the index of the row.
        columnIndex - the index of the column.
        Returns:
        the Class of the cell value.
      • getColumnClass

        public java.lang.Class<?> getColumnClass​(int columnIndex)
        Specified by:
        getColumnClass in interface javax.swing.table.TableModel
        Overrides:
        getColumnClass in class javax.swing.table.AbstractTableModel
      • getColumnClass

        public java.lang.Class<?> getColumnClass​(int typeIndex,
                                                 int columnIndex)
        Specified by:
        getColumnClass in interface MixedRowTableModel
        Parameters:
        typeIndex - the row type index.
        columnIndex - the column index.
        Returns:
        the Class of the column value.
      • getColumnName

        public java.lang.String getColumnName​(int columnIndex)
        Specified by:
        getColumnName in interface javax.swing.table.TableModel
        Overrides:
        getColumnName in class javax.swing.table.AbstractTableModel
      • getColumnName

        public java.lang.String getColumnName​(int typeIndex,
                                              int columnIndex)
        Specified by:
        getColumnName in interface MixedRowTableModel
        Parameters:
        typeIndex - the row type index.
        columnIndex - the column index.
        Returns:
        the header text for the column.
      • getColumnIdentifier

        public ColumnAdapter<?,​?> getColumnIdentifier​(int typeIndex,
                                                            int columnIndex)
        Specified by:
        getColumnIdentifier in interface MixedRowTableModel
        Parameters:
        typeIndex - the row type index.
        columnIndex - the column index.
        Returns:
        the TableColumn identifier of the column.
      • isSubRow

        public boolean isSubRow​(int rowIndex)
        Returns:
        true if the row is a detail or false if it is a header
      • getGroupNumber

        public int getGroupNumber​(int rowIndex)
        Specified by:
        getGroupNumber in interface MixedRowTableModel
        Parameters:
        rowIndex - the index of the row.
        Returns:
        the index of the group containing the row.
      • getSubRowIndex

        public int getSubRowIndex​(int rowIndex)
        Specified by:
        getSubRowIndex in interface MixedRowTableModel
        Parameters:
        rowIndex - the index of the row.
        Returns:
        the index of the row within its group.
      • getRowTypeIndex

        public int getRowTypeIndex​(int rowIndex)
        Specified by:
        getRowTypeIndex in interface MixedRowTableModel
        Parameters:
        rowIndex - index of the row.
        Returns:
        the type index of the row.
      • getDetailColumnAdapter

        protected ColumnAdapter<java.lang.Object,​java.lang.Object> getDetailColumnAdapter​(int typeIndex,
                                                                                                int columnIndex)
      • getValueAt

        public java.lang.Object getValueAt​(int rowIndex,
                                           int columnIndex)
        Specified by:
        getValueAt in interface javax.swing.table.TableModel
      • getDetailValueAt

        protected java.lang.Object getDetailValueAt​(java.lang.Object detail,
                                                    int typeIndex,
                                                    int columnIndex)
        Get the detail value for the specified detail type and column.
      • getValue

        public java.lang.Object getValue​(T bean,
                                         int columnIndex)
        Description copied from interface: BeanTableModel
        Get a column cell value for a bean.
        Specified by:
        getValue in interface BeanTableModel<T>
      • isCellEditable

        public boolean isCellEditable​(int rowIndex,
                                      int columnIndex)
        Delegates to the header/detail column adapters.
        Specified by:
        isCellEditable in interface javax.swing.table.TableModel
        Overrides:
        isCellEditable in class javax.swing.table.AbstractTableModel
        Returns:
        the result of ColumnAdapter.isEditable(Object)
      • getCursor

        public java.awt.Cursor getCursor​(java.awt.event.MouseEvent event,
                                         javax.swing.JTable table,
                                         int rowIndex,
                                         int columnIndex)
        Description copied from interface: BeanTableModel
        Get the mouse cursor to display for a cell.
        Specified by:
        getCursor in interface BeanTableModel<T>
        rowIndex - the row index of the cell
        columnIndex - the column index of the cell
        Returns:
        the mouse cursor to use for the cell or null to use the default cursor.
      • handleClick

        public void handleClick​(java.awt.event.MouseEvent event,
                                javax.swing.JTable table,
                                int rowIndex,
                                int columnIndex)
        Description copied from interface: BeanTableModel
        Handle a mouse click on a cell.
        Specified by:
        handleClick in interface BeanTableModel<T>
        Parameters:
        event - the click event
        rowIndex - the row containing the cell
        columnIndex - the column index of the cell
      • setCellValue

        protected void setCellValue​(java.lang.Object value,
                                    int rowIndex,
                                    int columnIndex)
        Set a value on a header or detail.
        Parameters:
        value - the cell value
        rowIndex - the table row index
        columnIndex - the table column index