package org.gudy.azureus2.ui.swt.progress;



/**
 * A simple listener interface used to pass a <code>ProgressReport</code> to a listener from a <code>ProgressReporter</code>
 * @author knguyen
 *
 */
public interface IProgressReporterListener
	extends IProgressReportConstants
{

	/**
	 * When an event is detected this callback method will be called so listeners can take appropriate action such as updating a UI element
	 * <p>
	 * Currently there are 2 return types recognized:
	 * <ul>
	 * <li><code>RETVAL_OK</code> - Indicates the given <code>ProgressReport</code> has been consumed successfully</li>
	 * <li><code>RETVAL_OK_TO_DISPOSE</code> - Indicates that this listener is no longer interested in any subsequent reports</li>
	 * </ul>
	 * </p>
	 * 
	 * The return value of <code>RETVAL_OK_TO_DISPOSE</code> is a hint to the caller that it is now
	 * safe to remove this listener from the caller's list of listeners.  This pattern allows the caller
	 * to perform clean up operations associated with this listener, and allows the listener to initiate
	 * its own removal from within an event loop.
	 * 
	 * <p> A typical life cycle of an event listener is create listener, register listener, then remove listener.
	 * To accomplish all three steps we would need a reference to the listeners at all time as can be seen in this sample: </p>
	 * 
	 * 
	 * <pre>
	 * ProgressReporter reporter = new ProgressReporter("I'm a reporter");
	 * 
	 * // Create a concrete listener since we need to remove it later for clean up
	 * IProgressReporterListener listener = new IProgressReporterListener() {
	 * 	public int report(ProgressReport progressReport) {
	 * 		// Do some work here
	 * 		return RETVAL_OK;
	 * 	}
	 * };
	 * 
	 * // Add the listener
	 * reporter.addListener(listener);
	 * 
	 * // Do some more work
	 * 
	 * // Then for clean up remove the listener
	 * if ([some condition] == true) {
	 * 	reporter.removeListener(listener);
	 * }
	 * 
	 * </pre>
	 * 
	 * 
	 * Sometime it is more convenient to remove a listener from within the call to .report() but a direct
	 * attempt at removal of this listener may result in modification conflict since most likely this method is being
	 * called from within an iterator loop which does not allow concurrent modifications.
	 * 
	 * To address this limitation we make use of the <code>RETVAL_OK_TO_DISPOSE</code> as a return code which will
	 * allow the caller to perform the clean up as in this modification of the example above:
	 * 
	 * <pre>
	 * ...
	 * 
	 * final IProgressReporterListener listener = new IProgressReporterListener() {
	 * 	public int report(ProgressReport progressReport) {
	 * 
	 * 		// Do some work here
	 * 
	 * 		// This would throw a ConcurrentModificationException
	 *		reporter.removeListener(listener); 
	 * 
	 * 		// This would work
	 * 		if ([some condition] == true) {
	 * 			return RETVAL_OK_TO_DISPOSE;
	 * 		}
	 * 
	 * 		return RETVAL_OK;
	 * 	}
	 * };
	 * </pre>
	 * 
	 * <p>If the decision to remove a listener is based on the information contained in the given <code>ProgressReport</code>
	 * we can implement a much simpler listener as an inner class like so:</p>
	 * <pre>
	 * 
	 * ProgressReporter reporter = new ProgressReporter("I'm a reporter");
	 * 
	 * // Creates an anonymous inner class using RETVAL_OK_TO_DISPOSE to initiate clean up  
	 * reporter.addListener(new IProgressReporterListener() {
	 * 	public int report(ProgressReport progressReport) {
	 * 
	 * 		// Do some work
	 * 
	 * 		if ([some condition] == true) {
	 * 			return RETVAL_OK_TO_DISPOSE;
	 * 		}
	 * 		return RETVAL_OK;
	 * 
	 * 	}}
	 * );
	 * 
	 * 
	 * </pre>
	 * 
	 * @param progressReport
	 * @return 
	 */
	public int report(IProgressReport progressReport);

}