/****************************************************************
** Licensed Materials - Property of IBM
**
** IBM Cognos Products: mdsrv
**
** (C) Copyright IBM Corp. 2008, 2010
**
** US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*****************************************************************/
/**
 * This class allows for the sending of an async request to the Cognos BI Bus.
 *
 * @constructor
 * @extends C_SoapRequest
 * @extends I_ServerPromptingListener
 * @extends I_ServerLogonListener
 * @requires G_BusServer
 * @requires C_Error
 * @param {I_RequestListener} v_oListener The listener for this request. If null, then no events will be fired.
 * @param {String} v_sSOAPAction SOAP action to set in the request header
 * @param {String} v_sRequest Request to send in SOAP body
 */
function C_mdsrvBusRequest( v_oListener, v_sSOAPAction, v_sRequest )
{
	this.F_ConstructBaseClass( v_oListener, G_CCHL.M_sGatewayURL, v_sSOAPAction );

	/**
	 * @private
	 */
	this.m_sRequest = v_sRequest;
	/**
	 * @private
	 */
	this.m_sRequestSoapAction = v_sSOAPAction;
	/**
	 * @private
	 */
	this.m_docResponse = null;
	/**
	 * @private
	 */
	this.m_bProcessResponse = true;
	/**
	 * @private
	 */
	this.m_bServerPrompting = true;
	/**
	 * @private
	 */
	this.m_sPromptReport = "";
	/**
	 * @private
	 */
	this.m_bAsyncBusRequest = false;
	/**
	 * @private
	 */
	this.m_sRoutingServerGroup = null;
		
	/**
	 * @private
	 */
	this.m_bIsLoggingOn = false;
	/**
	 * @private
	 */
	this.m_bIsPrompting = false;
	
	/**
	 * @private
	 */
	this.m_sFollowOnRequestSOAPAction = C_mdsrvBusRequest.K_sSOAPAction_metadataService_absolute;
	/**
	 * @private
	 */
	this.m_sCancelRequestSOAPAction = C_mdsrvBusRequest.K_sSOAPAction_metadataService_control;
	
	/**
	 * @private
	 */
	this.m_aNamespaces = [];
	this.F_AddNamespace( C_mdsrvBusRequest.k_sBIBusNamespaceDecl );
	this.F_AddNamespace( C_mdsrvBusRequest.k_sBIBusMDNamespaceDecl );
};

C_mdsrvBusRequest.F_Extends( C_SoapRequest );

/**
 * Primary Wait Threshold to use for async requests
 * @type Integer
 */
C_mdsrvBusRequest.K_sPrimaryWaitThreshold = 50;
/**
 * Secondary Wait Threshold to use for async requests
 * @type Integer
 */
C_mdsrvBusRequest.K_sSecondaryWaitThreshold = 30;

/**
 * @private
 */
C_mdsrvBusRequest.m_sLastRequest = "";
/**
 * @private
 */
C_mdsrvBusRequest.m_sLastResponse = "";

/**
 * Holds the available bus tracking info available for a new request. Only one request at a
 * time can be using a given bus:tracking
 *
 * @private
 */
C_mdsrvBusRequest.m_aBusTracking = [];

/**
 * @returns The last SOAP request sent to the server.
 * @type String
 */
C_mdsrvBusRequest.F_GetLastRequest = function()
{
	return this.m_sLastRequest;
};

/**
 * @returns The last SOAP response returned by the server.
 * @type XMLDocument
 */
C_mdsrvBusRequest.F_GetLastResponse = function()
{
	return this.m_sLastResponse;
};

/**
 * Releases all current conversations being maintained with the server thereby allowing the server
 * to free the resources asssociated with them.
 * @type void
 */
C_mdsrvBusRequest.F_ReleaseAllTracking = function()
{
	// This method will only release reportService conversations. A more general approach will be 
	// needed in the future to release the requests associated with each service.
	// We will need to have global objects to manage the requests RS makes to each service so that the 
	// conversations, and async activity can be managed properly.
	// I have logged " 593994 0 BUS requests are not managed properly" to track this
	
	var v_iRequests = this.m_aBusTracking.length;

	var v_sReleaseRequest =
		"<rns1:release>" +
			'<bus:conversation xsi:type="bus:asynchRequest">' +
			'</bus:conversation>' +
		"</rns1:release>";

	// release each bus request being maintained	
	for (var i = 0; i < v_iRequests; ++i)
	{
		var v_oReleaseRequest = new C_mdsrvBusRequest( null, C_mdsrvBusRequest.K_sSOAPAction_metadataService_control, v_sReleaseRequest );

		// Requests must be synchronous because they typically happen when the browser is shutting down. We abort all active requests when
		// shutting down the browser to ensure it goes down cleanly, so if these requests are async, they will be aborted before the server
		// gets them.
		v_oReleaseRequest.m_bAsync = false;

		v_oReleaseRequest.F_Send();
	}
};

/**
 * @returns The request SOAP response
 * @type XMLDocument
 */
C_mdsrvBusRequest.prototype.F_GetResponse = function()
{
	return this.m_docResponse;
};

/**
 * @returns True if the prompt window is up
 * @type Boolean
 */
C_mdsrvBusRequest.prototype.F_IsPrompting = function()
{
	return this.m_bIsPrompting;
};

/**
 * @returns True if the logon window is up
 * @type Boolean
 */
C_mdsrvBusRequest.prototype.F_IsLoggingOn = function()
{
	return this.m_bIsLoggingOn;
};

/**
 * Overrides the default CCHL locales for this request.
 * @param {String} v_sProductLocale Product locale.
 * @param {String} v_sContentLocale Content locale.
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetLocale = function(v_sProductLocale, v_sContentLocale)
{
	this.m_sProductLocale = v_sProductLocale;
	this.m_sContentLocale = v_sContentLocale;
};

/**
 * The response for the request will not be processed and checked for any errors or server interaction
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetNoResponseProcessing = function()
{
	this.m_bProcessResponse = false;
};

/**
 * Sets the request to not do server prompting.
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetNoServerPrompting = function()
{
	this.m_bServerPrompting = false;
};

/**
 * Sets the routing server group to use for this request.
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetRoutingServerGroup = function(v_sRoutingServerGroup)
{
	this.m_sRoutingServerGroup = v_sRoutingServerGroup;
};

/**
 * Sets the request to follow the BI Bus asynchronous mechanism
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetAsyncBusRequest = function(v_sWaitMethod, v_sCancelMethod, v_sGetOutputMethod, v_sFollowOnRequestSOAPAction, v_sCancelRequestSOAPAction)
{
	this.m_bAsyncBusRequest = true;
	this.m_sWaitMethod = v_sWaitMethod;
	this.m_sCancelMethod = v_sCancelMethod;
	this.m_sGetOutputMethod = v_sGetOutputMethod;
	this.m_sFollowOnRequestSOAPAction = v_sFollowOnRequestSOAPAction ? v_sFollowOnRequestSOAPAction : this.m_sFollowOnRequestSOAPAction;
	this.m_sCancelRequestSOAPAction = v_sCancelRequestSOAPAction ? v_sCancelRequestSOAPAction : this.m_sCancelRequestSOAPAction;
};

/**
 * @param {String} v_sPromptReport
 * @type void
 */
C_mdsrvBusRequest.prototype.F_SetPromptReport = function( v_sPromptReport )
{
	this.m_sPromptReport = v_sPromptReport;
};

/**
 * Creates an object context that can be used for a request.
 * @returns A context object that can be used for a request. The content object contains an m_eType attribute.
 * @type Object
 */
C_mdsrvBusRequest.F_CreateContext = function(v_eType)
{
	var v_oContext = {};
	v_oContext.m_eType = v_eType;
	return v_oContext;
};

/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_metadataService_high = "http://developer.cognos.com/schemas/metadataService/3.high";
/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_metadataService_absolute = "http://developer.cognos.com/schemas/metadataService/3.absolute";
/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_metadataService_session = "http://developer.cognos.com/schemas/metadataService/3.session";
/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_metadataService_control = "http://developer.cognos.com/schemas/metadataService/3.session";
/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_contentManagerService = "http://developer.cognos.com/schemas/bibus/3#contentManagerService";
//Based on FM Caspian RTC task 231966: MDSRV-SOAP ACTIONS - must amend for Planning bridging,
//SOAP requests sent to Content Manager must look like this:  http://www.ibm.com/xmlns/prod/cognos/contentManagerService/201109/.
//So this C_mdsrvBusRequest.K_sSOAPAction_contentManagerService value has been out of date. 
//While global search shows it is used nowhere in mdsrv client. We should consider about remove this variable safely.     
/**
 * @type String
 */
C_mdsrvBusRequest.K_sSOAPAction_systemService = "http://developer.cognos.com/schemas/bibus/3#systemService";

C_mdsrvBusRequest.K_sSOAPAction_metadataService = "http://developer.cognos.com/schemas/bibus/3#metadataService";

/**
 * @private
 */
C_mdsrvBusRequest.k_sBIBusNamespace = "http://developer.cognos.com/schemas/bibus/3";
/**
 * @private
 */
C_mdsrvBusRequest.k_sBIBusNamespaceDecl = "xmlns:bus='" + C_mdsrvBusRequest.k_sBIBusNamespace + "/'";
/**
 * @private
 */
C_mdsrvBusRequest.k_sBIBusMDNamespaceDecl = "xmlns:md1='http://developer.cognos.com/schemas/metadataService/3'";


/**
 * @param {String} v_sNamespace
 * @type void
 */
C_mdsrvBusRequest.prototype.F_AddNamespace = function( v_sNamespace )
{
	this.m_aNamespaces.push( v_sNamespace );
};

/**
 * @type void
 */
C_mdsrvBusRequest.prototype.F_Send = function()
{
	this.f_sendSoapRequest(
		this.f_createSoapRequest( this.m_sRequest, this.m_sProductLocale, this.m_sContentLocale ),
		this.m_sRequestSoapAction);
};

/**
 * @private
 */
C_mdsrvBusRequest.prototype.f_sendSoapRequest = function(v_sSoapRequest, v_sSoapAction)
{
	C_mdsrvBusRequest.m_sLastRequest = v_sSoapRequest;
	C_mdsrvBusRequest.m_sLastResponse = "";
	this.F_SetSoapAction(v_sSoapAction);
	this.F_SetRequestBody(v_sSoapRequest);
	C_mdsrvBusRequest.superClass.F_Send.call( this );
};

/**
 * @protected
 */
C_mdsrvBusRequest.prototype.F_IsReadyToProcess = function()
{
	if ( !C_mdsrvBusRequest.superClass.F_IsReadyToProcess.call( this ) )
	{
		return false;
	}

	delete this.m_oFollowOnState;
	
	// Check if any errors happened in the web request.
	if ( this.F_GetError() )
	{
		// allow the request to continue processing
		return !this.m_bPendingAbort;
	}
	
	var v_sResponseText = this.F_GetResponseText();
	var v_docResponse = U_XML.F_LoadString( null, v_sResponseText, false, true );
	this.m_docResponse = v_docResponse;
	
	if ( !v_docResponse || !v_docResponse.documentElement)
	{
		return !this.m_bPendingAbort;
	}

	this.m_docResponse.setProperty( "SelectionNamespaces", "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " + this.m_aNamespaces.join( " " ) );

	C_mdsrvBusRequest.m_sLastResponse = v_docResponse.xml;

	var v_nFault = v_docResponse.selectSingleNode( '/SOAP-ENV:Envelope/SOAP-ENV:Body/SOAP-ENV:Fault' );

	if ( v_nFault && !this.m_bPendingAbort )
	{
		if (this.m_bServerPrompting && this.m_oListener && G_BusServer.F_AuthenticationRequired(v_docResponse))
		{
			this.m_bLoggingOn = true;
				
			//G_App.F_ShowXMLTree( v_docResponse, "Logon prompt response" );
			
			if (G_BusServer.F_Logon(this, v_docResponse))
			{
				// Depending on what happens after logon, either the request will be completed (failed)
				// or it will be re-executed
				
				delete this.m_docResponse;
				return false;
			}
			this.m_bLoggingOn = false;
			this.F_SetNewErrorRes( "IDS_CCHL_INITIATE_LOGON_FAILED" );
		}

		return true;
	}

	var v_nBusTracking = v_docResponse.selectSingleNode('/SOAP-ENV:Envelope/SOAP-ENV:Header/bus:biBusHeader/bus:tracking');
	
	if (v_nBusTracking)
	{
		var v_sBusTracking = v_nBusTracking.xml;
		
		if (this.m_bPendingAbort)
		{
			this.m_bPendingAbort = false;
			var v_bCancellable = (v_docResponse.selectSingleNode( "/SOAP-ENV:Envelope/SOAP-ENV:Body/*/bus:result[bus:status='working' or bus:status='stillWorking']" ) != null);
			this.m_oFollowOnState = this.f_createFollowOnState(v_docResponse, v_sBusTracking, v_bCancellable);
			this.F_Abort();
			return false;
		}
		
		// If there were no errors, then we can reuse the tracking
		// Make tracking available for resuse in subsequent requests.
		// If this request resubmits itself, then it should reuse the same tracking because it will be at the
		// top of the queue.
		C_mdsrvBusRequest.m_aBusTracking.push(v_sBusTracking);

		// An async method requires tracking to work correctly
 		if (this.m_bAsyncBusRequest)
 		{
 			if (v_docResponse.selectSingleNode( "/SOAP-ENV:Envelope/SOAP-ENV:Body/*/bus:result[bus:status='complete'][bus:details/item/bus:status='responseReady']" ) )
 			{
 				delete this.m_docResponse;
 				this.f_sendFollowOnRequest(this.m_sGetOutputMethod, v_docResponse, v_sBusTracking, false);
 				return false;
 			}
 			else if (v_docResponse.selectSingleNode( "/SOAP-ENV:Envelope/SOAP-ENV:Body/*/bus:result[bus:status='working' or bus:status='stillWorking']" ) )
 			{
				delete this.m_docResponse;
 				this.f_sendFollowOnRequest(this.m_sWaitMethod, v_docResponse, v_sBusTracking, true);
 				return false;
 			}
 		}
 	}

	if (this.m_bPendingAbort)
	{
		// If the bus:tracking info is missing, then it is not possible to cancel this on the server
		this.f_forcePendingAbortOnClient();
		return false;
	}

	if (this.m_bServerPrompting && this.m_oListener && G_BusServer.F_RequiresServerPrompting(v_docResponse))
	{
		this.m_bIsPrompting = true;
		if (G_BusServer.F_DoPrompting(this, v_docResponse, this.m_sPromptReport))
		{
			// Depending on what happens after prompting, either the request will be completed (failed)
			// or it will be re-executed
			
			delete this.m_docResponse;
			return false;
		}
		this.m_bIsPrompting = false;
		this.F_SetNewErrorRes( "IDS_CCHL_INITIATE_SERVERPROMTING_FAILED" );
		return true;
	}
	
	return true;
};

/**
 * @protected
 */
C_mdsrvBusRequest.prototype.F_ProcessResponse = function()
{
	C_mdsrvBusRequest.superClass.F_ProcessResponse.call( this );

	if ( this.F_GetError() )
	{
		this.m_docResponse = null;
		return;
	}
	
	if (this.m_docResponse && this.m_docResponse.documentElement)
	{
		var v_nFault = this.m_docResponse.selectSingleNode( '/SOAP-ENV:Envelope/SOAP-ENV:Body/SOAP-ENV:Fault' );
	
		if ( v_nFault )
		{
			this.F_SetError( new C_BusSoapFault( this.m_docResponse ) );
			this.m_docResponse = null;
		}
	}
	else
	{
		var v_aMsg = [];
		var v_sResponseText = this.F_GetResponseText();
		
		if ( v_sResponseText )
		{
			v_aMsg.push( v_sResponseText );
		}
		else
		{
			v_aMsg.push(G_ResManager.F_GetString( "IDS_CCHL_HTTP_UNKNOWN_RESPONSE"));
			v_aMsg.push("\r\n");
			// These strings are hard coded, they are a last resort when there are problems.
			v_aMsg.push("Gateway  URL: " + G_CCHL.M_sGatewayURL);
			v_aMsg.push("Document URL: " + document.URL);

			var v_sStatusText = this.F_GetStatusText();
			if ( v_sStatusText )
			{
				v_aMsg.push("HTTP Status Text: " + v_sStatusText);
			}
		}

		this.m_docResponse = null;
		this.F_SetNewErrorRes( "IDS_CCHL_XMLHTTPERROR", v_aMsg.join( "\r\n" ) );
	}	
};

/**
 * @protected
 */
C_mdsrvBusRequest.prototype.f_sendFollowOnRequest = function(v_sMethod, v_docResponse, v_sBusTracking, v_bCancellable)
{
	G_Debug.F_Print("C_mdsrvBusRequest.f_sendFollowOnRequest : " + v_sMethod);
	this.m_oFollowOnState = this.f_createFollowOnState(v_docResponse, v_sBusTracking, v_bCancellable);

	var v_sRequest =
		"<" + v_sMethod + ">" +
			'<bus:conversation xsi:type="bus:asynchRequest">' +
				this.m_oFollowOnState.m_sConversation +
			'</bus:conversation>' +
			'<bus:parameterValues SOAP-ENC:arrayType="bus:parameterValue[]" xsi:type="SOAP-ENC:Array"/>' +
			'<bus:options SOAP-ENC:arrayType="bus:option[]" xsi:type="SOAP-ENC:Array"/>' +
		"</" + v_sMethod + ">";
	
	this.f_sendSoapRequest(this.f_createSoapRequest( v_sRequest, this.m_sProductLocale, this.m_sContentLocale ), this.m_sFollowOnRequestSOAPAction);
};

/**
 * Abort the current request.
 * @type void
 */
C_mdsrvBusRequest.prototype.F_Abort = function()
{
	if (this.m_bAsyncBusRequest && !this.m_oFollowOnState && !this.m_bCompleted)
	{
		G_Debug.F_Print("C_mdsrvBusRequest pending abort");

		/**
		* @private
		*/
		this.m_bPendingAbort = true;
		
		// Force pending abort on the client after 10 seconds
		var v_oRequest = this;
		setTimeout(function() { v_oRequest.f_forcePendingAbortOnClient() }, 10000);
		
		if ( this.m_oListener && this.m_oListener.F_Request_OnAborted )
		{
			this.m_oListener.F_Request_OnAborted( this );
		}
		
		return;
	}
	
	C_mdsrvBusRequest.superClass.F_Abort.call( this );

	if (this.m_oFollowOnState && this.m_oFollowOnState.m_bCancellable)
	{
		this.f_cancelRequest();
	}
};

/**
 * @private
 * This method forces the client to abort the request. This is done to ensure that the browser client connections
 * do not get locked up waiting for a server response for cancel.
 */
C_mdsrvBusRequest.prototype.f_forcePendingAbortOnClient = function()
{
	if (this.m_bPendingAbort)
	{
		G_Debug.F_Print("C_mdsrvBusRequest pending abort forced on client");
		this.m_bCompleted = true; // ensures F_Abort does not fire the OnAbort event since it has already been fired.
		this.m_bPendingAbort = false;
		C_mdsrvBusRequest.superClass.F_Abort.call( this );
	}
};

/**
 * @private
 */
C_mdsrvBusRequest.prototype.f_createFollowOnState = function(v_docResponse, v_sBusTracking, v_bCancellable)
{
	var v_aConversation = [];
	
	var nl = v_docResponse.selectNodes( "/SOAP-ENV:Envelope/SOAP-ENV:Body/*/bus:result/bus:primaryRequest/*" );
	for ( var i = 0; i < nl.length; i++ )
	{
		v_aConversation.push(nl.item( i ).xml);
	}
	
	var v_sConversation = v_aConversation.join("");
	
	var v_oCancelState =
	{
		"m_sConversation" : v_sConversation,
		"m_sBusTracking" : v_sBusTracking,
		"m_bCancellable" : v_bCancellable
	};
	
	return v_oCancelState;
};

/**
 * @private
 */
C_mdsrvBusRequest.prototype.f_cancelRequest = function()
{
	G_Debug.F_Print("C_mdsrvBusRequest cancelling request on server");
	var v_sCancelConversation = this.m_oFollowOnState.m_sConversation;
	var v_sCancelBusTracking = this.m_oFollowOnState.m_sBusTracking;
	delete this.m_oFollowOnState;

	C_mdsrvBusRequest.m_aBusTracking.push(v_sCancelBusTracking);
	
	var v_sCancelRequest =
		"<" + this.m_sCancelMethod + ">" +
			'<bus:conversation xsi:type="bus:asynchRequest">' +
				v_sCancelConversation +
			'</bus:conversation>' +
		"</" + this.m_sCancelMethod + ">";

	var v_oCancelRequest = new C_mdsrvBusRequest( null, this.m_sCancelRequestSOAPAction, v_sCancelRequest );
	v_oCancelRequest.F_Send();
};

/**
 * @param {Boolean} v_bSuccess
 * @type void
 */
C_mdsrvBusRequest.prototype.F_OnServerLogonComplete = function(v_bSuccess)
{
	this.m_bIsLoggingOn = false;
	// if logon successful
	if (G_BusServer.F_GetPassport() && v_bSuccess )
	{
		this.F_Send();
		return;
	}
	
	this.F_SetNewErrorRes( "IDS_CCHL_REQUEST_CANCELLED_LOGON" );
	this.m_docResponse = null;
	this.m_oListener.F_Request_OnComplete(this);
};

/**
 * @type void
 */
C_mdsrvBusRequest.prototype.F_OnServerPromptingComplete = function()
{

	this.m_bIsPrompting = false;
	// if prompting was successful
	if (G_BusServer.F_HasParameterValues())
	{
		// take existing request and replace parameters with the new ones
		var v_sRequest = this.m_sRequest;
		var v_idxStartParams = v_sRequest.indexOf( "<bus:parameterValues" );
		var v_idxEndParams = v_sRequest.indexOf("</bus:parameterValues>" );
		if ( v_idxStartParams != - 1 && v_idxEndParams != -1 )
		{
			v_sRequest = v_sRequest.substring(0, v_idxStartParams) + G_BusServer.F_GetParameterValues() + v_sRequest.substring(v_idxEndParams + 22);
		}
		else if ( v_idxStartParams != - 1 && v_idxEndParams == -1 )
		{
			v_sParamsStart = v_sRequest.slice( v_idxStartParams );
			v_idxEndParams = v_sParamsStart.indexOf( "/>" );
			v_sRequest = v_sRequest.substring(0, v_idxStartParams) + G_BusServer.F_GetParameterValues() + v_sRequest.substring(v_idxStartParams + v_idxEndParams + 2);
		}
		else
		{
			G_Debug.F_Alert('Could not replace params in request');
		}
		this.m_sRequest = v_sRequest;
		this.F_Send();
		return;
	}

	this.F_SetNewErrorRes( "IDS_CCHL_REQUEST_CANCELLED_PROMPTING" );
	this.m_docResponse = null;
	this.m_oListener.F_Request_OnComplete(this);

};

/**
 * @private
 */
C_mdsrvBusRequest.prototype.f_createSoapRequest = function( v_sRequest, v_sProductLocale, v_sContentLocale )
{
	var v_sPassport = G_BusServer.F_GetPassport();
	var v_sRouterServerGroup = (this.m_sRoutingServerGroup === null) ? G_BusServer.F_GetRoutingServerGroup() : this.m_sRoutingServerGroup;
	var v_sCafContextId = G_BusServer.F_GetCafContextId();
	
	var v_sBusTracking = (C_mdsrvBusRequest.m_aBusTracking.length > 0) ? C_mdsrvBusRequest.m_aBusTracking.pop() : "";
	
	var v_sSOAPRequest =
	'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" ' + this.m_aNamespaces.join( " " ) + '>' +
		'<SOAP-ENV:Header>' +
			'<bus:biBusHeader xsi:type="bus:biBusHeader">' +
				(
					v_sPassport ?
					('<bus:CAM xsi:type="bus:CAM">' +
						'<CAMPassport xsi:type="bus:CAMPassport">' +
							'<id xsi:type="xsd:string">' + 
								v_sPassport + 
							'</id>' +
						'</CAMPassport>' +
						'<authenticityToken xsi:type="xsd:base64Binary">' +
							G_BusServer.F_GetAuthenticityToken() +
						'</authenticityToken>' +
					'</bus:CAM>') : ''
				) +
				(
					v_sCafContextId ?
					('<bus:CAF xsi:type="bus:CAF">' +
						'<contextID xsi:type="xsd:string">' + 
							v_sCafContextId +
						'</contextID>' +
					'</bus:CAF>') : ''
				) +
				'<bus:userPreferenceVars SOAP-ENC:arrayType="bus:userPreferenceVar[]" xsi:type="SOAP-ENC:Array">' +
					'<item>' +
						'<bus:name xsi:type="xsd:string">productLocale</bus:name>' +
						'<bus:value xsi:type="xsd:string">' +
							(v_sProductLocale ? v_sProductLocale : G_CCHL.M_sProductLocale) +
						'</bus:value>' +
					'</item>' +
					'<item>' +
						'<bus:name xsi:type="xsd:string">contentLocale</bus:name>' +
						'<bus:value xsi:type="xsd:string">' +
							(v_sContentLocale ? v_sContentLocale : G_CCHL.M_sContentLocale) +
						'</bus:value>' +
					'</item>' +
				'</bus:userPreferenceVars>' +
   				'<bus:dispatcherTransportVars xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="bus:dispatcherTransportVar[]">' +
   					'<item xsi:type="bus:dispatcherTransportVar">' +
   						'<name xsi:type="xsd:string">md</name>' +
   						'<value xsi:type="xsd:string">true</value>' +
   					'</item>' +
   				'</bus:dispatcherTransportVars>' +
   				v_sBusTracking +
				(
					v_sRouterServerGroup ?
					('<bus:routing xsi:type="bus:routingInfo">' +
						'<routingServerGroup xsi:type="xsd:string">' +
							v_sRouterServerGroup + 
						'</routingServerGroup>' +
					'</bus:routing>') : ''
				) +
			'</bus:biBusHeader>' +
		'</SOAP-ENV:Header>' +
		'<SOAP-ENV:Body>' +
			v_sRequest +
		'</SOAP-ENV:Body>' +
	'</SOAP-ENV:Envelope>';

	return v_sSOAPRequest;
};

/**
 * This class is used to capture the error contained in a BUS SOAP fault.
 *
 * @constructor
 * @extends I_Error
 * @param {XMLDocument} v_docSoapResponse
 */
function C_BusSoapFault(v_docSoapResponse)
{
	/**
	* @private
	*/
	this.m_sErrorSummary = "";
	/**
	* @private
	*/
	this.m_sErrorDetails = "";
	/**
	* @private
	*/
	this.m_sErrorCode = "";

	v_docSoapResponse.setProperty( "SelectionNamespaces", "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + C_mdsrvBusRequest.k_sBIBusNamespaceDecl );

	// Search the document since this class is also used for documents that are not
	// complete SOAP responses.
	var v_nFault = v_docSoapResponse.selectSingleNode('//SOAP-ENV:Fault');
	
	var nl = v_nFault.selectNodes(".//bus:messageString | .//messageString | .//bus:message[not(*)] | .//message[not(*)]");
	
	if (nl.length > 0)
	{
		var v_sMsg = nl.item(0).text;
		var i = v_sMsg.indexOf(" ");
		
		this.m_sErrorSummary = ( i > 0 ) ? v_sMsg.substring( i + 1 ) : v_sMsg;
		this.m_sErrorCode = ( i > 0 ) ? v_sMsg.substring( 0, i ) : "";
		
		var v_aDetails = [];
		
		for (var j = 1; j < nl.length; ++j)
		{
			v_aDetails.push(nl.item(j).text);
		}
		
		this.m_sErrorDetails = v_aDetails.join("\r\n");
	}
	else
	{
		var v_nFaultString = v_nFault.selectSingleNode("faultstring | SOAP-ENV:faultstring");
		
		if (v_nFaultString)
		{
			this.m_sErrorSummary = v_nFaultString.text;
		}

		var v_nFaultCode = v_nFault.selectSingleNode("faultcode | SOAP-ENV:faultcode");
		
		if (v_nFaultCode)
		{
			this.m_sErrorCode = v_nFaultCode.text;
		}
	}
	
	if (!this.m_sErrorSummary)
	{
		this.m_sErrorSummary = G_ResManager.F_GetString("IDS_CCHL_UNRECOGNIZED_SOAP_FAULT");
		this.m_sErrorDetails = v_nFault.xml;
	}
};

/**
 * @type String
 */
C_BusSoapFault.prototype.F_GetErrorSummary = function()
{
	return this.m_sErrorSummary;
};

/**
 * @type String
 */
C_BusSoapFault.prototype.F_GetErrorDetails = function()
{
	return this.m_sErrorDetails;
};

/**
 * @type String
 */
C_BusSoapFault.prototype.F_GetErrorCode = function()
{
	return this.m_sErrorCode;
};