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.aop.Pointcut;
    19  import org.as2lib.aop.JoinPoint;
    20  
    21  /**
    22   * {@code KindedPointcut} represents any kinded pointcuts. These are for example
    23   * execution, set and get access pointcuts.
    24   * 
    25   * <p>Kinded pointcuts build upon a join point pattern and a specific join point type.
    26   * Pre-defined join point types are {@link AbstractJoinPoint#METHOD},
    27   * {@link AbstractJoinPoint#PROPERTY}, {@link AbstractJoinPoint#GET_PROPERTY},
    28   * {@link AbstractJoinPoint#SET_PROPERTY} and {@link AbstractJoinPoint#CONSTRUCTOR}.
    29   * You may combine several join point types with a bitwise or "|" to make this kinded
    30   * pointcut match all the combined join point types.
    31   * 
    32   * <p>The pattern may consist of wildcards. Using wildcards you can capture join points
    33   * based on specific characteristics like capture every setter method contained in every
    34   * class whose name starts with {@code "Abstract"} in the {@code org.as2lib.env} package
    35   * and every sub-package. Such a pattern would look something like this:
    36   * <code>org.as2lib.env..Abstract*.set*</code>
    37   * 
    38   * <p>You already see two wildcards there: '*' and '..'.
    39   * <ul>
    40   *   <li>'*' indicates any number of characters excluding the period.</li>
    41   *   <li>'..' indicates any number of charecters including all periods.</li>
    42   *   <li>'+' indicates all subclasses or subinterfaces of a given type.</li>
    43   *   <li>
    44   *     '!' negates the match; match all join points except the ones that match the
    45   *     pattern.
    46   *   </li>
    47   * </ul>
    48   * 
    49   * @author Simon Wacker
    50   * @see <a href="http://www.simonwacker.com/blog/archives/000057.php">Kinded Pointcuts</a>
    51   * @see <a href="http://www.simonwacker.com/blog/archives/000053.php">Wildcards</a>
    52   */
    53  class org.as2lib.aop.pointcut.KindedPointcut extends BasicClass implements Pointcut {
    54  	
    55  	/** The types of the matching join points. */
    56  	private var matchingJoinPointTypes:Number;
    57  	
    58  	/** The pattern that represents the join point. */
    59  	private var joinPointPattern:String;
    60  	
    61  	/**
    62  	 * Constructs a new {@code KindedPointcut} instance.
    63  	 *
    64  	 * <p>Depending on the join points {@code matches} method a pattern of value
    65  	 * {@code null} or {@code undefined} will cause the {@link #captures} method to
    66  	 * return {@code true} or {@code false}. Note that the join point implementations
    67  	 * provided by this framework return {@code true} for a {@code null} pattern.
    68  	 * 
    69  	 * <p>A matching join point type of value {@code null} or {@code undefined} is
    70  	 * interpreted as "any type of join point allowed".
    71  	 * 
    72  	 * <p>{@code matchingJoinPointTypes} can be either only one type or a bitwise or "|"
    73  	 * combination of several types. It is thus possible to make this kinded pointcut
    74  	 * match more than one join point type.
    75  	 * <code>AbstractJoinPoint.METHOD | AbstractJoinPoint.CONSTRUCTOR</code>
    76  	 * 
    77  	 * @param joinPointPattern the join point pattern
    78  	 * @param matchingJoinPointTypes the types of the join points that match this
    79  	 * pointcut
    80  	 */
    81  	public function KindedPointcut(joinPointPattern:String, matchingJoinPointTypes:Number) {
    82  		this.joinPointPattern = joinPointPattern;
    83  		this.matchingJoinPointTypes = matchingJoinPointTypes;
    84  	}
    85  	
    86  	/**
    87  	 * Checks whether the given {@code joinPoint} is captured by this pointcut. This is
    88  	 * normally the case if the join point is of the correct type and the pattern
    89  	 * matches the join point.
    90  	 * 
    91  	 * {@code false} will be returned if:
    92  	 * <ul>
    93  	 *   <li>The passed-in join point is {@code null} or {@code undefined}.</li>
    94  	 *   <li>The passed-in join point does not match the given join point pattern.</li>
    95  	 *   <li>The passed-in join point's type does not match the given one.</li>
    96  	 * </ul>
    97  	 *
    98  	 * @param joinPoint the join point to check whether it is captured by this pointcut
    99  	 * @return {@code true} if the given {@code joinPoint} is captured else {@code false}
   100  	 * @see JoinPoint#matches
   101  	 */
   102  	public function captures(joinPoint:JoinPoint):Boolean {
   103  		if (!joinPoint) return false;
   104  		if (this.matchingJoinPointTypes == null) {
   105  			return joinPoint.matches(this.joinPointPattern);
   106  		}
   107  		return ((this.matchingJoinPointTypes & joinPoint.getType()) > 0
   108  					&& joinPoint.matches(this.joinPointPattern));
   109  	}
   110  	
   111  }