Class ProgressReporter

java.lang.Object
com.biglybt.ui.swt.progress.ProgressReporter
All Implemented Interfaces:
IProgressReportConstants, IProgressReporter, Comparable

public class ProgressReporter extends Object implements IProgressReporter, IProgressReportConstants
A implementation of IProgressReporter

Any process wishing to participate in providing global progress indication can instantiate this class and simply use the available methods so set values or issue a command

When ever any state changes in this reporter a notification will be sent to the global reporting manager ProgressReportingManager followed by a notification to all registered listeners of this reporter

The listeners will be passed an immutable progress report ProgressReporter.ProgressReport which represents a snapshot of all the public properties contained in this reporter; inspecting the ProgressReport is the only way a listener can query the properties of this reporter. This pattern allows the ProgressReporter to continue and process requests by not having to thread lock all public methods. Additionally, the listeners are guaranteed a consistent snapshot of the reporter.

This reporter also has the capability to receive loop back commands from a listener for actions such like cancel() and retry(). These commands are enabled by calling setCancelAllowed(boolean) or setRetryAllowed(boolean). The listener only initiates these actions by sending a notification back to the owner of the reporter; it is up the to owner to perform the actual act of canceling or retrying.

A typical life cycle of the ProgresReporter as seen from an owner is as follows (an owner is defined as the process that created the reporter):

  • Create ProgressReporter
  • Set initial properties
  • Register a listener to the reporter to respond to loopback notifications (optional)
  • Update the reporter
  • Then optionally Dispose of the reporter [
    invalid reference
    ProgressReporter#dispose(Object)
    ]
  • .

    In addition to internal clean-ups, calling dispose(Object) will effectively remove the reporter from the history stack of the reporting manager and no more messages from this reporter will be processed.

Once a reporter is created and any property in the reporter is set the global reporting manager is notified; at which point any listener listening to the manager is forwarded this reporter. The manager listener may decide to display this reporter in a UI element, may register specific listeners to this reporter, may query its properties and take action, or can simply monitor it for such functions as logging.

This implementation is non-intrusive to the owner process and so provides existing processes the ability to participate in global progress indication without significant modification to the underlying processes.
  • Field Details

    • manager

      private ProgressReportingManager manager
    • ID

      private int ID
      An instance id for this reporter that is guaranteed to be unique within this same session
    • minimum

      private int minimum
    • maximum

      private int maximum
    • selection

      private int selection
    • percentage

      private int percentage
    • latestReportType

      private int latestReportType
    • isIndeterminate

      private boolean isIndeterminate
    • isDone

      private boolean isDone
    • isPercentageInUse

      private boolean isPercentageInUse
    • isCancelAllowed

      private boolean isCancelAllowed
    • isCanceled

      private boolean isCanceled
    • isRetryAllowed

      private boolean isRetryAllowed
    • isInErrorState

      private boolean isInErrorState
    • isDisposed

      private boolean isDisposed
    • title

      private String title
    • message

      private String message
    • messageHistory

      private CopyOnWriteList messageHistory
      Accumulates the detail messages in a List

      This is for when a listener starts listening to this reporter after it has started running; upon initialization the listener may query this list to get all messages sent up to that point.

    • detailMessage

      private String detailMessage
    • errorMessage

      private String errorMessage
    • name

      private String name
    • image

      private org.eclipse.swt.graphics.Image image
    • reporterType

      private String reporterType
    • latestProgressReport

      private IProgressReport latestProgressReport
    • reporterListeners

      private CopyOnWriteList reporterListeners
    • objectData

      private Object objectData
      An arbitrary object reference that can be used by the owner of the ProgressReporter and its listeners to share additional information should the current implementation be insufficient
    • messageHistoryLimit

      private int messageHistoryLimit
    • isActive

      private boolean isActive
      If any of the following states have been reached then the reporter is considered inactive:
      • isDisposed == true
      • isDone == true
      • isInErrorState == true
      • isCanceled == true
    • cancelCloses

      private boolean cancelCloses
  • Constructor Details

    • ProgressReporter

      protected ProgressReporter(ProgressReportingManager manager)
      Construct a ProgressReporter; the returned instance is initialized with the proper ID
    • ProgressReporter

      protected ProgressReporter(ProgressReportingManager _manager, String name)
      Construct a ProgressReporter with the given name; the returned instance would have been initialized with the proper ID
      Parameters:
      name -
  • Method Details

    • setReporterType

      public void setReporterType(String reporterType)
      Description copied from interface: IProgressReporter
      Sets the type of a reporter. This is a user defined property and no duplication check is ensured. This optional property can be used to identify particular types of reports so that report consumers have a way to ignore uninteresting report types
      Specified by:
      setReporterType in interface IProgressReporter
      Parameters:
      reporterType -
    • dispose

      public void dispose()
      Description copied from interface: IProgressReporter
      Disposes any resources or listeners that this reporter has references to or otherwise is responsible for

      Also removes it from the global ProgressReportingManager so that any subsequent event from this reporter is no longer forwarded

      Specified by:
      dispose in interface IProgressReporter
    • reInit

      private void reInit()
      Resets this reporter to its initial states such that values are reset to default

      An appropriate use for this is when a process is restarting or retrying; this allows an owning process to keep on using the same instance of this reporter without having to create and dispatch a new one

    • initMessageHistory

      private void initMessageHistory()
    • notifyListeners

      private void notifyListeners(IProgressReport report)
      Notifies registered listener that an event has occurred. Subsequently a listener may be removed if it returns the value of RETVAL_OK_TO_DISPOSE; this optimization is designed to prevent dangling/orphaned listeners, and also reduces the number of listeners to notify upon the next event
    • updateAndNotify

      private void updateAndNotify(int eventType)
      Updates and notifies listeners
      Parameters:
      REPORT_TYPE -
    • setSelection

      public void setSelection(int selection, String message)
      Description copied from interface: IProgressReporter
      Sets the selection to the progress reporter; this is used when a traditional min, max, selection is specified.

      NOTE: this selection value also synchronize the percentage value of this reporter

      Specified by:
      setSelection in interface IProgressReporter
      Parameters:
      selection -
      message -
    • setPercentage

      public void setPercentage(int percentage, String message)
      Description copied from interface: IProgressReporter
      Sets the percentage value to the progress reporter; this is used when a simple percentage is specified as opposed to setting min, max, and selection.

      NOTE: this percentage value also synchronize the selection value of this reporter

      Specified by:
      setPercentage in interface IProgressReporter
      Parameters:
      percentage - an integer from 0-100
      message - a textual message to display; null to leave the previous message untouched, empty String to clear any previous message
    • setIndeterminate

      public void setIndeterminate(boolean isIndeterminate)
      Description copied from interface: IProgressReporter
      Set this reporter into indeterminate mode; use this when an accurate ratio of amount of work done vs. total amount of work can not be calculated
      Specified by:
      setIndeterminate in interface IProgressReporter
      Parameters:
      isIndeterminate -
    • setDone

      public void setDone()
      Description copied from interface: IProgressReporter
      Indicates that the associated process is done
      Specified by:
      setDone in interface IProgressReporter
    • setMessage

      public void setMessage(String message)
      Description copied from interface: IProgressReporter
      Sets the current status message for this reporter; this is typically used to display a message at each incremental update
      Specified by:
      setMessage in interface IProgressReporter
      Parameters:
      message - a textual message
    • appendDetailMessage

      public void appendDetailMessage(String detailMessage)
      Description copied from interface: IProgressReporter
      Appends the detail message to this reporter. This is typically a more verbose message that is optionally displayed by the UI. This is an optional property so UI components displaying this can decide to show nothing for it (if it's null)or show the regular message in its place

      Additionally this is an appending message so that reporters can send smaller units of the message rather than having to store and send the entire (and ever increasing) messages for each update

      Specified by:
      appendDetailMessage in interface IProgressReporter
      Parameters:
      detailMessage -
    • setMinimum

      public void setMinimum(int min)
      Specified by:
      setMinimum in interface IProgressReporter
      Parameters:
      min - the min to set
    • setMaximum

      public void setMaximum(int max)
      Specified by:
      setMaximum in interface IProgressReporter
      Parameters:
      max - the max to set
    • cancel

      public void cancel()
      Description copied from interface: IProgressReporter
      Marks this reporter as canceled and notify any listeners about it

      NOTE: This is only a hint back to the processes listening to this reporter; it is up to that process to determine the correct course of action in response to this flag

      Specified by:
      cancel in interface IProgressReporter
    • retry

      public void retry()
      Description copied from interface: IProgressReporter
      Notifies listener that a retry is requested
      Specified by:
      retry in interface IProgressReporter
    • setCancelAllowed

      public void setCancelAllowed(boolean cancelAllowed)
      Description copied from interface: IProgressReporter
      Sets whether the process associated with this reporter is allowed to be canceled by the user. This serves as a hint to the progress manager handling this reporter. If set to true the manager may enable a UI component allowing the user to cancel the associated process if appropriate.

      The holder of this reporter can register a listener to receive the cancel event

      Specified by:
      setCancelAllowed in interface IProgressReporter
      Parameters:
      cancelAllowed - true to indicate that this process may solicit a REPORT_TYPE_CANCEL input from the user; default is false
      See Also:
    • setName

      public void setName(String name)
      Specified by:
      setName in interface IProgressReporter
      Parameters:
      name - a textual name to identify the process this reporter represents; need not be unique (should not be used as a lookup key), and may be null.
    • setTitle

      public void setTitle(String title)
      Description copied from interface: IProgressReporter
      Sets the title that may be used by a UI component. A typical usage would be for the title of a progress dialog
      Specified by:
      setTitle in interface IProgressReporter
      Parameters:
      title - the title to set
    • setImage

      public void setImage(org.eclipse.swt.graphics.Image image)
      Description copied from interface: IProgressReporter
      Sets the image corresponding to this reporter; this image may be used by the UI to decorate this reporter

      NOTE: Though not strictly required (nor enforced) the image should be 32X32 pixels with transparency. If not then cropping or enlargement may be applied as required by the particular UI

      Specified by:
      setImage in interface IProgressReporter
      Parameters:
      image - the image; may be null
    • setErrorMessage

      public void setErrorMessage(String errorMessage)
      Description copied from interface: IProgressReporter
      Sets an error message to this reporter; subsequently isInErrorState will be set to true
      Specified by:
      setErrorMessage in interface IProgressReporter
      Parameters:
      errorMessage -
      See Also:
      • invalid reference
        #reInit()
    • setRetryAllowed

      public void setRetryAllowed(boolean retryOnError)
      Description copied from interface: IProgressReporter
      This is a hint to any UI components displaying this reporter to determine if the user should be prompted to retry on error
      Specified by:
      setRetryAllowed in interface IProgressReporter
    • shouldIgnore

      private boolean shouldIgnore()
      A convenience method to return whether this reporter should ignore subsequent calls to its accessor methods. When a reporter has reached this state listeners usually make the assumption that there will be no more changes to any properties in this reporter. The use of this method is intended to provide a more consistent state for the reporter; without this check a listener may have reference to a reporter that is marked as done but then a subsequent message says it's at 50% completion. By cutting of the notification here we prevent such ambiguity from occurring for the listeners.

      If any of the following states have been reached then the reporter can ignore subsequent calls to its accessor methods:

      • isDisposed == true
      • isDone == true

      Returns:
    • getCancelCloses

      public boolean getCancelCloses()
      Specified by:
      getCancelCloses in interface IProgressReporter
    • setCancelCloses

      public void setCancelCloses(boolean b)
      Specified by:
      setCancelCloses in interface IProgressReporter
    • addToMessageHistory

      private void addToMessageHistory(String value, int type)
      Create and add an IMessage to the message history
      Parameters:
      value -
      type -
    • setObjectData

      public void setObjectData(Object objectData)
      Description copied from interface: IProgressReporter
      An arbitrary object reference that can be used to further identify the reporter. This object is also accessible to listeners of the reporter through ProgressReporter.ProgressReport.objectData so that it can be used to pass information to and from the listeners.
      Specified by:
      setObjectData in interface IProgressReporter
      Parameters:
      objectData - the objectData to set
    • getMessageHistory

      public IMessage[] getMessageHistory()
      Description copied from interface: IProgressReporter
      Returns an array of IMessage's that has been generated since the reporter was created
      Specified by:
      getMessageHistory in interface IProgressReporter
      Returns:
    • addListener

      public void addListener(IProgressReporterListener listener)
      Specified by:
      addListener in interface IProgressReporter
      Parameters:
      listener -
    • removeListener

      public void removeListener(IProgressReporterListener listener)
      Specified by:
      removeListener in interface IProgressReporter
      Parameters:
      listener -
    • compareTo

      public int compareTo(Object obj)
      Numerically compare by reporter ID's
      Specified by:
      compareTo in interface Comparable
    • equals

      public boolean equals(Object obj)
      Reporters are equal iif they have the same ID
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Hashcode and ID are the same
      Overrides:
      hashCode in class Object
    • getProgressReport

      public IProgressReport getProgressReport()
      Description copied from interface: IProgressReporter
      Returns an IProgressReport which is a snapshot of this reporter

      NOTE: Each call to this method creates a new snapshot therefore the correct usage pattern is:

      
              IProgressReport report = getProgressReport();
              if( report.isDone() == false ){
                      // Do something
              {
              else if( report.isCanceled() == false ){
                      // Do something else
              {
              ...
      
       
      It may be tempting to use the less verbose pattern by repeatedly calling this method directly such as:
      
              if( getProgressReport().isDone == false ){
                      // Do something
              {
              else if( getProgressReport().isCanceled == false ){
                      // Do something else
              {
      
       
      BUT this can produce inconsistent results since each successive call to getProgressReport() is returning a different snapshot.
      Specified by:
      getProgressReport in interface IProgressReporter
      Returns: