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