1 /* 2 * Copyright (C) 2012-2013 DFKI GmbH 3 * Deutsches Forschungszentrum fuer Kuenstliche Intelligenz 4 * German Research Center for Artificial Intelligence 5 * http://www.dfki.de 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 define( 28 //this comment is needed by jsdoc2 [copy of comment for: function Dictionary(...] 29 /** 30 * A dictionary (or map) for key-value storage and access. 31 * @name Dictionary 32 * @class 33 */ 34 function(){ 35 36 //set to @ignore in order to avoid doc-duplication in jsdoc3 37 /** 38 * @ignore 39 * 40 * A dictionary (or map) for key-value storage and access. 41 * @constructs Dictionary 42 */ 43 function Dictionary() { 44 45 /** 46 * "map" for the dictionary 47 * 48 * @private 49 * 50 * @memberOf Dictionary# 51 */ 52 var map = {}; 53 54 /** 55 * This list contains the "keys" of all current entries in <tt>map</tt>. 56 * 57 * @private 58 * 59 * @memberOf Dictionary# 60 */ 61 var keyList = []; 62 63 /** 64 * Prefix for keys in internal MAP object, for avoiding overwrite of 65 * existing Object properties/functions 66 * 67 * @constant 68 * @private 69 * 70 * @memberOf Dictionary# 71 */ 72 var KEY_PREFIX = '$$'; 73 74 /** 75 * Helper function that creates the actual lookup key. 76 * 77 * The "lookup key" is original key with applied key-prefix. 78 * 79 * @param {String} key 80 * the key (without the internal key prefix) 81 * @returns {String} 82 * the key prefixed with the internal key prefix 83 * 84 * @private 85 * 86 * @memberOf Dictionary# 87 */ 88 var lookupKey = function(key) { 89 return KEY_PREFIX + key; 90 }; 91 92 /** @lends Dictionary.prototype */ 93 return { 94 /** 95 * Put / add an entry to the dictionary. 96 * 97 * @param {String} 98 * key the lookup key for the value 99 * @param {any} 100 * value the value to store 101 * 102 * @public 103 * 104 * @memberOf Dictionary.prototype 105 */ 106 put : function(key, value) { 107 108 var isAlreadyPresent = this.containsKey(key); 109 110 var lKey = lookupKey(key); 111 map[lKey] = value; 112 113 if (!isAlreadyPresent) { 114 keyList.push(lKey); 115 } 116 }, 117 /** 118 * Check if the dictionary contains an entry for a key. 119 * 120 * @param {String} 121 * key the lookup key to check 122 * @returns {Boolean} <code>true</code> if an entry exists, otherwise 123 * <code>false</code> 124 * 125 * @public 126 */ 127 containsKey : function(key) { 128 return typeof map[lookupKey(key)] !== 'undefined'; 129 }, 130 /** 131 * Check if the dictionary contains an entry with the value. 132 * 133 * <p> 134 * NOTE that this function may execute rather slowly, with O(n). 135 * 136 * @param {any} 137 * value the value to check 138 * @param {Boolean} 139 * [useStrict] if <code>true</code> entry-values are 140 * checked against param <tt>value</tt> with 141 * <code>===</code>. If <code>false</code> or omitted, 142 * values are compared with each other using <code>==</code>. 143 * @returns {Boolean} <code>true</code> if an entry exists, otherwise 144 * <code>false</code> 145 * 146 * @public 147 */ 148 containsValue : function(value, useStrict) { 149 for (var i = 0, size = keyList.length; i < size; ++i) { 150 if (useStrict) { 151 if (map[keyList[i]] === value) { 152 return true; 153 } 154 } else { 155 if (map[keyList[i]] == value) { 156 return true; 157 } 158 } 159 } 160 return false; 161 }, 162 /** 163 * Get the value for a key. 164 * 165 * @param {String} 166 * key the lookup key with was used to store the entry/value. 167 * @returns {any} the value for the <tt>key</tt>, or 168 * <code>undefined</code> if the dictionary has no entry for 169 * the <tt>key</tt>. 170 * 171 * @public 172 */ 173 get : function(key) { 174 return map[lookupKey(key)]; 175 }, 176 /** 177 * Remove an entry from the dictionary. 178 * 179 * <p> 180 * NOTE that this may execute rather slowly, with O(n). 181 * 182 * 183 * @param {String} 184 * key the lookup key for the entry to remove 185 * @returns {Boolean} <code>true</code> if the entry was removed. If 186 * there was no entry for the <tt>key</tt> and nothing was 187 * removed, <code>false</code> is returned. 188 * 189 * @public 190 */ 191 remove : function(key) { 192 193 if (this.containsKey(key)) { 194 195 var lKey = lookupKey(key); 196 197 // remove from map: 198 delete map[lKey]; 199 200 // remove from key-list 201 for (var i = 0, size = keyList.length; i < size; ++i) { 202 if (keyList[i] == lKey) { 203 keyList.splice(i, 1); 204 break; 205 } 206 } 207 return true; 208 } 209 210 return false; 211 }, 212 /** 213 * Get a list of the keys for all entries in the dictionary. 214 * 215 * <p> 216 * The returned list has no specific ordering. 217 * 218 * <p> 219 * NOTE that this may execute rather slowly, with O(n). 220 * 221 * <p> 222 * NOTE that the returned list is no "view" for the keys, i.e. changes 223 * on this list will not be reflected by the dictionary's key-list. 224 * 225 * @returns {Array<String>} a list of all keys 226 * @public 227 */ 228 getKeys : function() { 229 var prefixLen = KEY_PREFIX.length; 230 var size = keyList.length; 231 var list = new Array(size); 232 // create copy of keyList with removed key-prefixes: 233 for (var i = 0; i < size; ++i) { 234 list[i] = keyList[i].substring(prefixLen); 235 } 236 return list; 237 }, 238 /** 239 * Get the size of the dictionary. 240 * 241 * @returns {Number} the count of entries in the dictionary 242 * @public 243 */ 244 size : function() { 245 return keyList.length; 246 }, 247 /** 248 * Remove all entries from the dictionary. 249 * 250 * <p> 251 * NOTE that this may execute rather slowly, with O(n). 252 * 253 * @public 254 */ 255 clear : function() { 256 // var size = keyList.length; 257 // for(var i=0; i < size; ++i){ 258 // delete map[keyList[i]]; 259 // } 260 // keyList.splice(0, size); 261 delete map; 262 map = {}; 263 keyList.splice(0, keyList.length); 264 } 265 }; 266 }; 267 268 return Dictionary; 269 }); 270