/**
 *      Copyright 2006 - Luca Guidi / thedigitalconspiracy.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/****************************************************************************/
/*                             STRING CLASS                                 */
/****************************************************************************/
/**
 * String
 * Extending String class
 *
 * @author 			Luca Guidi
 * @version 			1.0
 * @since 			1.0
 * 
 * date				2006 Oct, 30
 * last revision		2006 Oct, 30
 */
 
    /**
     * Check if two strings are equals
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 26
     * last revision		2006 Oct, 26
     *
     * @param               	sString
     *
     * @return              	true, if are equals
     *                      	false, if not
     */
 /*boolean*/ String.prototype.equals = function(/*String*/ sString){
        return (this == sString) ? true : false;
    }
 
/****************************************************************************/
/*                           EXCEPTION CLASS                                */
/****************************************************************************/
/**
 * Exception
 * Provides an exception handling
 *
 * @author 			Luca Guidi
 * @version 			1.0
 * @since 			1.0
 * 
 * date				2006 Oct, 30
 * last revision		2006 Oct, 30
 */
 var Exception = {
    /*static String*/ INVALID_ARGUMENT : 'Invalid argument',
    
    /**
     * Provides an exception handling
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 30
     * last revision		2006 Oct, 30
     *
     * @param			eError, a JavaScript Error object
     *				that we want to throw.
     *
     * @return			A string with useful error informations.
     */    
    /*static String*/ throwEx : function(/*Error*/ eError){
        if( !(eError instanceof Error) )
            throw new Error('Invalid Exception Handling');
        
        return 'Exception: '+ eError.message +' @ ' + eError.fileName
            +':'+(eError.lineNumber - 1);
    }
 }
/****************************************************************************/
/*                            HASHMAP CLASS                                 */
/****************************************************************************/

/**
 * HashMap
 * 
 * @author 			Luca Guidi
 * @version 			1.0
 * 
 * date				2006 Oct, 25
 * last revision		2006 Oct, 30
 */
 HashMap = Class.create();
 
 HashMap.prototype = {
    
    /*struct*/  oStruct     : null,
    /*int*/     sSize       : 0,
	/*struct*/  keys		: null,
	/*int*/ 	actualKey	: 0,
	/*int*/ 	sKeys		: 0,
    
    /**
     * Constructor.
     * Required by Prototype.
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 30
     * last revision		2006 Oct, 30
     */
    /*HashMap*/ initialize : function(){
        this.oStruct = {}
		this.keys = {}
        return;
    },
 
    /**
     * Clear the hashmap contents
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 30
     * last revision		2006 Oct, 30
     */
    /*void*/ clear : function(){
        this.oStruct = {}
		this.keys = {}
        this.sSize = 0;
		 this.actualKey = 0;
        return;
    },
 
    /**
     * Check if contains specified key
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 25
     * last revision		2006 Oct, 25
     *
     * @param       	        sKey
     *
     * @return      	        true, if hashmap contains key
     *              	        false, if not
     */
    /*boolean*/ containsKey : function(/*String*/ sKey){
        for(var x in this.oStruct){
            if(x == sKey && this.oStruct[sKey] != undefined)
                return true;
        }
        
        return false;
    },
    
    /**
     * Check if contains an object with specified value
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 25
     * last revision		2006 Oct, 30
     *
     * @param               	sValue
     *
     * @return              	true, if map contains specified value
     *                      	false, if not
     */
    /*boolean*/ containsValue : function(/*String*/ sValue){
        for(var x in this.oStruct){
            if( this.oStruct[x] != undefined
		&& (this.oStruct[x].toString()).equals(sValue.valueOf()) )
                return true;
        }
        
        return false;
    },
    
    /**
     * Returns the object with specified key
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 24
     * last revision		2006 Oct, 24
     *
     * @param               	sKey
     *
     * @return              	The object with specified key.
     */
    /*Object*/ get : function(/*String*/ sKey){
        if(!this.containsKey(sKey))
            return null;
        return this.oStruct[sKey];
    },
    
    /**
     * Check if hashmap is empty
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 24
     * last revision		2006 Oct, 24
     *
     * @return              	true, if map is empty
     *                      	false, if not
     */
    /*Object*/ isEmpty : function(){
        return (this.sSize <= 0) ? true : false;
    },
   
    /**
     * Set into the hashmap an object with specified key.
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 24
     * last revision		2006 Oct, 30
     *
     * @param               	sKey
     * @param               	oObj
     *
     * @return              	Previous value associated to the key
     */
    /*Object*/ put : function(/*String*/ sKey, /*Object*/ oObj){
//		alert(sKey);
		
		/* //comentado por Lauro, em 30/05/2007
        if( !(oObj instanceof Object) )
            throw Exception.throwEx(new Error(Exception.INVALID_ARGUMENT));
        */
		
        oOldObj = null;
        //If key's not in Map, we need to increment size
        if( this.containsKey(sKey) )
            oOldObj = this.get(sKey);
        else
            this.sSize++;
   
        this.oStruct[sKey] = oObj;
		
		this.sKeys = this.sSize - 1;
		
		this.keys[this.sKeys] = sKey;//Por Lauro

        return oOldObj;
    },
        
    /**
     * Remove the object at specified key.
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 24
     * last revision		2006 Oct, 30
     *
     * @param               	sKey
     *
     * @return              	The removed object
     */
    /*Object*/ remove : function(/*String*/ sKey){
        if(!this.containsKey(sKey))
            return null;
        oldObj = this.oStruct[sKey];
        this.oStruct[sKey] = undefined;
		
		//por Lauro...
		//remove a chave...
		var auxKeys = {};
		var cont = 0;
		for(var i = 0; i < this.keys.length; i++){
			if(this.keys[i] != sKey){
				auxKeys[cont] = sKey;
				cont++;
			}
		}
		
		this.keys = auxKeys;
		//--
		
        this.sSize--;
        
        return oldObj;
    },
    
    /**
     * Return hashmap size
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 30
     * last revision		2006 Oct, 30
     *
     * @return              	map size
     */
    /*int*/ size : function(){
        return this.sSize;
    },
    
    /**
     * Returns selializated internal contents.
     * "[k0 : objK0, k1 : objK1, k2 : objK2, ..., kn : objKn]"
     *
     * @author 			Luca Guidi
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2006 Oct, 30
     * last revision		2006 Oct, 30
     *
     * @return              	Serializated contents.
     */
    /*String*/ toString : function(){
        var str = '[';
        for(var x in this.oStruct)
            str += x+' : '+this.oStruct[x]+','
        str += ']'
        return str;
    },
	
	/**
     * Itera o HashMap.
     *
     * @author 			Lauro Becker
     * @version 		1.0
     * @since 			1.0
     * 
     * date			2007 May, 30
     * last revision		2007 May, 30
     *
     * @return              	element
     */
	 /*Object*/ next : function(){
//		 alert("oStrinct["+this.keys[this.actualKey]+"]");
		 
		 if(this.hasNext){
			 if(this.oStruct[this.keys[this.actualKey]]){
				this.actualKey++;
				return this.oStruct[this.keys[this.actualKey - 1]];
			 }
			 else{
				 return null;
			 }
		 }
	 },
	 
	 hasNext : function(){
		 if(this.actualKey <= this.sKeys){
			 return true;
		 }
		 else{
			 return false;
		 }
	 },
	 
	 resetIterator : function(){
		 this.actualKey = 0;
	 },
	 
	 getActualKey : function(){
		 return this.keys[this.actualKey - 1];
	 }
}
