//TODO history onComplete request
//TODO declare MD5 build in the object in order that the arrays are note build for all MD5 build

/**
 * @fileoverview this files provides static method which allow to send network request in order to obtain html content or comwebBean object (xml Content) via the CW_comwebAjax class, and provides utility request class like transaction, requestResume ...
 */


function AjaxTransactionManager(){
	this.initialize();
}

AjaxTransactionManager.prototype = {
	/**
	 * Stores the differents transactions
	 * @type {HashTable}
	 */
	ajaxTransactions:null,
	/**
	 * Stores the default transaction name in order to return the corresponding transaction
	 * when no other transaction were added
	 * @type {String}
	 */
	defaultTransactionName : "defaultTr123",

	/**
	 * call by the constructor in order to initialize attributes values
	 */
	initialize: function(){
		this.ajaxTransactions = new HashTable();
		this.addNewTransaction(this.defaultTransactionName);
	},
	/**
	 * @param {String} transactionId unique transaction identifier
	 * @return {boolean} indicate if the transaction is correctly creates
	 */
	addNewTransaction:function(transactionId){
		 if (this.ajaxTransactions.containsKey(transactionId)){
		 	return false;
		 }else{
			this.ajaxTransactions.put(transactionId,new AjaxTransaction(transactionId));
		 }
	},
	/**
	 * @param {String} transactionId unique transaction identifier
	 * @return {AjaxTransaction} the corresponding transaction, if there is not return the default transaction
	 */
	getTransaction:function(transactionId){
		if (this.ajaxTransactions.containsKey(transactionId)){
			return this.ajaxTransactions.get(transactionId);
		}else{
			CW_logger.log(CW_logger.LEVEL_WARNING,"AjaxTransactionManager.getTransaction("+transactionId+"): no transaction correspond to the given identifier, return the default one")
			this.addNewTransaction(transactionId)
			return this.ajaxTransactions.get(transactionId);
		}
	}

};

/**
 * @class this class permits to manage a request ajax group, which correspond to a transaction,
 * this transaction give methods, in order that comwebAjax used it when process and buil request as
 * an LIFO (last in first out) steak
 * @param {String} _identifier
 * @constructor
 */
function AjaxTransaction(_identifier){
	this.identifier = _identifier;
	this.initialize();
}

AjaxTransaction.prototype = {
	/**
	 * stores the unique transaction identifier of the instance
	 * @type {String} unique transaction identifier
	 */
	identifier:null,
	/**
	 * stores the differents MD5 sign of ajax request which corresponding to this transaction
	 *@type {Array}
	 */
	transactions:null,
	/**
	 * call by the constructor in order to initialize attributes values
	 */
	initialize: function(){
		this.transactions = new Array();
	},

	/**
	 * called wnen ComwebAjax creat a new ajax request, and give to the corresponding transaction
	 * (this instance) the md5 sign of the request, allow to register the given MD5 sign
	 *@param {String} MD5_sign
	 */
	 registerMD5:function(MD5_sign){
		this.transactions.push(MD5_sign);
	 },

	 /**
	  * Allow to know if the given MD5 sign corresponding to the last register request
	  * @param {String} MD5_sign the md5 sign of the request
	  * @return {boolean} return if the last register request, so MD5 sign, is the given MD5 sign
	  */
	  isLastTransaction:function(MD5_sign){
			//used prototype.js Array extension
			return this.transactions.last() == MD5_sign;
	  },
	/**
	 * Allow to clear all the registered request (MD5 sign), this method must be called only after
	 * process the last register request
	 */
	  removeAll:function(){
	  	//used prototype.js Array extension
	  	this.transactions.clear();
	  },
	  /**
	   * Allow to know if a given MD5 sign is valid, in fact a valid MD5 sign is a MD5 sign
	   * which was registered and not delete when an youngest MD5 sign (request) proccess response
	   * @param {String} MD5_sign the given MD5_sign
	   * @return {boolean} indicates if the given MD5_sign is valid
	   */
	  isValidMD5: function(MD5_sign){
	  		CW_logger.log(CW_logger.LEVEL_INFORMATION , "AjaxTransaction("+this.identifier+").isValidMD5 " + MD5_sign + " ||content " + this.toString());
			return (this.transactions.indexOf(MD5_sign) >= 0);
	  },
		/**
		 * Allow to delete older registered MD5 sign than the given one, used it when you process
		 * the response of the request corresponding to the given MD5_sign.  The given MD5 will be delete too
		 *@param {String} MD5_sign the given MD5 sign
		 */
	  deleteOlderMD5: function (MD5_sign){
			if (this.transactions.indexOf(MD5_sign) > 0){
				var findMD5 = false;
				var currentMD5;

				while (this.transactions.length > 0 && !findMD5){
					currentMD5 = this.transactions.shift();
					findMD5 = (currentMD5 == MD5_sign);
				}
			}
	  },
		/**
		 * Allow to delete the given MD5 sign, used it when you process the response of the corresponding
		 * request, but this response is not valid (for example have not the 200 status)
		 *@param {String} MD5_sign the given MD5 sign
		 */
	  deleteMD5: function(MD5_sign){
			this.transactions = this.transactions.without(MD5_sign);
	  },

		toString: function(){
			var result = "";
			for (var i = 0;i<this.transactions.length;i++){
				result = result + this.transactions[i] + " ||";
			}
			return result;
		}



};


/**
 * @class This class permits to store the differents values of an ajax request, in order to retrieve the values
 * when the ajax sended request operation have finished
 * @param {String} _url url of the request (with no parameters)
 * @param {String} _callback  : value of the function which will be called with the xml content (comwebBean) as parameter
 * @param {String} _queryString : parameters of the request (not encoded in UTF-8) like , langId=FR&serviceId=3
 * @param {boolean} _historyEntry : indicates if the ajax operation must enter in the history
 * @param {String} _transactionId : identifier of the corresponding ajax transaction
 * @param {String} _MD5Sign : MD5 sign which corresponding to the request (MD5(url + queryString + config.webappName))
 * @constructor
 */
function RequestResume(_url,_callback ,_queryString,_historyName,_transactionId,_MD5Sign,_hashTableStore){
	/**
	 *url of the request (with no parameters)
	 * @type {String}
	 */
	this.url = _url;
	/**
	 *value of the function which will be called with the xml content (comwebBean) as parameter
	 * @type {String}
	 */
	this.callback  = _callback ;
	/**
	 *parameters of the request (not encoded in UTF-8) like , langId=FR&serviceId=3
	 * @type {String}
	 */
	this.queryString = _queryString;
	/**
	 *indicates if the ajax operation must enter in the history
	 * @type {boolean}
	 */
	this.historyEnter = (_historyName != null);
	/**
	 *indicates the refresh page history name (if name==null then no history)
	 *@type {String}
	 */
	this.historyName = _historyName;
	/**
	 *identifier of the corresponding ajax transaction
	 * @type {String}
	 */
	this.transactionId = _transactionId;
	/**
	 *MD5 sign which corresponding to the request (MD5(url + queryString + config.webappName))
	 * @type {String}
	 */
	this.MD5Sign = _MD5Sign;

	this.hashTableStore = _hashTableStore;
}


/**
 * This static class provides static method which allow to send network request in order to obtain html content or comwebBean object (xml Content)  To access to the satic method use: <b>CW_comwebAjax.method(...)</b>
 * @class This static class permits to regroup util method like encoder, decoder ....  To access to the satic method use: <b>CW_util.method(...)</b>
 * @constructor
 */
function CW_comwebAjax (){
}

CW_comwebAjax.prototype = {
	/**
	 * Stores the AjaxTransactionManager in order to manage the transaction request
	 * @type {AjaxTransactionManager}
	 */
	ajaxTransactionManager :  new AjaxTransactionManager(),

	getHost:function(){
		var comwebBean_upload = getUploadWrapper();
		return comwebBean_upload.getHost();
	},

	getUploadWrapper: function() {
		  var xhr = Ajax.getTransport();
		  xhr.open('GET', '/comweb/upload?action=host&cache=' + (new Date()).getTime(), false);
		  xhr.send(null);

		var logIndic = " CW_comwebAjax.getHost() "
		var docxml;
		try{
			/*docxml = xmlparser.loadXML(xhr.responseText);
			var chilNodes = docxml.getChildNodes();
			if (chilNodes.length == 1){
				docxml = chilNodes.item(0);
			}else if (chilNodes.length == 2){
				if (chilNodes.item(0).getNodeName() == "xml"){
					CW_logger.log(CW_logger.LEVEL_COMWEB_AJAX,logIndic + " first child have xml ("+chilNodes.item(0).getNodeValue()+") name deliver the second one");
					docxml = chilNodes.item(1);


				}else{
					CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.getHost(), there are 2 chilNodes, and the first is not xml so understanding xml content <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>");
					return false;
				}
			}else{
				if (chilNodes.length == 0){
					CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.getHost(), there are no chilNodes, so understanding xml content <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>");
					return false;
				}else{
					CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.getHost(), there are too many chilNodes, so understanding xml content <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>");
					return false;
				}
			}*/

								if (window.ActiveXObject) {
		                // Code for IE
		                var doc = new ActiveXObject("Microsoft.XMLDOM");

		                doc.async = "false";
		                doc.loadXML(xhr.responseText);
		            } else {
		                // Code for Mozilla, Firefox, Opera, etc.
		                var parser = new DOMParser();
		                var doc = parser.parseFromString(xhr.responseText, "text/xml");
		            }

					docxml = doc.documentElement;
		}catch (e){
			CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.getHost(), the file is not xmlValid or can't get chilNodes <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>" + e);
			return false;
		}

		var comwebBean_upload = new ComwebBean_upload();
		comwebBean_upload.parseXml(docxml);
		// var result = comwebBean_upload.getHost();
		// CW_logger.log(CW_logger.LEVEL_COMWEB_AJAX,logIndic + " -> result:" + result);
		// return result;
		return comwebBean_upload;

	},

	/**
	 * this method allow to obtain the xml content deliver by the given url, this
	 * content will be parsed and return to the refresh function given by parameter.
	 * <br />
	 * otherParams : this method can be called like this : sendRequest(url,callback ,historyEnter,transactionId,'param1=value1','param2=value2' ...) <br />
	 * where the other parameters are the request parameters and must be like : '[param name]=[param value]'
	 * <br />
	 * @param {String} url url of the request (with no parameters)
	 * @param {String} callback  : value of the function which will be called with the xml content (comwebBean) as parameter
	 * @param {String} historyName indicates the refresh page history name (if name==null then no history)
	 * @param {String} transactionId : identifier of the corresponding ajax transaction
	 * @param {String} ... (otherParams) : parameters of the request (not encoded in UTF-8) like: 'langId=FR','serviceId=3'
	 * @deprecated
	 * @ignore
	 */
	sendRequest : function (url,callback ,historyName,transactionId){
		alert("sendRequest OLD");

		var queryString = this._createQueryString(arguments,4);
		this._sendRequestQueryString(url,callback ,historyName,transactionId,queryString);
	},

	/**
	 * <br>
	 * <b>CW_comwebAjax.sendRequest(url,callback ,historyName,transactionId,parameters,hashTableStore)</b>
	 * <br>
	 * This method allow to obtain the xml content deliver by the given url, this
	 * content will be parsed and return to the callback function given by parameter, the hashTableStore parameter is the hashTable Design values .
	 *
	 * @param {String} url url of the request (with no parameters)
	 * @param {String} callback  : value of the function which will be called with the xml content (comwebBean) as parameter
	 * @param {String} historyName indicates the refresh page history name (if name==null then no history)
	 * @param {String} transactionId : identifier of the corresponding ajax transaction
	 * @param {Array} parameters : array which contain value and parameters for the request, must contain string like '[param name]=[param value]'
	 * @param {HashTable} hashTableStore : hashtable which is transmit to the given callback function
	 */
	sendRequest : function (url,callback ,historyName,transactionId,parameters,hashTableStore){

		if (parameters!=null &&  !(parameters instanceof  Array)){
			CW_logger.log(CW_logger.LEVEL_ERROR,"you are using deprected sendRequest with parameters as string, you must set request parameters in an Array");
		}else{
			var queryString = "" ;
			if (parameters){
				queryString = this._createQueryString(parameters,0);
			}
			this._sendRequestQueryString(url,callback ,historyName,transactionId,queryString,hashTableStore);
		}
	},

	/**
	 * <br>
	 * <b>CW_comwebAjax.sendRequestForm(url,callback,historyName,transactionId,form,hashTableStore)</b>
	 * <br>
	 * This method allow to obtain the xml content deliver by the given url, this
	 * content will be parsed and return to the callback function given by parameter, the hashTableStore parameter is the hashTable Design values .
	 * the url parameters are builded from the given form
	 *
	 *@param {String} url: url which is invoke in order to obtain the xml content
	 *@param {String} callback : value of the function which will be called with the xml content as parameter
	 *@param {String} historyName indicates the refresh page history name (if name==null then no history)
	 *@param {String} transactionId : identifier of the corresponding ajax transaction
	 *@param {FormElement} form which have the differents params (name are the inputs names) and values (inputs values) of the query string
	 *@param {HashTable} hashTableStore : hashtable which is transmit to the given callback function
	 */
	sendRequestForm: function (url,callback,historyName,transactionId,form,hashTableStore){
		//alert("sendRequestForm");

		var queryString = Form.serialize(form);
		//alert(queryString);

		CW_logger.log(CW_logger.LEVEL_INFORMATION,"sendRequestForm:"+ queryString );
		this._sendRequestQueryString(url,callback,historyName,transactionId,CW_util.encodeUTF8(queryString),hashTableStore);
	},

	/**
	 * <br>
	 * <b>CW_comwebAjax.loadHtml(url,containerId,I18nHashParameters)</b>
	 * <br>
	 * update an HTML element (determines by the given containerId) with content (determines by the given url) from the server.
	 * the html content can contains i18n values, this values can need to set parameters, those parametres are stores in the given I18nHashParameters
	 *@param {String} url: url which is invoke in order to obtain the html  content
	 *@param {String} containerId : id of the html element will be refresh with the html content
	 *@param {HashTable} I18nHashParameters : hashtable which stores the i18n parameters values like "ownername -> charles"
	 *@param {boolean} append : indicates if the loaded html must be append as child of the given container
	 *@return {Element} the html element which is loaded
	 */
	loadHtml:function(url,containerId,I18nHashParameters,append){
		/*
		 * create the ajax request (prototype.js) options:
		 * the request method is post, the parameters are set in the post body and are encoded in UTF8
		 * when ajax (prototype.js) have the server response it deliver it to the onRequestComplete method
		 */
		 var xhr = Ajax.getTransport();
		 xhr.open('GET', url , false);
		 xhr.send(null);

		var appendHtml = false;
		if (append == true || append == "true"){
			appendHtml = true;
		}

		return this._onHtmlLoaded(I18nHashParameters,containerId,(new Date()).getTime(),url,xhr,append)

		/*var options = {
			asynchronous:false,
			method:'get',
			requestHeaders: ['X-Prototype-Version', Prototype.Version ],
			onComplete: this._onHtmlLoaded.bind(options,I18nHashParameters,containerId,(new Date()).getTime(),url)
		};

		CW_logger.log(CW_logger.LEVEL_INFORMATION,"ComwebAjax.loadHtml launch request - url:" + url + " containerId:" + containerId);
		new Ajax.Request(url, options);*/
	},
	/**
	 * called when the request created by loadHtml function is complete
	 * parse the html content in order to set the i18n values
	 * and refresh the htmlElement with the created content
	 * @private
	 * @ignore
	 * @param  {HashTable} I18nHashParameters : hashtable which stores the i18n parameters values like "ownername -> charles"
	 * @param {String} containerId : id of the html element will be refresh with the html content
	 * @param {XMLHttpRequest} xhr
	 */
	_onHtmlLoaded:function(I18nHashParameters,containerId,timeInMillis,url,xhr,append){
		var logIndic ="CW_comwebAjax._onHtmlLoaded ";

		try{
			var currentTime = (new Date()).getTime();
			var content = xhr.responseText;

			var i18nRegExp = new RegExp("i18n[(]{1,1}[a-zA-Z1-9,.]+[)]{1,1}","g");
			var i18nMatches = i18nRegExp.exec2(content);


			var i18nValuesRegExp =  new RegExp("[a-zA-Z1-9.]+","g");
			var currentI18n = "";
			var i18nvalues = null;

			for (var i=0;i<i18nMatches.length;i++){
				currentI18n = new String(i18nMatches[i]);
				//delete "i18n(" prefix and ")" suffix
				currentI18n = currentI18n.substring(5,currentI18n.length -1);
				i18nvalues = i18nValuesRegExp.exec2(currentI18n);

				if (i18nvalues.length == 1){
					content = content.replace(i18nMatches[i],CW_internationalization.getValue(i18nvalues[0]));
				}else if(i18nvalues.length > 1){
					content = content.replace(i18nMatches[i],CW_internationalization.getValueParams(i18nvalues[0],I18nHashParameters));
				}
			}
			var currentTime2 = (new Date()).getTime();
			var parentDiv = document.getElementById(containerId);
			if (!append){
				parentDiv.innerHTML = "";
			}

			var insertion = new Insertion.Bottom(parentDiv, content);
			var result = insertion.getFragment();

			//parentDiv.insertAdjacentHTML("beforeEnd", content);

			CW_logger.logTime("_onHtmlLoaded('"+url+"'), server response:" + (currentTime - timeInMillis) + " ms , i18n parsing:" + (currentTime - currentTime2) + " ms, display:" + ((new Date()).getTime() - currentTime2) + " ms" );



			var childsParentDiv = parentDiv.immediateDescendants();
			if (childsParentDiv.length > 0){
				return childsParentDiv[childsParentDiv.length -1];
			}else{
				return parentDiv.lastChild;
			}
		}catch(e){
			CW_logger.log(CW_logger.LEVEL_ERROR,"ComwebAjax.loadHtml launch request - url:" + url + " containerId:" + containerId + " error:" + e);
			return null;
		}
	},


	/**
	 *@ignore
	 *@private
	 *@param {String} url: url which is invoke in order to obtain the xml content
	 *@param {String} callback : value of the function which will be called with the xml content as parameter
	 *@param {String} historyName indicates the refresh page history name (if name==null then no history)
	 *@param {String} transactionId : identifier of the corresponding ajax transaction
	 *@param {String} queryString : query string of the request like [param1=value1&param2=value2...] where the differents value are escaped
	 *@param {HashTable} hashTableStore : hashtable which is transmit to the given callback function
	 *@author charles Herteaux [cherteaux@scroon.com]
	 *
	 */
	_sendRequestQueryString : function (url,callback ,historyName,transactionId,queryString,hashTableStore){
		/*
			in order to assure the compatible historyName version
			old was historyEnter, boolean which indcates if the history must contain the ajax response
		*/

		if (historyName!=null){
			if (historyName == "true"){
				historyName = "";
			}else if (historyName == "false"){
				historyName = null;
			}
		}


		/*
		 * set parameters values in querry string for the language and the service identifier
		 * in order that contacted service retrieve those informations
		 */
		if (queryString==null || queryString == ""){
			queryString = "lng=" +  CW_config.langId + "&site.uid=" + CW_config.serviceId;
		}else {
			if (queryString.indexOf("lng=") < 0){
				queryString += "&lng=" +  CW_config.langId + "&site.uid=" + CW_config.serviceId;
			}
			if (queryString.indexOf("site.uid=") < 0){
				queryString += "&site.uid=" + CW_config.serviceId;
			}
		}

		CW_logger.log(CW_logger.LEVEL_INFORMATION,"ComwebAjax.sendRequest - url: "+url+" queryString:" + queryString);

		/*
		 * set the MD5 sign
		 */
		var strMD5 = MD5(url + queryString + CW_config.webappName);
		//uncomment when the MD5 servlet will be available
		url = new String(url);
		if (CW_config.isProd && url.indexOf("/comweb/") == 0 ){
			url = url.replace("/comweb/","/comweb/MD5_" +MD5(queryString)+ "/");
		}

		/*
		 * register the request (MD5) in the given transaction
		 */
		transactionId = strMD5;
		var transaction = this.ajaxTransactionManager.getTransaction(transactionId);
		transaction	.registerMD5(strMD5);


		var	requestResume = new RequestResume(
				url,
				callback ,
				queryString,
				historyName,
				transaction.identifier,
				strMD5,
				hashTableStore);


		var asynchronousValue = true;
		if (callback == "CW_config.initInternationalization"){
			asynchronousValue = false;
		}

		if (!asynchronousValue){
			CW_logger.log("NOTICE","ComwebAjax.sendRequest - url: "+ url + " this url permits to change lang value so set asynchronous request at :" + asynchronousValue );
		}


		/*
		 * create the ajax request (prototype.js) options:
		 * the request method is post, the parameters are set in the post body and are encoded in UTF8
		 * when ajax (prototype.js) have the server response it deliver it to the onRequestComplete method
		 */
		var options = {
			asynchronous:asynchronousValue,
			method:'post',
			encoding:'UTF-8',
			requestHeaders: ['X-Prototype-Version', Prototype.Version ],
			postBody: CW_util.encodeUTF8(queryString),
			onComplete: this._onRequestComplete.bind(options,requestResume,(new Date()).getTime())
		};


		/*
		 * send the ajax request
		 */
		CW_logger.log(CW_logger.LEVEL_INFORMATION,"ComwebAjax.sendRequest launch request - queryString:" + queryString);

		new Ajax.Request(url, options);
	},



	/**
	 * @private
	 * @ignore
	 * @param {RequestResume} requestResume
	 * @param {XMLHttpRequest} xhr
	 */
	_onRequestComplete: function(requestResume,timeInMillis,xhr){
		CW_logger.log(CW_logger.LEVEL_INFORMATION," comwebAjax.onRequestComplete : process the request ("+requestResume.url+ " - "  + requestResume.queryString + ")");

		//get the transaction
		var transaction = CW_comwebAjax.ajaxTransactionManager.getTransaction(requestResume.transactionId);
		//build the url
		var url = requestResume.url + "?" + requestResume.queryString;

		if (xhr.status == 200){
			if (transaction.isValidMD5(requestResume.MD5Sign)){
				if (CW_comwebAjax._processXmlResponse(xhr,requestResume,timeInMillis)){
					//the satus is correct and the xml processing too
					transaction.deleteOlderMD5(requestResume.MD5Sign);

						if (requestResume.historyEnter){

							var curHistory = requestResume.historyName + "/" + requestResume.callback + "/" + requestResume.url + "/" +(requestResume.queryString);
							try{
								CW_logger.log(CW_logger.LEVEL_INFORMATION," comwebAjax.onRequestComplete :  add history url:" + curHistory );
								//	dhtmlHistory.add(curHistory,requestResume);
							}catch(e){
								CW_logger.log(CW_logger.LEVEL_ERROR," comwebAjax.onRequestComplete : cant add history url:" + curHistory + " error:" + e);
							}
						}

				}else{
					CW_logger.log(CW_logger.LEVEL_ERROR," comwebAjax.onRequestComplete : while processing xml response");
					transaction.deleteMD5(requestResume.MD5Sign);
				}
			}else{
				CW_logger.log("NOTICE","the request ("+url+") is not process because, transaction (" + requestResume.transactionId +") indicates that is not valid");
			}
		}else{
			//not 200 status
			transaction.deleteMD5(requestResume.MD5Sign);
			CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.onRequestComplete() error (status:"+xhr.status+") on the given url: <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a> headers:" + xhr.getAllResponseHeaders() );
			return;
		}
	},
	/**
	 * @private
	 * @ignore
	 * @param {XMLHttpRequest} xhr
	 * @param {String} callback
	 * @return {boolean} indicates if the process is corretly executed
	 */
	_processXmlResponse:function(xhr,requestResume,timeInMillis){
		var callback = requestResume.callback;
		var url = requestResume.url;
		var logIndic = "comwebAjax.js: processXmlResponse (callback :"+callback +" ||url:" +url+ ")";
		CW_logger.log(CW_logger.LEVEL_INFORMATION,logIndic);
				var currentTime = (new Date()).getTime();
				//create the xml wrapper
				var docxml;
				var doc;
				try{
					CW_logger.log(CW_logger.LEVEL_INFORMATION,logIndic + " try to load xml");
					if (window.ActiveXObject) {
		                // Code for IE
		                var doc = new ActiveXObject("Microsoft.XMLDOM");

		                doc.async = "false";
		                doc.loadXML(xhr.responseText);
		            } else {
		                // Code for Mozilla, Firefox, Opera, etc.
		                var parser = new DOMParser();
		                var doc = parser.parseFromString(xhr.responseText, "text/xml");
		            }

					docxml = doc.documentElement;
					CW_logger.log(CW_logger.LEVEL_INFORMATION,logIndic + " xml loaded");
					/*var chilNodes = docxml.childNodes ;
					if (chilNodes.item(0).nodeName == "xml"){
						docxml = chilNodes.item(1);
					}*/

				}catch (e){
					CW_logger.log(CW_logger.LEVEL_ERROR,"comwebAjax.(), the file is not xmlValid or can't get chilNodes <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>" + e);
					return false;
				}
				try{
					var nodeName = docxml.nodeName  ;
					var comwebBean = null;
					try{
						comwebBean = eval("new ComwebBean_" + nodeName + "();");
						comwebBean.getName();
					}catch(e){
						CW_logger.log(CW_logger.LEVEL_WARNING,"ComwebAjax: can't create the corresponding object: ComwebBean_" + nodeName + ", try to set ComwebBean : " + e);
						try{
							comwebBean = new ComwebBean();
						}catch(e){
							CW_logger.log(CW_logger.LEVEL_ERROR,"ComwebAjax: can't create the corresponding object: ComwebBean :" + e);
							return false;
						}
					}
					try{
						CW_logger.log(CW_logger.LEVEL_INFORMATION,comwebBean.getName() + " parseXml")
						comwebBean.parseXml(docxml);
					}catch(e){
						CW_logger.log(CW_logger.LEVEL_ERROR,"ComwebAjax: the corresponding object can't parseXML: ComwebBean_" + nodeName + " - <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a> :"+ e);
						return false;
					}
					CW_logger.log(CW_logger.LEVEL_COMWEB_AJAX,"do the eval with callback  (" +callback +"), given comwebBean:"+comwebBean.name+" ,  receive file: <a href='javascript:openUrl(\""+url+"\")'>"  +url+ "</a>");
					//alert("CW_config.langId:" +  CW_config.initInternationalization(comwebBean));
					//CW_config.initInternationalization(comwebBean);

					try{
						CW_logger.registerComwebBean(comwebBean,requestResume.callback, requestResume.url + "?" + requestResume.queryString);
					}catch(e){
						//alert("Error register comwebBean:" + e);
					}

					var currentTime2 = (new Date()).getTime();
					eval(callback  + "(comwebBean,requestResume);");


					CW_logger.logTime("_processXmlResponse('"+url+"'), server response:" + (currentTime - timeInMillis) + " ms , xml bean parsing:" + (currentTime - currentTime2) + " ms, display:" + ((new Date()).getTime() - currentTime2) + " ms" );


				}catch (e){
					CW_logger.log(CW_logger.LEVEL_ERROR,"can't realise the eval of the callback :" +callback  +  " : " + CW_util.describeError(e) );
					return false;
				}

			return true;
	},
	/**
	 * @private
	 * @ignore
	 */
	_createQueryString: function( theArgs, offset ) {
      var queryString = ""
      for ( var i = offset ; i < theArgs.length ; i++ ) {
          if ( i != offset )
            queryString += "&";

          var anArg = theArgs[i];

          if ( anArg.name != undefined && anArg.value != undefined ) {
            queryString += anArg.name +  "=" + (anArg.value);
          }
          else {
             var ePos  = anArg.indexOf('=');
             var argName  = anArg.substring( 0, ePos );
             var argValue = anArg.substring( ePos + 1 );
             queryString += argName + "=" + escape(argValue);
          }
      }

      return queryString;
   },


	/**
	 * @ignore
	 *@deprecated
	 */
	sendRequestRefresh : function (url,callback ,historyEntry){
		this.sendRequest(url,callback ,historyEntry,"defuatlIdTransaction");
	}
};

/**
 * object which permits to give static CW_comwebAjax method
 * @type CW_comwebAjax
 * @final
 */
var CW_comwebAjax = new CW_comwebAjax() ;

/**
 * The following function will generate the MD5 signature for the given
 * string. It will be used by the function that performs requests, in
 * order to sign the request parameters. Therefore, this request can be
 * cached and that cache provided to requests targeting the same
 * content.
 */
var MD5 = function (string) {
    function RotateLeft(lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    }

    function AddUnsigned(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }

    function F(x,y,z) { return (x & y) | ((~x) & z); }
    function G(x,y,z) { return (x & z) | (y & (~z)); }
    function H(x,y,z) { return (x ^ y ^ z); }
    function I(x,y,z) { return (y ^ (x | (~z))); }

    function FF(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    }

    function GG(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    }

    function HH(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    }

    function II(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    }

    function ConvertToWordArray(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    }

    function WordToHex(lValue) {
        var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
        }
        return WordToHexValue;
    }

    function Utf8Encode(string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    }

    var x=Array();
    var k,AA,BB,CC,DD,a,b,c,d;
    var S11=7, S12=12, S13=17, S14=22;
    var S21=5, S22=9 , S23=14, S24=20;
    var S31=4, S32=11, S33=16, S34=23;
    var S41=6, S42=10, S43=15, S44=21;

    string = Utf8Encode(string);

    x = ConvertToWordArray(string);

    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

    for (k=0;k<x.length;k+=16) {
        AA=a; BB=b; CC=c; DD=d;
        a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=AddUnsigned(a,AA);
        b=AddUnsigned(b,BB);
        c=AddUnsigned(c,CC);
        d=AddUnsigned(d,DD);
    }

    var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);

    return temp.toLowerCase();
};