org.knime.core.node.tableview
Class TableContentModel

java.lang.Object
  extended by javax.swing.table.AbstractTableModel
      extended by org.knime.core.node.tableview.TableContentModel
All Implemented Interfaces:
Serializable, EventListener, TableModel, HiLiteListener, TableContentInterface

public class TableContentModel
extends AbstractTableModel
implements HiLiteListener, TableContentInterface

Proprietary implementation of a model for a table view. Input of the model is a DataTable that is to be displayed in the table view.

This class uses a ring buffer to cache the rows being displayed. As new rows are read from the DataTable (using the the table's RowIterator) they are added to the ring buffer (and "old" rows are deleted). Each time a row is requested that resides before the cursor of the current iterator and is not in the cache (default size: 500), the cache is cleared and a new iterator is instantiated. Thus, this class will have some performance problems when the user scrolls up in the table view. However, when scrolling down, the data flow is somewhat "fluent".

This class also supports hiliting of rows (even though it is a view property). We do store the hilite status of the rows in here as it complies nicely with the caching strategy.

Author:
Bernd Wiswedel, University of Konstanz
See Also:
DataTable, Serialized Form

Nested Class Summary
static class TableContentModel.TableContentFilter
          Possible hilite filter incarnations.
 
Field Summary
static int CACHE_SIZE
          Default size of the ring buffer (500).
static int CHUNK_SIZE
          Number of rows being read at a time (50).
static String PROPERTY_DATA
          Property name of the event when the data table has changed.
static String PROPERTY_HILITE
          Property name of the event when hilite handler changes.
 
Fields inherited from class javax.swing.table.AbstractTableModel
listenerList
 
Constructor Summary
TableContentModel()
          Creates a new TableContentModel with empty content.
TableContentModel(DataTable data)
          Creates a new TableContentModel displaying data.
TableContentModel(DataTable data, HiLiteHandler prop)
          Creates a new TableContentModel displaying data.
 
Method Summary
 void addPropertyChangeListener(PropertyChangeListener listener)
          Adds property change listener to this instance.
 void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
          Adds property change listener to this instance.
protected  void boundColumn(int columnIndex)
          Checks if given argument is in range and throws an exception if it is not.
protected  void boundRow(int rowIndex)
          Checks if given argument is in range and throws an exception if it is not.
 void cancelRowCountingInBackground()
          Cancels the potential row counter thread invoked by countRowsInBackground().
protected  void clearCache()
          Clears cache, instantiates new Iterator.
 void countRowsInBackground()
          Starts a new internal thread that will iterate over the table and count the rows in it.
 int getCacheSize()
          Get the size of the cache.
 int getChunkSize()
          Get the chunk size.
 ColorAttr getColorAttr(int row)
          Get the color information for a row.
 Class<DataCell> getColumnClass(int column)
          Returns DataCell.class.
 int getColumnCount()
          Get the column count.
 String getColumnName(int colIndex)
          Get the column header for some specific column index.
 DataTable getDataTable()
          Get reference to underlying DataTable as it was passed in the constructor or changed by successive calls of setDataTable(DataTable).
 DataTableSpec getDataTableSpec()
          Get the table spec of the current DataTable.
 HiLiteHandler getHiLiteHandler()
          Return a reference to the hilite handler currently being used.
protected  PropertyChangeSupport getPropertyChangeSupport()
          Get reference to PropertyChangeSupport to allow subclasses to fire customized events.
protected  DataRow getRow(int row)
          Gets a row with a specified index.
 int getRowCount()
          Get the number of rows in this model.
 RowKey getRowKey(int row)
          Get the row key for a given row index.
 TableContentModel.TableContentFilter getTableContentFilter()
           
 String getTableName()
          Get the name of the current data table (if any) or null.
 DataCell getValueAt(int row, int column)
          Get the DataCell at a specific location.
 boolean hasData()
          Is there valid data to show?
 boolean hasHiLiteHandler()
          Is there a HiLiteHandler connected?
 boolean hasListeners(String propertyName)
          Are there listeners registered to this class?
 void hiLite(KeyEvent e)
          Invoked when some item(s) were hilit.
 boolean isHiLit(int row)
          Is the Row row hilited? The row with the index will be cached (if it hasn't been in there) and the hilite status of the row is returned.
 boolean isRowCountFinal()
          Returns true if the iterator has traversed the whole DataTable at least once.
 void removePropertyChangeListener(PropertyChangeListener listener)
          Removes a listener from this instance.
 void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)
          Removes a listener from this instance.
protected  void requestHiLite(ListSelectionModel selModel)
          HiLites all rows that are selected according to the given selection model.
protected  void requestResetHiLite()
          Resets the hiliting of all keys by invoking the reset method in the HiLiteHandler.
protected  void requestUnHiLite(ListSelectionModel selModel)
          "Unhilites" all rows that are selected according to the given selection model.
protected  int setCacheSize(int size)
          Changes the size of the ring buffer so that size rows can be cached.
protected  int setChunkSize(int newSize)
          Set a new chunk size.
 void setDataTable(DataTable data)
          Sets new data for this table.
 void setHiLiteHandler(HiLiteHandler hiliter)
          Set a new HiLiteHandler.
(package private)  void setRowCount(int newCount, boolean isFinal)
          Used by the row counter thread to inform about new rows.
 void setTableContentFilter(TableContentModel.TableContentFilter newFilter)
          Set new filter instance.
 void showHiLitedOnly(boolean showOnlyHilite)
          Deprecated. This method has been replaced by setTableContentFilter(TableContentFilter).
 boolean showsHiLitedOnly()
          Deprecated. This method has been replaced by getTableContentFilter()
 void unHiLite(KeyEvent e)
          Invoked when some item(s) were unhilit.
 void unHiLiteAll(KeyEvent event)
          Invoked, when everything (all rows) are unhilit.
 
Methods inherited from class javax.swing.table.AbstractTableModel
addTableModelListener, findColumn, fireTableCellUpdated, fireTableChanged, fireTableDataChanged, fireTableRowsDeleted, fireTableRowsInserted, fireTableRowsUpdated, fireTableStructureChanged, getListeners, getTableModelListeners, isCellEditable, removeTableModelListener, setValueAt
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.knime.core.node.tableview.TableContentInterface
addTableModelListener, removeTableModelListener
 

Field Detail

PROPERTY_DATA

public static final String PROPERTY_DATA
Property name of the event when the data table has changed.

See Also:
Constant Field Values

PROPERTY_HILITE

public static final String PROPERTY_HILITE
Property name of the event when hilite handler changes.

See Also:
Constant Field Values

CACHE_SIZE

public static final int CACHE_SIZE
Default size of the ring buffer (500).

See Also:
Constant Field Values

CHUNK_SIZE

public static final int CHUNK_SIZE
Number of rows being read at a time (50). Once a "new" row is accessed, the system will use the DataTable's iterator to get CHUNK_SIZE new rows which are added to the cache. Suppose you have a table with more than 100 rows: Those are then accessed

See Also:
Constant Field Values
Constructor Detail

TableContentModel

public TableContentModel()
Creates a new TableContentModel with empty content. Call setDataTable(DataTable) to set a valid data table. No HiLiting is available.

See Also:
setDataTable(DataTable), setHiLiteHandler(HiLiteHandler)

TableContentModel

public TableContentModel(DataTable data)
Creates a new TableContentModel displaying data. No HiLiting is available.

Parameters:
data - the table to be displayed. May be null to indicate that there is no data available.

TableContentModel

public TableContentModel(DataTable data,
                         HiLiteHandler prop)
Creates a new TableContentModel displaying data. If prop is not null, its HiLiteHandler is used to do hilite synchronization.

Parameters:
data - the table to be displayed. May be null to indicate that there is no data available.
prop - the HiLiteHandler However, may also be null to disable any hiliting.
Method Detail

setDataTable

public void setDataTable(DataTable data)
Sets new data for this table. The argument may be null to indicate invalid data (nothing displayed).

Parameters:
data - the new data being displayed or null

countRowsInBackground

public void countRowsInBackground()
Starts a new internal thread that will iterate over the table and count the rows in it. Successive calls of this method are ignored. Also if the final row count is known (either by consecutive calls of this method or because the table is so small that the cache is filled with all rows) this method has no effect.
The row counting process can be aborted by calling cancelRowCountingInBackground().


cancelRowCountingInBackground

public void cancelRowCountingInBackground()
Cancels the potential row counter thread invoked by countRowsInBackground(). If this method has not been called yet, this method does nothing.


setHiLiteHandler

public void setHiLiteHandler(HiLiteHandler hiliter)
Set a new HiLiteHandler. If the argument is null hiliting is disabled.

Parameters:
hiliter - the new handler to use.

getHiLiteHandler

public HiLiteHandler getHiLiteHandler()
Return a reference to the hilite handler currently being used.

Returns:
the current HiLiteHandler or null if none is set

hasData

public final boolean hasData()
Is there valid data to show?

Returns:
true if underlying DataTable is not null

getTableName

public String getTableName()
Get the name of the current data table (if any) or null.

Returns:
The table name or null.

hasHiLiteHandler

public final boolean hasHiLiteHandler()
Is there a HiLiteHandler connected?

Returns:
true if global hiliting is possible

showHiLitedOnly

@Deprecated
public final void showHiLitedOnly(boolean showOnlyHilite)
Deprecated. This method has been replaced by setTableContentFilter(TableContentFilter).

Control behaviour to show only hilited rows.

Parameters:
showOnlyHilite - true Filter and display only rows whose hilite status is set.

showsHiLitedOnly

@Deprecated
public boolean showsHiLitedOnly()
Deprecated. This method has been replaced by getTableContentFilter()

Get status of filtering for hilited rows.

Returns:
true if only hilited rows are shown, false if all rows are shown.

setTableContentFilter

public final void setTableContentFilter(TableContentModel.TableContentFilter newFilter)
Set new filter instance. If changed, the table will be refreshed.

Parameters:
newFilter - The new filter to be applied.
Throws:
NullPointerException - If argument is null.

getTableContentFilter

public TableContentModel.TableContentFilter getTableContentFilter()
Returns:
the currently set filter.

getColumnCount

public int getColumnCount()
Get the column count.

Specified by:
getColumnCount in interface TableModel
Returns:
the number of columns in the underlying DataTable or 0 if hasData() returns false.

getRowCount

public int getRowCount()
Get the number of rows in this model. This number may be less than the actual row count in the underlying DataTable. (Note, the final size of a DataTable is not necessarily known in advance.) The row count is updated each time a new row is requested. The return value is: Keep in mind that this call may not return the same value for two successive calls as it is possible that new rows have been seen in the meantime. As new rows are seen an event is fired.

Specified by:
getRowCount in interface TableModel
Specified by:
getRowCount in interface TableContentInterface
Returns:
a lower bound for the number of rows in this model
See Also:
TableModel.getRowCount()

getValueAt

public DataCell getValueAt(int row,
                           int column)
Get the DataCell at a specific location. If the requested row is in the cache, it will be returned. Otherwise the ring buffer is updated (iterator pushed forward or reset) until the row is in the cache.

Specified by:
getValueAt in interface TableModel
Parameters:
row - the row index
column - the column index
Returns:
the DataCell in the underlying DataTable at position [row, column]
Throws:
IndexOutOfBoundsException - if either argument violates its range

getRowKey

public RowKey getRowKey(int row)
Get the row key for a given row index. The row key will be displayed in a separate (row header) table.

Specified by:
getRowKey in interface TableContentInterface
Parameters:
row - The row index.
Returns:
The key of that row.

getColumnName

public String getColumnName(int colIndex)
Get the column header for some specific column index. The final column name is generated by using the column header's DataCell toString() method.

Specified by:
getColumnName in interface TableModel
Overrides:
getColumnName in class AbstractTableModel
Parameters:
colIndex - the column's index
Returns:
header of column colIndex
Throws:
IndexOutOfBoundsException - if colIndex out of range
See Also:
AbstractTableModel.getColumnName(int), DataColumnSpec.getName()

getColumnClass

public Class<DataCell> getColumnClass(int column)
Returns DataCell.class.

Specified by:
getColumnClass in interface TableModel
Overrides:
getColumnClass in class AbstractTableModel

getDataTable

public final DataTable getDataTable()
Get reference to underlying DataTable as it was passed in the constructor or changed by successive calls of setDataTable(DataTable).

Returns:
reference to table or null if hasData() returns false
See Also:
TableContentModel(DataTable)

getDataTableSpec

public DataTableSpec getDataTableSpec()
Get the table spec of the current DataTable. It returns null if the model is currently not having a table.

Returns:
The spec of the DataTable.

isRowCountFinal

public boolean isRowCountFinal()
Returns true if the iterator has traversed the whole DataTable at least once. The value returned by getRowCount() is therefore final. It returns false if the value can still increase.

Note: The row count may not increase even if isRowCountFinal() returns false. This unlikely case occurs when - by chance - getRowCount() + 1 is indeed the final row count. See the getRowCount() method for further details.

Returns:
if there are no more unknown rows

setCacheSize

protected final int setCacheSize(int size)
Changes the size of the ring buffer so that size rows can be cached. This method will clear the current cache. The cache should have at least a size so that all rows that are displayed at a time can be buffered (however, no further checking is carried out).

If size is less than twice the chunk size, i.e.

size < 2*getChunkSize()
, it will be set to it. So when a "new" row is requested, at least getChunkSize() rows after (including that row) and before the new row will be also in the cache.

Parameters:
size - size of the new cache.
Returns:
the new cache size (may differ from size, see above)
Throws:
IllegalArgumentException - if size <= 0.

getCacheSize

public final int getCacheSize()
Get the size of the cache.

Returns:
number of rows that fit in cache
See Also:
CACHE_SIZE

setChunkSize

protected final int setChunkSize(int newSize)
Set a new chunk size. This value is defaulted to CHUNK_SIZE on start-up. The new value can be at most getCacheSize()/2. If it is bigger, it's value is reduced to getCacheSize()/2.

Parameters:
newSize - the new value
Returns:
the new chunk size (may differ from passed argument, see above)
Throws:
IllegalArgumentException - if newSize is <= 0.
See Also:
getCacheSize()

getChunkSize

public final int getChunkSize()
Get the chunk size.

Returns:
The current value of a chunk being read (default: CHUNK_SIZE.

isHiLit

public boolean isHiLit(int row)
Is the Row row hilited? The row with the index will be cached (if it hasn't been in there) and the hilite status of the row is returned. This method may change the current cache content since it ensures row is in the cache.

Specified by:
isHiLit in interface TableContentInterface
Parameters:
row - The row index of interest
Returns:
true If that index is currently hilited

getColorAttr

public ColorAttr getColorAttr(int row)
Get the color information for a row.

Specified by:
getColorAttr in interface TableContentInterface
Parameters:
row - The row of interest
Returns:
The color information for that row

requestHiLite

protected void requestHiLite(ListSelectionModel selModel)
HiLites all rows that are selected according to the given selection model. This method does nothing if no handler is connected.

Parameters:
selModel - To get selection status from
Throws:
NullPointerException - if selModel is null

requestUnHiLite

protected void requestUnHiLite(ListSelectionModel selModel)
"Unhilites" all rows that are selected according to the given selection model. This method does nothing if no handler is connected.

Parameters:
selModel - To get selection status from
Throws:
NullPointerException - if selModel is null

requestResetHiLite

protected void requestResetHiLite()
Resets the hiliting of all keys by invoking the reset method in the HiLiteHandler. This method does nothing if no handler is connected.

See Also:
HiLiteHandler.fireClearHiLiteEvent()

hiLite

public void hiLite(KeyEvent e)
Invoked when some item(s) were hilit.

Specified by:
hiLite in interface HiLiteListener
Parameters:
e - contains a list of row keys that were hilit

unHiLite

public void unHiLite(KeyEvent e)
Invoked when some item(s) were unhilit.

Specified by:
unHiLite in interface HiLiteListener
Parameters:
e - contains a list of row keys that were unhilit

unHiLiteAll

public void unHiLiteAll(KeyEvent event)
Invoked, when everything (all rows) are unhilit.

Specified by:
unHiLiteAll in interface HiLiteListener
Parameters:
event - contains a list of row key that were unhilit

getRow

protected DataRow getRow(int row)
Gets a row with a specified index. Either the row is in the cache (just take it) or the row must be got from the DataTable (uses iterator and puts row into cache).

Parameters:
row - row index of interest
Returns:
the row at a specific position
Throws:
IndexOutOfBoundsException - if row violates its range

clearCache

protected void clearCache()
Clears cache, instantiates new Iterator.


setRowCount

void setRowCount(int newCount,
                 boolean isFinal)
Used by the row counter thread to inform about new rows. An event will be fired to inform registered listeners.

Parameters:
newCount - the new row count
isFinal - if there are possibly more rows to count

addPropertyChangeListener

public void addPropertyChangeListener(PropertyChangeListener listener)
Adds property change listener to this instance.

Parameters:
listener - A new listener to register.
See Also:
#addPropertyChangeListener(PropertyChangeListener)

addPropertyChangeListener

public void addPropertyChangeListener(String propertyName,
                                      PropertyChangeListener listener)
Adds property change listener to this instance.

Parameters:
propertyName - only events with that id are fired to the listener.
listener - the listener to register here
See Also:
#addPropertyChangeListener(String, PropertyChangeListener)

hasListeners

public boolean hasListeners(String propertyName)
Are there listeners registered to this class?

Parameters:
propertyName - property name of interest
Returns:
true if there are known listeners, false otherwise
See Also:
PropertyChangeSupport.hasListeners(java.lang.String)

removePropertyChangeListener

public void removePropertyChangeListener(PropertyChangeListener listener)
Removes a listener from this instance.

Parameters:
listener - listener to be removed
See Also:
#removePropertyChangeListener(PropertyChangeListener)

removePropertyChangeListener

public void removePropertyChangeListener(String propertyName,
                                         PropertyChangeListener listener)
Removes a listener from this instance.

Parameters:
propertyName - only if it listens to this property id
listener - listener to be removed
See Also:
#removePropertyChangeListener(String, PropertyChangeListener)

getPropertyChangeSupport

protected final PropertyChangeSupport getPropertyChangeSupport()
Get reference to PropertyChangeSupport to allow subclasses to fire customized events.

Returns:
reference to change support object, never null.

boundRow

protected final void boundRow(int rowIndex)
Checks if given argument is in range and throws an exception if it is not.

Parameters:
rowIndex - row index to check
Throws:
IndexOutOfBoundsException - if argument violates range

boundColumn

protected final void boundColumn(int columnIndex)
Checks if given argument is in range and throws an exception if it is not.

Parameters:
columnIndex - column index to check
Throws:
IndexOutOfBoundsException - if argument violates range


Copyright, 2003 - 2010. All rights reserved.
University of Konstanz, Germany.
Chair for Bioinformatics and Information Mining, Prof. Dr. Michael R. Berthold.
You may not modify, publish, transmit, transfer or sell, reproduce, create derivative works from, distribute, perform, display, or in any way exploit any of the content, in whole or in part, except as otherwise expressly permitted in writing by the copyright owner or as specified in the license file distributed with this product.