org.jdesktop.jdnc
Class DataLoader

java.lang.Object
  extended by org.jdesktop.jdnc.DataLoader
All Implemented Interfaces:
MessageSource, ProgressSource
Direct Known Subclasses:
TableModelExtTextLoader

public abstract class DataLoader
extends java.lang.Object
implements ProgressSource, MessageSource

Base class for implementing objects which asynchronously load data from an input stream into a model, ensuring that the potentially lengthy operation does not block the user-interface.

Swing requires that all operations which directly affect the user-interface component hierarchy execute on a single thread, the event dispatch thread ( Swing's single-threaded GUI rule). Because of this, the task of streaming data (potentially over the network) should not be performed on the event dispatch thread because it would cause the user-interface to freeze and become unresponsive. And yet, while the reading of the data should be off-loaded to a separate thread, it is desirable to incrementally load portions of that data into the model as it's read so that the user can see more immediate results than if he/she had to wait for the entire data stream to be read before seeing any data at all.

This class implements all the required thread and object synchronization to support this asynchronous, incremental load operation. It does this by splitting the operation into three distinct steps:

  1. read-meta-data: obtain any available meta-data from the stream which may provide structural and type information about the data. Meta-data is typically encoded in the beginning of the stream and is format-dependent. This should be called only from the event dispatch thread since it will modify properties on the model and possibly generate events which affect user-interface components.
  2. read-data: reading the data from the input-stream and loading it into a Java data structure which is not connected to the data model. This step is typically the most time consuming, hence it is performed in its own "reader" thread which is created by the startLoading method.
  3. load-data: taking the contents of the disconnected data structure and adding it to the data model. This step must be performed on the event dispatch thread because it has the potential to generate events which affect the user-interface components.
A concrete subclass should implement the 3 methods corresponding to these steps:

     public void loadMetaData(Object model, InputStream is)
     public void readData(Object model, InputStream is)
     public void loadData(Object model)
 

An application using a DataLoader instance may only invoke initializeMetaData and startLoading directly. startLoading will cause readData and loadData to invoked during the load operation.

Version:
1.0
Author:
Amy Fowler

Field Summary
static java.lang.String READER_PRIORITY_KEY
           
 
Constructor Summary
protected DataLoader()
           
 
Method Summary
 void addMessageListener(MessageListener l)
          Adds the specified message listener to this data loader.
 void addProgressListener(ProgressListener l)
          Adds the specified progress listener to this data loader.
protected  void fireException(java.lang.Throwable t)
           
protected  void fireMessage(java.lang.String message)
           
protected  void fireProgressEnded()
          Fires event indicating that the load operation has completed
protected  void fireProgressIncremented(int progress)
          Fires event indicating that an increment of progress has occured.
protected  void fireProgressStarted(int minimum, int maximum)
          Fires event indicating that the load operation has started.
 MessageListener[] getMessageListeners()
          Returns an array of listeners.
 ProgressListener[] getProgressListeners()
          Returns an array of listeners.
protected  int getReaderThreadPriority()
           
protected abstract  void loadData(java.lang.Object model)
          Invoked internally once the readData method calls scheduleLoad to schedule the loading of an increment of data to the model.
abstract  void loadMetaData(java.lang.Object model, java.io.InputStream is)
          Initializes the model with any meta-data available in the input stream.
protected abstract  void readData(java.io.InputStream is)
          Invoked by the startLoading method.
 void removeMessageListener(MessageListener l)
          Removes the specified message listener from this data loader.
 void removeProgressListener(ProgressListener l)
          Removes the specified progress listener from this data loader.
protected  void scheduleLoad()
          Invoked by the readData method from the "reader" thread to schedule a subsequent call to loadData on the event dispatch thread.
 void startLoading(java.lang.Object model, java.io.InputStream is)
          Starts the asynchronous load operation by spinning up a separate thread that will read the data from the input stream.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

READER_PRIORITY_KEY

public static final java.lang.String READER_PRIORITY_KEY
See Also:
Constant Field Values
Constructor Detail

DataLoader

protected DataLoader()
Method Detail

addProgressListener

public void addProgressListener(ProgressListener l)
Adds the specified progress listener to this data loader.

Specified by:
addProgressListener in interface ProgressSource
Parameters:
l - progress listener to be notified as data is loaded or errors occur

removeProgressListener

public void removeProgressListener(ProgressListener l)
Removes the specified progress listener from this data loader.

Specified by:
removeProgressListener in interface ProgressSource
Parameters:
l - progress listener to be notified as data is loaded or errors occur

getProgressListeners

public ProgressListener[] getProgressListeners()
Description copied from interface: ProgressSource
Returns an array of listeners.

Specified by:
getProgressListeners in interface ProgressSource
Returns:
array containing all progress listeners registered on this data loader

addMessageListener

public void addMessageListener(MessageListener l)
Adds the specified message listener to this data loader.

Specified by:
addMessageListener in interface MessageSource
Parameters:
l - message listener to be notified as data is loaded or errors occur

removeMessageListener

public void removeMessageListener(MessageListener l)
Removes the specified message listener from this data loader.

Specified by:
removeMessageListener in interface MessageSource
Parameters:
l - message listener to be notified as data is loaded or errors occur

getMessageListeners

public MessageListener[] getMessageListeners()
Description copied from interface: MessageSource
Returns an array of listeners.

Specified by:
getMessageListeners in interface MessageSource
Returns:
array containing all message listeners registered on this data loader

loadMetaData

public abstract void loadMetaData(java.lang.Object model,
                                  java.io.InputStream is)
                           throws java.io.IOException
Initializes the model with any meta-data available in the input stream. The amount of meta-data available from the input stream is format-dependent. This method is synchronous and may be invoked from the event dispatch thread.

Parameters:
model - the data model being loaded from the input stream
is - the input stream containing the meta-data
Throws:
java.io.IOException

startLoading

public void startLoading(java.lang.Object model,
                         java.io.InputStream is)
Starts the asynchronous load operation by spinning up a separate thread that will read the data from the input stream. This method will return immediately. Prior to calling this method, a MessageListener should be registered to be notified as data is loaded or errors occur. If the data model being loaded requires meta-data to describe its structure (such as the number of columns in a tabular data row), then that meta-data must be initialized before startLoading is called and must not be modified while the load operation executes, otherwise synchronization errors will occur.

Parameters:
model - the data model being loaded from the input stream
is - the input stream containing the data
See Also:
addProgressListener(org.jdesktop.swingx.event.ProgressListener)

getReaderThreadPriority

protected int getReaderThreadPriority()

readData

protected abstract void readData(java.io.InputStream is)
                          throws java.io.IOException,
                                 ConversionException
Invoked by the startLoading method. This method will be called on a separate "reader" thread. Subclasses must implement this method to read the data from the stream and place it in a data structure which is disconnected from the data model. When increments of data are ready to be loaded into the model, this method should invoke scheduleLoad, which will cause loadData to be called on the event dispatch thread, where the model may be safely updated. Progress events must not be fired from this method.

Parameters:
is - the input stream containing the data
Throws:
java.io.IOException - if errors occur while reading data from the input stream
ConversionException - if errors occur while converting data values from string to object
See Also:
scheduleLoad()

loadData

protected abstract void loadData(java.lang.Object model)
Invoked internally once the readData method calls scheduleLoad to schedule the loading of an increment of data to the model. This method is called on the event dispatch thread, therefore it is safe to mutate the model from this method. Subclasses must implement this method to load the current contents of the disconnected data structure into the data model. Note that because there is an unpredictable delay between the time scheduleLoad is called from the "reader" thread and loadData executes on the event dispatch thread, there may be more data available for loading than was available when scheduleLoad was invoked. All available data should be loaded from this method.

This method should fire an appropriate progress event to notify progress listeners when:

Parameters:
model - the data model being loaded from the input stream
See Also:
fireProgressStarted(int, int), fireProgressEnded(), fireException(java.lang.Throwable)

scheduleLoad

protected void scheduleLoad()
Invoked by the readData method from the "reader" thread to schedule a subsequent call to loadData on the event dispatch thread. If readData invokes scheduleLoad multiple times before loadData has the opportunity to execute on the event dispatch thread, those requests will be collapsed, resulting in only a single call to loadData.

See Also:
readData(java.io.InputStream), loadData(java.lang.Object)

fireProgressStarted

protected void fireProgressStarted(int minimum,
                                   int maximum)
Fires event indicating that the load operation has started. For a determinite progress operation, the minimum value should be less than the maximum value. For inderminate operations, set minimum equal to maximum.

Parameters:
minimum - the minimum value of the progress operation
maximum - the maximum value of the progress operation

fireProgressIncremented

protected void fireProgressIncremented(int progress)
Fires event indicating that an increment of progress has occured.

Parameters:
progress - total value of the progress operation. This value should be between the minimum and maximum values

fireProgressEnded

protected void fireProgressEnded()
Fires event indicating that the load operation has completed


fireException

protected void fireException(java.lang.Throwable t)

fireMessage

protected void fireMessage(java.lang.String message)


Copyright © 2005 Sun Microsystems All Rights Reserved.