Interface AsyncDataLink<DataType>

Type Parameters:
DataType - the type of the data to be accessed. This type is strongly recommended to be immutable or effectively immutable.
All Known Implementing Classes:
AsyncChannelLink

public interface AsyncDataLink<DataType>
Defines a link to asynchronously access a specific data.

Instances of AsyncDataLink usually only need to store the input needed to find the actual data. For example: A AsyncDataLink intended to load a particular file, needs to store the path to the file only. And later load the content of the file when requested to do so.

The link to the data is intended to be permanent, so users should not hope that the underlying data will change. Note however, that sometimes it is impossible to the implementation to guarantee that it will provide the same data always when requested.

To combine AsyncDataLink instances see the useful utility methods in AsyncLinks.

Providing the data

When the user of this interface needs the data referenced by the AsyncDataLink, it needs to invoke the getData method and provide a listener to which the data will be forwarded when ready. The data need to forwarded by calling the onDataArrive method of the listener passing the data as an argument.

The data is intended to be provided iteratively with each progress providing a more accurate or simply a super set of the previously provided data. Providing possibly incomplete data however is optional and implementations may only provide the final complete data. However providing the final data is mandatory (unless when providing the data is canceled). The intention of this definition is that when a new data is forwarded to the listener, previously provided datas can be safely ignored and be discarded.

It is important to note that the datas must be provided one after another and must never be forwarded concurrently to the same listener. This is because listeners are not required to be thread-safe.

As an example when a AsyncDataLink implementation loads an image based on a file path it can iteratively forward an incomplete image until all the pixels of the image was loaded. Once the image has been loaded: the final complete image must be forwarded to the listener.

The data retrieval process can be canceled when the requested data is no longer needed. Cancellation requests are detected through the passed CancellationToken. Note that implementation may ignore cancellation attempts but good implementations should at least make a best attempt to stop retrieving the requested data.

Finish providing data

Once the data has been completely loaded (or failed to be loaded due to some unexpected error), the listener must be notified by calling the onDoneReceive method of the listener. The report can contain an exception as well to describe the failure which may have occurred. Note that once the client requested the data to be loaded, it is mandatory for every AsyncDataListener implementation to sooner or later call the onDoneReceive method.

Controlling the data currently being loaded

The clients can control how the data is to be loaded by the returned AsyncDataController object and also query the current progress of the loading process. Controlling the loading process is done by sending an object through the controlData method of the returned AsyncDataController. How and what can be controlled is completely implementation dependant but it most not affect the final data to be forwarded to the listener. It may affect the time needed to provide the final data but not the actual result. Note that due to some sources being unreliable, this may not be achievable but a best effort must be done to adhere to this contract. Controlling the data is merely intended to be used to affect intermediate datas.

The second generic feature of the AsyncDataController is that it can be used to retrieve the current status of the loading process. The most important property of this status is the estimated progress of loading process. Implementations however are recommended to provide other valuable information about the progress.

String representation of data links and queries

Since AsyncDataLink and AsyncDataQuery instances can be attached in a convoluted way, it can be very helpful if the toString() method returns a human readable string describing what the AsyncDataLink will do. The string representation is not intended to be parsed or even be parsable it is only intended to contain helpful information when debugging an application. To be consistent with the string representation provided by implementations in JTrim, the following guidelines should be used:
  • The representation should be multi-lined each line describing a single action.
  • The representation should be readable from top to bottom describing the consecutive actions.
  • When an AsyncDataLink or AsyncDataQuery wraps another query, the string representation of the subquery or sublink should be indented. The indentations should be done using the appendIndented methods of the AsyncFormatHelper class.
  • When working with arrays or collections it is recommended to add the content as an indented multi-line string with each element in a separate line. The AsyncFormatHelper contains methods to format them so.
  • The efficiency is not an issue because the string representation is intended to be used for debugging only.
  • The methods in AsyncFormatHelper should be used whenever possible for better consistency.

Thread safety

Implementations of this interface are required to be safe to use by multiple threads concurrently.

Synchronization transparency

Implementations of this interface are not required to be synchronization transparent. Note however that the getData method must return reasonably fast, must never do expensive tasks synchronously and especially not depend on some external resources.
See Also:
  • Method Details

    • getData

      AsyncDataController getData(CancellationToken cancelToken, AsyncDataListener<? super DataType> dataListener)
      Starts retrieving the data which is linked to this AsyncDataLink. The data will be forwarded to the specified listener usually asynchronously on a separate thread. Note however that this method may also forward the data synchronously on the current thread to the listener if it is readily available and does not need some expensive operation to load.

      Once this method has been called successfully, the onDoneReceive method of the listener must be called eventually regardless what happens. Failing to call this method is a serious failure of the AsyncDataLink implementation.

      Parameters:
      cancelToken - the CancellationToken signaling if the data retrieval process need to be canceled. Implementations may ignore cancellation requests but they should cancel the data retrieval and call the onDoneReceive method of the listener, signaling that the data retrieval cannot be completed due to cancellation. This argument cannot be null.
      dataListener - the listener to which the data is to be forwarded. This argument cannot be null.
      Returns:
      the AsyncDataController which can be used to control the way it is being loaded and request the progress of the data retrieving process. This method must never return null.
      Throws:
      NullPointerException - thrown if the specified listener or the CancellationToken is null