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.core.BasicClass;
    18  import org.as2lib.env.overload.Overload;
    19  import org.as2lib.env.except.IllegalArgumentException;
    20  import org.as2lib.aop.Advice;
    21  import org.as2lib.aop.Pointcut;
    22  import org.as2lib.app.exec.Call;
    23  import org.as2lib.aop.AopConfig;
    24  
    25  /**
    26   * {@code AbstractAspect} provides convenient method implmenetations and offers
    27   * functionalities to add advices in different manners.
    28   * 
    29   * @author Simon Wacker
    30   */
    31  class org.as2lib.aop.aspect.AbstractAspect extends BasicClass {
    32  	
    33  	/** All added advices. */
    34  	private var advices:Array;
    35  	
    36  	/**
    37  	 * Constructs a new {@code AbstractAspect} instance.
    38  	 */
    39  	private function AbstractAspect(Void) {
    40  		this.advices = new Array();
    41  	}
    42  	
    43  	/**
    44  	 * Returns all added advices.
    45  	 * 
    46  	 * <p>The returned advices are needed by weavers.
    47  	 * 
    48  	 * @return all added advices
    49  	 */
    50  	public function getAdvices(Void):Array {
    51  		return this.advices.concat();
    52  	}
    53  	
    54  	/**
    55  	 * @overload #addAdviceByAdvice
    56  	 * @overload #addAdviceByTypeAndStringAndMethod
    57  	 * @overload #addAdviceByTypeAndPointcutAndMethod
    58  	 */
    59  	private function addAdvice() {
    60  		var o:Overload = new Overload(this);
    61  		o.addHandler([Advice], addAdviceByAdvice);
    62  		o.addHandler([Number, String, Function], addAdviceByTypeAndStringAndMethod);
    63  		o.addHandler([Number, Pointcut, Function], addAdviceByTypeAndPointcutAndMethod);
    64  		return o.forward(arguments);
    65  	}
    66  	
    67  	/**
    68  	 * Adds the passed-in {@code advice}.
    69  	 * 
    70  	 * <p>No action will take place if {@code advice} is {@code null} or
    71  	 * {@code undefined}.
    72  	 *
    73  	 * @param advice the advice to add
    74  	 */
    75  	private function addAdviceByAdvice(advice:Advice):Void {
    76  		if (advice) {
    77  			this.advices.push(advice);
    78  		}
    79  	}
    80  	
    81  	/**
    82  	 * Adds a new advice of the given {@code type}, for the given {@code pointcut} and
    83  	 * with the given {@code method} that is executed if a join point captured by the
    84  	 * {@code pointcut} is reached.
    85  	 * 
    86  	 * <p>The advice is obtained by the {@code getAdvice} method of the advice factory
    87  	 * returned by {@link AopConfig#getDynamicAdviceFactory} method.
    88  	 *
    89  	 * @param type the type of the advice
    90  	 * @param pointcut the pointcut represented by a string that determines which join
    91  	 * points are captured
    92  	 * @param method the method that contains the actions to be executed at specific
    93  	 * join points captured by the {@code pointcut}
    94  	 * @throws IllegalArgumentException if argument {@code method} is {@code null} or
    95  	 * {@code undefined}
    96  	 */
    97  	private function addAdviceByTypeAndStringAndMethod(type:Number, pointcut:String, method:Function):Advice {
    98  		if (method == null) throw new IllegalArgumentException("Argument 'method' must not be 'null' nor 'undefined'.", this, arguments);
    99  		var callback:Call = new Call(this, method);
   100  		var result:Advice = AopConfig.getDynamicAdviceFactory().getAdvice(type, pointcut, callback);
   101  		addAdviceByAdvice(result);
   102  		return result;
   103  	}
   104  	
   105  	/**
   106  	 * Adds a new advice of the given {@code type}, for the given {@code pointcut} and
   107  	 * with the given {@code method} that is executed if a join point captured by the
   108  	 * {@code pointcut} is reached.
   109  	 *
   110  	 * @param type the type of the advice
   111  	 * @param pointcut the pointcut that determines which join points are captured
   112  	 * @param method the method that contains the actions to be executed at specific
   113  	 * join points captured by the {@code pointcut}
   114  	 * @throws IllegalArgumentException if argument {@code method} is {@code null} or
   115  	 * {@code undefined}
   116  	 */
   117  	private function addAdviceByTypeAndPointcutAndMethod(type:Number, pointcut:Pointcut, method:Function):Advice {
   118  		if (method == null) throw new IllegalArgumentException("Argument 'method' must not be 'null' nor 'undefined'.", this, arguments);
   119  		var callback:Call = new Call(this, method);
   120  		var result:Advice = AopConfig.getDynamicAdviceFactory().getAdvice(type, pointcut, callback);
   121  		addAdviceByAdvice(result);
   122  		return result;
   123  	}
   124  	
   125  }