Source: tools/extensions/dictionary.js


define(
	//this comment is needed by jsdoc2 [copy of comment for: function Dictionary(...]
	/**
	 * A dictionary (or map) for key-value storage and access.
	 * @name Dictionary
	 * @memberOf mmir.tools
	 * @class
	 *
	 * @example
	 * var Dictionary = new mmir.require('mmirf/dictionary');
	 * var d = new Dictionary();
	 */
	function(){

//set to @ignore in order to avoid doc-duplication in jsdoc3
/**
 * A dictionary (or map) for key-value storage and access.
 * @constructs mmir.tools.Dictionary
 * @ignore
 */
function Dictionary() {

	/**
	 * "map" for the dictionary
	 *
	 * @private
	 *
	 * @memberOf mmir.tools.Dictionary#
	 */
	var map = {};

	/**
	 * This list contains the "keys" of all current entries in <tt>map</tt>.
	 *
	 * @private
	 *
	 * @memberOf mmir.tools.Dictionary#
	 */
	var keyList = [];

	/**
	 * Prefix for keys in internal MAP object, for avoiding overwrite of
	 * existing Object properties/functions
	 *
	 * @constant
	 * @private
	 *
	 * @memberOf mmir.tools.Dictionary#
	 */
	var KEY_PREFIX = '$$';

	/**
	 * Helper function that creates the actual lookup key.
	 *
	 * The "lookup key" is original key with applied key-prefix.
	 *
	 * @param {String} key
	 * 			the key (without the internal key prefix)
	 * @returns {String}
	 * 			the key prefixed with the internal key prefix
	 *
	 * @private
	 *
	 * @memberOf mmir.tools.Dictionary#
	 */
	var lookupKey = function(key) {
		return KEY_PREFIX + key;
	};

	/** @lends Dictionary.prototype */
	return {
		/**
		 * Put / add an entry to the dictionary.
		 *
		 * @param {String}
		 *            key the lookup key for the value
		 * @param {any}
		 *            value the value to store
		 *
		 * @public
		 *
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		put : function(key, value) {

			var isAlreadyPresent = this.containsKey(key);

			var lKey = lookupKey(key);
			map[lKey] = value;

			if (!isAlreadyPresent) {
				keyList.push(lKey);
			}
		},
		/**
		 * Check if the dictionary contains an entry for a key.
		 *
		 * @param {String}
		 *            key the lookup key to check
		 * @returns {Boolean} <code>true</code> if an entry exists, otherwise
		 *          <code>false</code>
		 *
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		containsKey : function(key) {
			return typeof map[lookupKey(key)] !== 'undefined';
		},
		/**
		 * Check if the dictionary contains an entry with the value.
		 *
		 * <p>
		 * NOTE that this function may execute rather slowly, with O(n).
		 *
		 * @param {any}
		 *            value the value to check
		 * @param {Boolean}
		 *            [useStrict] if <code>true</code> entry-values are
		 *            checked against param <tt>value</tt> with
		 *            <code>===</code>. If <code>false</code> or omitted,
		 *            values are compared with each other using <code>==</code>.
		 * @returns {Boolean} <code>true</code> if an entry exists, otherwise
		 *          <code>false</code>
		 *
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		containsValue : function(value, useStrict) {
			for (var i = 0, size = keyList.length; i < size; ++i) {
				if (useStrict) {
					if (map[keyList[i]] === value) {
						return true;
					}
				} else {
					if (map[keyList[i]] == value) {
						return true;
					}
				}
			}
			return false;
		},
		/**
		 * Get the value for a key.
		 *
		 * @param {String}
		 *            key the lookup key with was used to store the entry/value.
		 * @returns {any} the value for the <tt>key</tt>, or
		 *          <code>undefined</code> if the dictionary has no entry for
		 *          the <tt>key</tt>.
		 *
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		get : function(key) {
			return map[lookupKey(key)];
		},
		/**
		 * Remove an entry from the dictionary.
		 *
		 * <p>
		 * NOTE that this may execute rather slowly, with O(n).
		 *
		 *
		 * @param {String}
		 *            key the lookup key for the entry to remove
		 * @returns {Boolean} <code>true</code> if the entry was removed. If
		 *          there was no entry for the <tt>key</tt> and nothing was
		 *          removed, <code>false</code> is returned.
		 *
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		remove : function(key) {

			if (this.containsKey(key)) {

				var lKey = lookupKey(key);

				// remove from map:
				map[lKey] = void(0);

				// remove from key-list
				for (var i = 0, size = keyList.length; i < size; ++i) {
					if (keyList[i] == lKey) {
						keyList.splice(i, 1);
						break;
					}
				}
				return true;
			}

			return false;
		},
		/**
		 * Get a list of the keys for all entries in the dictionary.
		 *
		 * <p>
		 * The returned list has no specific ordering.
		 *
		 * <p>
		 * NOTE that this may execute rather slowly, with O(n).
		 *
		 * <p>
		 * NOTE that the returned list is no "view" for the keys, i.e. changes
		 * on this list will not be reflected by the dictionary's key-list.
		 *
		 * @returns {Array<String>} a list of all keys
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		getKeys : function() {
			var prefixLen = KEY_PREFIX.length;
			var size = keyList.length;
			var list = new Array(size);
			// create copy of keyList with removed key-prefixes:
			for (var i = 0; i < size; ++i) {
				list[i] = keyList[i].substring(prefixLen);
			}
			return list;
		},
		/**
		 * Get the size of the dictionary.
		 *
		 * @returns {Number} the count of entries in the dictionary
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		size : function() {
			return keyList.length;
		},
		/**
		 * Remove all entries from the dictionary.
		 *
		 * <p>
		 * NOTE that this may execute rather slowly, with O(n).
		 *
		 * @public
		 * @memberOf mmir.tools.Dictionary.prototype
		 */
		clear : function() {
			// var size = keyList.length;
			// for(var i=0; i < size; ++i){
			// delete map[keyList[i]];
			// }
			// keyList.splice(0, size);
			map = void(0);
			map = {};
			keyList.splice(0, keyList.length);
		}
	};
};

return Dictionary;
});