1 /**
  2  * @author Gillis Haasnoot <gillis.haasnoot@gmail.com>
  3  * @package Banana.Util
  4  * @summary ArrayBiCollection
  5  */
  6 
  7 goog.provide('Banana.Util.ArrayBiCollection');
  8 
  9 goog.require('Banana.Util.ArrayUniCollection');
 10 
 11 /**
 12  * Array bi collection is a wrapper class holding two Banana.Util.ArrayUniCollection
 13  * In one we keep track of key -> index. In the other key -> data.
 14  * 
 15  * @constructor
 16  */
 17 Banana.Util.ArrayBiCollection = function()
 18 {
 19 	this.keyIndex = new Banana.Util.ArrayUniCollection();
 20 	this.keyData = new Banana.Util.ArrayUniCollection();
 21 
 22 	/**
 23 	 * Clones the collection
 24 	 * @return {Banana.Util.ArrayBiCollection}
 25 	 */
 26 	this.clone = function()
 27 	{
 28 		var t = new Banana.Util.ArrayBiCollection();
 29 		t.keyIndex = this.keyIndex.clone();
 30 		t.keyData = this.keyData.clone();
 31 		return t;
 32 	}
 33 
 34 	/**
 35 	 * gets indexed array with elements containing the data
 36 	 * @return {Array}
 37 	 */
 38 	this.getArray = function()
 39 	{
 40 		var a = [];
 41 
 42 		this.each(function(i,d)
 43 		{
 44 			a.push(d);
 45 		});
 46 
 47 		return a;
 48 	}
 49 
 50 	/**
 51 	 * Adds new item to the collection. Key in string or int format.
 52 	 * @param {String} key
 53 	 * @param {mixed} item
 54 	 */
 55 	this.addItem = function(key, item)
 56 	{
 57 		this.remove(key);
 58 		this.keyIndex.addItem(key,this.keyIndex.getLength())
 59 		this.keyData.addItem(key,item);
 60 	};
 61 
 62 	/**
 63 	 * Gets data by key
 64 	 * @param {String} key
 65 	 * @return {mixed} 
 66 	 */
 67 	this.getItem = function(key)
 68 	{
 69 		return this.keyData.getItem(key);
 70 	};
 71 
 72 	/**
 73 	 * Gets item by index
 74 	 * @param {int} index
 75 	 * @return {mixed} 
 76 	 */
 77 	this.getItemByIndex = function(index)
 78 	{
 79 		return this.keyData.getItemByIndex(index);
 80 	}
 81 
 82 	/**
 83 	 * Gets key by index
 84 	 * @param {int} index
 85 	 * @return {String}
 86 	 */
 87 	this.getKeyByIndex = function(index)
 88 	{
 89 		return this.keyIndex.getKeyByIndex(index);
 90 	}
 91 
 92 	/**
 93 	 * TODO: (Duplicated implementation of getItem??)
 94 	 * Gets item by key
 95 	 * @ignore 
 96 	 * @param {String} key
 97 	 * @return {mixed}
 98 	 */
 99 	this.getItemByKey = function(key)
100 	{
101 		return this.getItemByIndex(this.getIndex(key));
102 	}
103 
104 	/**
105 	 * gets index by key
106 	 * @param {String} key
107 	 * @return {int} 
108 	 */
109 	this.getIndex = function(key)
110 	{
111 		return this.keyIndex.getItem(key);
112 	}
113 
114 	/**
115 	 * gets length of the collection
116 	 * @return {int}
117 	 */
118 	this.getLength = function()
119 	{
120 		return this.keyIndex.getLength();
121 	}
122 
123 	/**
124 	 * checks if given key exists in the collection
125 	 * @param {String} key
126 	 * @return {boolean} true if found
127 	 */
128 	this.isset = function(key)
129 	{
130 		return (this.getItem(key) != undefined);
131 	}
132 
133 	/**
134 	 * Removes item by key
135 	 * @param {String} key
136 	 */
137 	this.remove = function(key)
138 	{
139 		if (this.isset(key))
140 		{
141 
142 			var index = this.keyIndex.getItem(key);
143 
144 			this.keyIndex.removeByIndex(index);
145 			this.keyData.removeByIndex(index);
146 
147 			///we need to decrement keyindex items after removed item
148 			var len = this.getLength();
149 			for (var i = index;  i < len; i++)
150 			{
151 
152 				this.keyIndex.alterItem(this.getKeyByIndex(i),i);
153 
154 			}
155 		}
156 	}
157 
158 	/**
159 	 * clears the collection
160 	 */
161 	this.clear = function()
162 	{
163 		this.keyIndex = new Banana.Util.ArrayUniCollection();
164 		this.keyData = new Banana.Util.ArrayUniCollection();
165 	}
166 
167 	/**
168 	 * sorts the collection
169 	 * @param {Function} fn
170 	 */
171 	this.sort = function(fn)
172 	{
173 		var sortedKeys = this.keyIndex.sortedKeys(fn);
174 		var oldData = this.keyData;
175 		this.clear();
176 
177 		for (var i = 0; i < sortedKeys.length; i++)
178 		{
179 			this.addItem(sortedKeys[i], oldData.getItem(sortedKeys[i]));
180 		}
181 
182 		return this;
183 	}
184 
185 	/**
186 	 * Walks over the collection
187 	 * @param {Function} f
188 	 * @param {mixed} userdata
189 	 */
190 	this.each = function(f,userdata)
191 	{
192 		var len = this.getLength();
193 		for (var i = 0; i < len; i++)
194 		{
195 			f(i,this.getItemByIndex(i),userdata);
196 		}
197 	}
198 }