/**
 * Arrays
 */
function Arrays() {}

/**
 * Utility method to remove an item from an array and compact the array
 */
Arrays.removeFromArray = function(array, item)
{
	var result = null;
	var i = 0;
	// search for and remove the item
	while (i < array.length)
	{
		if (array[i] == item)
		{
			result = array[i];
			array[i] = null;
			break;
		}
		i++;
	}
	
	if (result != null)
	{
		Arrays.shiftDown(array, i);
	}
	return result;
};

Arrays.shiftDown = function(array, index)
{
	while (index < array.length)
	{
		if ((index + 1) < array.length)
		{
			array[index] = array[index + 1];
		}
		index++;
	}
	array.length--;
};


/**
 * Map
 * 
 * An object-to-object map backed by arrays. 
 * Search speed is slow for large collections. 
 */
function Map()
{
	this.m_keys = new Array();
	this.m_values = new Array();
}

/**
 * Gets the value mapped to the specified key
 */
Map.prototype.getValue = function(key)
{
	var index = this.getIndexOf(key);
	if (index >= 0)
	{
		return this.m_values[index];
	}
	return null;
};

/**
 * Create a new mapping
 * @return previous value mapped to the key, or null if no mapping existed
 */
Map.prototype.put = function(key, value)
{
	if (key == null)
		throw "Map.put(): key cannot be null"

	if (value == null)
		throw "Map.put(): value cannot be null"
	
	var result = null;
	var index = this.getIndexOf(key);
	if (index >=0)
	{
		result = this.m_values[index];
		this.m_values[index] = value;
	}
	else
	{
		this.m_keys[this.m_keys.length] = key;
		this.m_values[this.m_values.length] = value;
	}
	return result;
};

/**
 * Removes a mapping
 * @return value mapped to the key, or null if no mapping existed
 */
Map.prototype.remove = function(key)
{
	var result = null;
	var index = this.getIndexOf(key);
	if (index >= 0)
	{
		this.m_keys[index] = null;
		Arrays.shiftDown(this.m_keys, index);
		result = this.m_values[index];
		this.m_values[index] = null;
		Arrays.shiftDown(this.m_values, index);
	}
	return result;
};

/**
 * Get the number objects mapped by this map
 */
Map.prototype.getSize = function()
{
	return this.m_keys.length;
};

/**
 * Gets an array containing all the keys
 */
Map.prototype.getKeys = function()
{
	var result = new Array();
	for (var i = 0; i < this.m_keys.length; i++)
	{
		result[i] = this.m_keys[i];
	}
	return result;
};

Map.prototype.contains = function(key)
{
	return this.getIndexOf(key) > 0;
};

Map.prototype.getIndexOf = function(key)
{
	for (var i = 0; i < this.m_keys.length; i++)
	{
		if (this.m_keys[i] == key)
		{
			return i;
		}
	}
	return -1;
};
