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.reflect.MethodInfo;
    19  import org.as2lib.env.reflect.ClassInfo;
    20  
    21  /**
    22   * {@code MethodAlgorithm} searches for all methods of a specific class.
    23   * 
    24   * <p>This class is mostly used internally. If you wanna obtain the methods of a
    25   * class you need its representing ClassInfo. You can then also use the
    26   * {@link ClassInfo#getMethods} method directly and do not have to make the detour
    27   * over this class. The {@link ClassInfo#getMethods} method is also easier to use
    28   * and offers some extra functionalities.
    29   *
    30   * <p>If you nevertheless want to use this class here is how it works.
    31   *
    32   * <code>
    33   *   var classInfo:ClassInfo = ClassInfo.forClass(MyClass);
    34   *   var methodAlgorithm:MethodAlgorithm = new MethodAlgorithm();
    35   *   var methods:Array = methodAlgorithm.execute(classInfo);
    36   * </code>
    37   *
    38   * <p>Refer to the {@link #execute} method for details on how to get data from the
    39   * methods array appropriately.
    40   * 
    41   * @author Simon Wacker
    42   */
    43  class org.as2lib.env.reflect.algorithm.MethodAlgorithm extends BasicClass {
    44  	
    45  	/** The temporary result. */
    46  	private var r:Array;
    47  	
    48  	/** The class to return methods for. */
    49  	private var i:ClassInfo;
    50  	
    51  	/** Determines whether the method is static or not. */
    52  	private var s:Boolean;
    53  	
    54  	/**
    55  	 * Constructs a new {@code MethodAlgorithm} instance.
    56  	 */
    57  	public function MethodAlgorithm(Void) {
    58  	}
    59  	
    60  	/**
    61  	 * Searches for all methods of the passed-in class {@code i}.
    62  	 * 
    63  	 * <p>The resulting array contains instances of type {@link MethodInfo}.
    64  	 * 
    65  	 * <p>{@code null} will be returned if:
    66  	 * <ul>
    67  	 *   <li>The passed-in class {@code i} is {@code null} or {@code undefined}.</li>
    68  	 *   <li>The {@code getType} method of the passed-in class returns {@code null}.</li>
    69  	 * </ul>
    70  	 *
    71  	 * <p>Only the passed in class will be searched through, no super classes.
    72  	 *
    73  	 * <p>The found methods are stored in the resulting array by index as well as by
    74  	 * name. This means you can obtain {@code MethodInfo} instances either by index:
    75  	 * <code>var myMethod:MethodInfo = myMethods[0];</code>
    76  	 *
    77  	 * <p>Or by name:
    78  	 * <code>var myMethod:MethodInfo = myMethods["myMethodName"];</code>
    79  	 * 
    80  	 * @param i the class info instance representing the class to search through
    81  	 * @return the found methods, an empty array or {@code null}
    82  	 */
    83  	public function execute(i:ClassInfo):Array {
    84  		if (i == null) return null;
    85  		var c:Function = i.getType();
    86  		if (!c) return null;
    87  		this.i = i;
    88  		this.r = new Array();
    89  		
    90  		this.s = true;
    91  		_global.ASSetPropFlags(c, null, 0, true);
    92  		_global.ASSetPropFlags(c, ["__proto__", "constructor", "__constructor__", "prototype"], 1, true);
    93  		search(c);
    94  		
    95  		this.s = false;
    96  		var p:Object = c.prototype;
    97  		_global.ASSetPropFlags(p, null, 0, true);
    98  		_global.ASSetPropFlags(p, ["__proto__", "constructor", "__constructor__", "prototype"], 1, true);
    99  		search(p);
   100  		
   101  		// ASSetPropFlags must be restored because unexpected behaviors get caused otherwise
   102  		_global.ASSetPropFlags(c, null, 1, true);
   103  		_global.ASSetPropFlags(p, null, 1, true);
   104  		
   105  		return r;
   106  	}
   107  	
   108  	private function search(t):Void {
   109  		var k:String;
   110  		for (k in t) {
   111  			if (typeof(t[k]) == "function"
   112  					&& k.indexOf("__get__") < 0
   113  					&& k.indexOf("__set__") < 0) {
   114  				r[r.length] = new MethodInfo(k, i, s);
   115  				r[k] = r[r.length-1];
   116  			}
   117  		}
   118  	}
   119  	
   120  }