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.except.IllegalArgumentException; 19 import org.as2lib.env.reflect.ReflectUtil; 20 import org.as2lib.app.exec.ForEachExecutable; 21 import org.as2lib.util.AccessPermission; 22 23 /** 24 * {@code Call} enables another object to call a method in another scope without 25 * having to know the scope. 26 * 27 * <p>This enables you to pass a call to another object and let the object execute 28 * the call without losing its scope. You use the {@link #execute} method to do so. 29 * 30 * @author Simon Wacker 31 * @author Martin Heidegger 32 */ 33 class org.as2lib.app.exec.Call extends BasicClass implements ForEachExecutable { 34 35 /** The object to execute the method on. */ 36 private var object; 37 38 /** The method to execute on the object. */ 39 private var method:Function; 40 41 /** 42 * Constructs a new {@code Call} instance. 43 * 44 * @param object the object to execute the method on 45 * @param method the method to execute 46 * @throws IllegalArgumentException if either {@code object} or {@code method} is 47 * {@code null} or {@code undefined} 48 */ 49 public function Call(object, method:Function) { 50 if (object == null) { 51 throw new IllegalArgumentException("Required parameter 'object' is null or undefined.", this, arguments); 52 } 53 if (method == null) { 54 throw new IllegalArgumentException("Required parameter 'method' is null or undefined.", this, arguments); 55 } 56 this.object = object; 57 this.method = method; 58 } 59 60 /** 61 * Executes the method on the object passing the given {@code arguments} and returns the 62 * result of the execution. 63 * 64 * @return the result of the method execution 65 */ 66 public function execute() { 67 return method.apply(object, arguments); 68 } 69 70 /** 71 * Iterates over the passed-in {@code object} using the for..in loop and executes 72 * this call passing the found member, its name and the passed-in {@code object}. 73 * 74 * <p>Example: 75 * <code> 76 * class MyClass { 77 * 78 * private var a:String; 79 * private var b:String; 80 * private var c:String; 81 * 82 * public function MyClass() { 83 * a = "1"; 84 * b = "2"; 85 * c = "2"; 86 * } 87 * 88 * public function traceObject(value, name:String, inObject):Void { 89 * trace(name + ": " + value); 90 * } 91 * 92 * public function listAll() { 93 * new Call(this, traceObject).forEach(this); 94 * } 95 * } 96 * </code> 97 * 98 * <p>Note that only members visible to for..in loops cause the {@link #execute} 99 * method to be invoked. 100 * 101 * @param object the object to iterate over 102 */ 103 public function forEach(object):Array { 104 var i:String; 105 var result:Array = new Array(); 106 for (i in object) { 107 try { 108 result.push(execute(object[i], i, object)); 109 } catch(e) { 110 111 } 112 } 113 return result; 114 } 115 116 /** 117 * Returns the string representation of this call. 118 * 119 * @return the string representation of this call 120 */ 121 public function toString():String { 122 // TODO: Refactor the code and outsource it. 123 var result:String=""; 124 result += "[type " + ReflectUtil.getTypeNameForInstance(this) + " -> "; 125 AccessPermission.set(object, null, AccessPermission.ALLOW_ALL); 126 var methodName:String = ReflectUtil.getMethodName(method, object); 127 if (ReflectUtil.isMethodStatic(methodName, object)) { 128 result += "static "; 129 } 130 if (object == null) { 131 result += object.toString(); 132 } else { 133 var className:String = ReflectUtil.getTypeName(object); 134 if (className) { 135 result += className; 136 } else { 137 result += object.toString(); 138 } 139 } 140 result += "." + methodName; 141 result += "()]"; 142 return result; 143 } 144 145 }