1  /*
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   * 
     8   *      http://www.mozilla.org/MPL/MPL-1.1.html
     9   * 
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  import org.as2lib.env.except.IllegalArgumentException;
    18  import org.as2lib.env.event.EventExecutionException;
    19  import org.as2lib.env.event.SimpleEventListenerSource;
    20  import org.as2lib.env.event.multicaster.ConsumableEventMulticaster;
    21  
    22  /**
    23   * {@code SimpleConsumableEventMulticaster} multicasts an event to all added listeners with
    24   * custom arguments until the event is consumed.
    25   *
    26   * <p>Example:
    27   * <code>
    28   *   // creates a multicaster for the 'onError' event
    29   *   var multicaster:SimpleConsumableEventMulticaster = new SimpleConsumableEventMulticaster("onError");
    30   *   // adds listeners
    31   *   multicaster.addListener(new SimpleErrorListener());
    32   *   multicaster.addListener(new MyErrorListener());
    33   *   // executes the specified event on all listeners passing the given arguments
    34   *   multicaster.dispatch(myErrorCode, myException);
    35   * </code>
    36   *
    37   * <p>The event dispatch is stopped as soon as any of the above listeners returns
    38   * {@code true}. If for example the {@code SimpleErrorListener.onError} method
    39   * returns {@code true}, {@code MyErrorListener.onError} will not be executed
    40   * because the event is consumed.
    41   * 
    42   * @author Simon Wacker
    43   */
    44  class org.as2lib.env.event.multicaster.SimpleConsumableEventMulticaster extends SimpleEventListenerSource implements ConsumableEventMulticaster {
    45  	
    46  	/** The name of the event. */
    47  	private var eventName:String;
    48  	
    49  	/**
    50  	 * Constructs a new {@code SimpleConsumableEventMulticaster} instance.
    51  	 * 
    52  	 * @param eventName the name of the event to execute on listeners
    53  	 * @param listeners (optional) an array of listeners to populate this broadcaster
    54  	 * with
    55  	 * @throws IllegalArgumentException if passed-in {@code eventName} is {@code null},
    56  	 * {@code undefined} or an empty string
    57  	 */
    58  	public function SimpleConsumableEventMulticaster(eventName:String, listeners:Array) {
    59  		if (!eventName) throw new IllegalArgumentException("Argument 'eventName' [" + eventName + "] must not be 'null' nor 'undefined'.", this, arguments);
    60  		this.eventName = eventName;
    61  		if (listeners) {
    62  			addAllListeners(listeners);
    63  		}
    64  	}
    65  	
    66  	/**
    67  	 * Returns the event name set on construction.
    68  	 *
    69  	 * @return the name of the event
    70  	 */
    71  	public function getEventName(Void):String {
    72  		return this.eventName;
    73  	}
    74  	
    75  	/**
    76  	 * Dispatches the event to all listeners passing the given arguments as parameters
    77  	 * to the listeners' event methods until a listener consumes the event by returning
    78  	 * {@code true}.
    79  	 * 
    80  	 * @param .. any number of arguments to pass to the listeners' event methods
    81  	 * @throws EventExecutionException if a listener's event method threw an exception
    82  	 */
    83  	public function dispatch():Void {
    84  		var i:Number = this.l.length;
    85  		if (i > 0) {
    86  			var k:Number;
    87  			try {
    88  				for (k = 0; k < i; k++) {
    89  					// explicit check whether the return value is true; returning any kind of object
    90  					// would otherwise also result in true if "== true" was omitted
    91  					if (this.l[k][eventName].apply(this.l[k], arguments) == true) {
    92  						return;
    93  					}
    94  				}
    95  			} catch (e) {
    96  				// "new EventExecutionException" without braces is not MTASC compatible because of the following method call to "initCause"
    97  				throw (new EventExecutionException("Unexpected exception was thrown during dispatch of event [" + this.eventName + "] on listener [" + this.l[k] + "] with arguments [" + arguments + "].", this, arguments)).initCause(e);
    98  			}
    99  		}
   100  	}
   101  	
   102  }