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  
    19  /**
    20   * {@code ClassUtil} contains fundamental operations to efficiently and easily
    21   * work with any class. All methods here are supposed to be used with functions
    22   * treated as classes.
    23   * 
    24   * @author Martin Heidegger
    25   * @author Simon Wacker
    26   */
    27  class org.as2lib.util.ClassUtil extends BasicClass {
    28  	
    29  	/**
    30  	 * Checks if the passed-in {@code subClass} is extended by the passed-in
    31  	 * {@code superClass}.
    32  	 * 
    33  	 * @param subClass the class to check
    34  	 * @param superClass the class to match
    35  	 * @return {@code true} if {@code subClass} is a sub-class of {@code superClass}
    36  	 */
    37  	public static function isSubClassOf(subClass:Function, superClass:Function):Boolean {
    38  		var base:Object = subClass.prototype;
    39  		// A superclass has to be in the prototype chain
    40  		while(base !== undefined) {
    41  			base = base.__proto__;
    42  			if(base === superClass.prototype) {
    43  				return true;
    44  			}
    45  		}
    46  		return false;
    47  	}
    48  	
    49  	/**
    50  	 * Checks if the passed-in {@code clazz} implements the passed-in {@code
    51  	 * interfaze}.
    52  	 * 
    53  	 * @param clazz the class to check
    54  	 * @param interfaze the interface the {@code clazz} may implement
    55  	 * @return {@code true} if the passed-in {@code clazz} implements the passed-in
    56  	 * {@code interfaze} else {@code false}
    57  	 */
    58  	public static function isImplementationOf(clazz:Function, interfaze:Function):Boolean {
    59  		// A interface must not be in the prototype chain.
    60  		if (isSubClassOf(clazz, interfaze)) {
    61  			return false;
    62  		}
    63  		// If it's an interface then it must not be extended but the class has
    64  		// to be an instance of it
    65  		return (createCleanInstance(clazz) instanceof interfaze);
    66  	}
    67  	
    68  	/**
    69  	 * Creates a new instance of the passed-in {@code clazz} without invoking its 
    70  	 * constructor.
    71  	 * 
    72  	 * @param clazz the	class to create a new instance of
    73  	 * @return new instance of the passed-in class.
    74  	 * @author Martin Heidegger
    75  	 * @author Ralf Bokelberg (www.qlod.com)
    76  	 */
    77  	public static function createCleanInstance(clazz:Function):Object {
    78  		var result:Object = new Object();
    79  		result.__proto__ = clazz.prototype;
    80  		result.__constructor__ = clazz;
    81  		return result;
    82  	}
    83  	
    84  	/**
    85  	 * Creates a new instance of the passed-in {@code clazz} applying the
    86  	 * passed-in {@code args} to the constructor.
    87  	 * 
    88  	 * <p>This util is mostly made for MTASC compatibility because it doesn't
    89  	 * allow {@code new clazz()} for usual variables.
    90  	 * 
    91  	 * @param clazz Class to be instanciated
    92  	 * @param args Arguments to be applied to the constructor
    93  	 * @return new instance of the class
    94  	 */
    95  	public static function createInstance(clazz:Function, args:Array) {
    96  		if (!clazz) return null;
    97  		var result:Object = new Object();
    98  		result.__proto__ = clazz.prototype;
    99  		result.__constructor__ = clazz;
   100  		clazz.apply(result, args);
   101  		return result;
   102  	}
   103  }