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.overload.Overload; 19 import org.as2lib.env.reflect.ClassInfo; 20 import org.as2lib.env.reflect.PackageInfo; 21 import org.as2lib.env.reflect.Cache; 22 23 /** 24 * {@code SimpleCache} is a simple and performant implementation of the {@code Cache} 25 * interface. 26 * 27 * <p>The caching of classes and packages leads to better performance. You also 28 * must cache them because for example the parent of two classes residing in the 29 * same package should be the same {@code PackageInfo} instance. 30 * 31 * <p>This cache is mostly used internally. But you can also use it to add 32 * {@code ClassInfo} or {@code PackageInfo} instances directly so that they do not 33 * have to be searched for. This can improve the performance dramatically with 34 * classes or packages that are needed quite often. 35 * 36 * <p>This implementation sets a variable with name {@code "__as2lib__hashCode"} on 37 * every cached class and package to offer better performance. Do not delete this 38 * property. 39 * 40 * @author Simon Wacker 41 */ 42 class org.as2lib.env.reflect.SimpleCache extends BasicClass implements Cache { 43 44 /** The number of generated hash codes. */ 45 private static var hashCodeCounter:Number = 0; 46 47 /** The added infos. */ 48 private var cache:Array; 49 50 /** The root package. */ 51 private var root:PackageInfo; 52 53 /** 54 * Constructs a new {@code SimpleCache} instance. 55 * 56 * <p>The root/default package determines where the {@code ClassAlgorithm} and 57 * {@code PackageAlgorithm} classes start their search. 58 * 59 * @param root the root/default package of the package hierarchy 60 */ 61 public function SimpleCache(root:PackageInfo) { 62 this.root = root; 63 releaseAll(); 64 } 65 66 /** 67 * @overload #getClassByClass 68 * @overload #getClassByInstance 69 */ 70 public function getClass():ClassInfo { 71 var o:Overload = new Overload(this); 72 o.addHandler([Function], getClassByClass); 73 o.addHandler([Object], getClassByInstance); 74 return o.forward(arguments); 75 } 76 77 /** 78 * Returns the class info representing the passed-in {@code clazz}. 79 * 80 * <p>{@code null} will be returned if: 81 * <ul> 82 * <li>There is no corresponding {@code ClassInfo} instance cached.</li> 83 * <li>The passed-in {@code clazz} is {@code null} or {@code undefined}.</li> 84 * </ul> 85 * 86 * @param clazz the class to return the class info for 87 * @return the class info representing the passed-in {@code clazz} 88 */ 89 public function getClassByClass(clazz:Function):ClassInfo { 90 if (clazz === null || clazz === undefined) return null; 91 var p:Object = clazz.prototype; 92 var c:Number = p.__as2lib__hashCode; 93 if (c == undefined) return null; 94 if (c == p.__proto__.__as2lib__hashCode) { 95 return null; 96 } 97 return cache[c]; 98 } 99 100 /** 101 * Returns the class info representing the class the {@code instance} was 102 * instantiated of. 103 * 104 * <p>{@code null} will be returned if: 105 * <ul> 106 * <li>There is no corresponding {@code ClassInfo} instance cached.</li> 107 * <li>The passed-in {@code instance} is {@code null} or {@code undefined}.</li> 108 * </ul> 109 * 110 * @param instance the instance to return the appropriate class info for 111 * @return the class info representing the instance's class 112 */ 113 public function getClassByInstance(instance):ClassInfo { 114 if (instance === null || instance === undefined) return null; 115 var p:Object = instance.__proto__; 116 var c:Number = p.__as2lib__hashCode; 117 if (c == undefined) return null; 118 if (c == p.__proto__.__as2lib__hashCode) { 119 return null; 120 } 121 return cache[c]; 122 } 123 124 /** 125 * Adds the passed-in {@code classInfo} to the list of cached class infos and returns 126 * this {@code classInfo}. 127 * 128 * @param classInfo the class info to add 129 * @return the passed-in and added {@code classInfo} 130 */ 131 public function addClass(info:ClassInfo):ClassInfo { 132 if (!info) return null; 133 var p = info.getType().prototype; 134 var h:Number = p.__as2lib__hashCode; 135 if (h != null && h != p.__proto__.__as2lib__hashCode) { 136 cache[h] = info; 137 } else { 138 cache[p.__as2lib__hashCode = hashCodeCounter++] = info; 139 _global.ASSetPropFlags(p, "__as2lib__hashCode", 1, true); 140 } 141 return info; 142 } 143 144 /** 145 * Returns the package info representing the passed-in {@code package}. 146 * 147 * <p>{@code null} will be returned if: 148 * <ul> 149 * <li>There is no corresponding {@code PackageInfo} instance cached.</li> 150 * <li>The passed-in {@code package} is {@code null} or {@code undefined}.</li> 151 * </ul> 152 * 153 * @param package the package to return the appropriate package info for 154 * @return the pakcage info representing the passed-in {@code package} 155 */ 156 public function getPackage(package):PackageInfo { 157 if (package === null || package === undefined) return null; 158 var c:Number = package.__as2lib__hashCode; 159 if (c == null) return null; 160 if (c == package.__proto__.__as2lib__hashCode) { 161 return null; 162 } 163 return cache[c]; 164 } 165 166 /** 167 * Adds the passed-in {@code packageInfo} to this cache and returns this added 168 * {@code packageInfo}. 169 * 170 * @param packageInfo the package info to add 171 * @return the passed-in and added {@code packageInfo} 172 */ 173 public function addPackage(info:PackageInfo):PackageInfo { 174 if (!info) return null; 175 var p = info.getPackage(); 176 var h:Number = p.__as2lib__hashCode; 177 if (h != null && h != p.__proto__.__as2lib__hashCode) { 178 cache[h] = info; 179 } else { 180 cache[p.__as2lib__hashCode = hashCodeCounter++] = info; 181 _global.ASSetPropFlags(p, "__as2lib__hashCode", 1, true); 182 } 183 return info; 184 } 185 186 /** 187 * Returns the root package of the whole package hierarchy. 188 * 189 * <p>The root package is also refered to as the default package. 190 * 191 * <p>The root/default package determines where the {@code ClassAlgorithm} and 192 * {@code PackageAlgorithm} classes start their search. 193 * 194 * @return the root/default package 195 */ 196 public function getRoot(Void):PackageInfo { 197 return root; 198 } 199 200 /** 201 * Releases all cached class and package infos. 202 * 203 * <p>Note that their {@code __as2lib__hashCode} variable stays the same. 204 */ 205 public function releaseAll(Void):Void { 206 cache = new Array(); 207 addPackage(root); 208 } 209 210 }