// WMXMLMessage.h: interface for the WMXMLMessage class.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// WMXMLMessage class - implementation of XML message classes
// Stores internal representation of parsed XML message for processing.
// Both "encoded" (SOAP encoding only) or "literal" usage supported.
// Both "document" and "rpc" messaging styles are supported.
//  
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WMXMLMESSAGE_H__3E49EA5F_9AA0_4215_B570_BD4FB76A234D__INCLUDED_)
#define AFX_WMXMLMESSAGE_H__3E49EA5F_9AA0_4215_B570_BD4FB76A234D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <comdef.h>
#include "WMSOAPReqDeserializer.h"
#include "WMSOAPRespDeserializer.h"
#include "WMSOAPSerializer.h"
#include "DIMEPayload.h"
#include <set>
using namespace std;

interface Iwmwsdlclient2;

class WMXMLMessageElement
{
public:
	WMXMLMessageElement() {}
	WMXMLMessageElement(const wstring& wstrNamespaceURI,
						const wstring& wstrName,
						const variant_t& varContent);
	WMXMLMessageElement(const wstring& wstrNamespaceURI,
						const wstring& wstrName);
	virtual ~WMXMLMessageElement() {}

	wstring		m_wstrNamespaceURI;
	wstring		m_wstrName;
	_variant_t	m_varContent;
};

class WMSOAPHeaderMsgElement : public WMXMLMessageElement
{
public:
	WMSOAPHeaderMsgElement()
    {
        m_bRcvdInMsg = true;
        m_bMustUnderstand = false;
        m_bRelay = false;
    }
	WMSOAPHeaderMsgElement( const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							const variant_t& varContent,
							bool bMustUnderstand,
							const wstring& wstrActor,
                            bool bRelay,
                            bool bRcvdInMsg = true);
	~WMSOAPHeaderMsgElement() {}

    bool    m_bRcvdInMsg;
	bool	m_bMustUnderstand;
    bool    m_bRelay;
	wstring	m_wstrActor;
};

class WMSOAPHeaderMsgElementLit : public WMXMLMessageElement
{
public:
	WMSOAPHeaderMsgElementLit()
    {
        m_bRcvdInMsg = true;
        m_bMustUnderstand = false;
        m_bRelay = false;
    }
	WMSOAPHeaderMsgElementLit(  const wstring& wstrNamespaceURI,
								const wstring& wstrName,
								const wstring& wstrLiteralXML,
								bool bMustUnderstand,
								const wstring& wstrActor,
                                bool bRelay,
								const wstring& wstrEncodingStyle,
                                bool bRcvdInMsg = true);
	~WMSOAPHeaderMsgElementLit() {}

    bool    m_bRcvdInMsg;
	bool	m_bMustUnderstand;
    bool    m_bRelay;
	wstring	m_wstrActor;
	wstring m_wstrEncodingStyle;
	wstring m_wstrLiteralXML;
};

class WMSOAPBodyElementLit
{
public:
	WMSOAPBodyElementLit() {}
	WMSOAPBodyElementLit(   const wstring& wstrLiteralXML,
							const wstring& wstrEncodingStyle);
	~WMSOAPBodyElementLit() {}

	wstring m_wstrEncodingStyle;
	wstring m_wstrLiteralXML;
};

class WMSOAPParamMsgElement : public WMXMLMessageElement
{
public:
	WMSOAPParamMsgElement() { m_bIsInParam = false; m_bIsOutParam = false; }
	WMSOAPParamMsgElement(  const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							const variant_t& varContent,
							bool m_bIsInParam,
							bool m_bIsOutParam);
	~WMSOAPParamMsgElement() {}

	bool	m_bIsInParam;
	bool	m_bIsOutParam;
};

class WMXMLMessage  
{
public:
	WMXMLMessage();
	WMXMLMessage(char *pszPtr, unsigned long ulLength);
	virtual ~WMXMLMessage();

	void SetBuffer(char *pszPtr, unsigned long ulLength);
	const char *GetBufferPtr() { return m_pszBuffer; }
	unsigned long GetBufferLength() { return m_ulBufLength; }
	void SetRootElement(WMXMLElement *pRoot);
	WMXMLElement *DetachRootElement();

protected:
	// storage for XML
	char *m_pszBuffer;
	unsigned long m_ulBufLength;
	// pointer to root node of message parse tree
	WMXMLElement *m_pRootElement;
};

class WMSOAPMessage : public WMXMLMessage
{
public:
	WMSOAPMessage();
	virtual ~WMSOAPMessage();

	// operations
	bool Initialize(const wstring& wstrServiceName,
					const wstring& wstrPortName,
					const wstring& wstrNodeURI,
					const wstring& wstrSOAPAction,
					const wstring& wstrNextHopURL,
					bool bExplicitTypingEnabled,
                    bool bNodeTypeEnabled,
					IDispatch *pWSDLClient);
	bool Deserialize();
	bool Serialize();
	bool ProcessRPC();
	bool ProcessRPCGet( const wstring& wstrSvcURI,
                        const wstring& wstrExtraPath,
                        const wstring& wstrQueryString);

	// SOAP Fault members
	bool SetSOAPFault(  const wstring& wstrFaultCode,
                        const wstring& wstrFaultCodeNS,
                        const wstring& wstrSubCode,
                        const wstring& wstrSubCodeNS,
						map<wstring, wstring>& mapReasonText,
						const wstring& wstrFaultNode,
						bool bNeedDetail);
	bool SetSOAPFault(  const wstring& wstrFaultCode,
                        const wstring& wstrFaultCodeNS,
						const wstring& wstrFaultString,
						const wstring& wstrFaultNode,
						bool bNeedDetail);
	bool SetSOAPFaultLit(   const wstring& wstrLiteralXML,
							const wstring& wstrEncodingStyle);
	bool IsSOAPFault() { return m_bIsSOAPFault; }
	bool IsLocalFault() { return m_bIsLocalFault; }
	void SetLocalFaultFlag(bool bFlag) { m_bIsLocalFault = bFlag; }
	void ClearSOAPFault();
	const wstring& GetSOAPFaultCode() { return m_wstrFaultCode; }
	const wstring& GetSOAPFaultCodeNS() { return m_wstrFaultCodeNS; }
	const wstring& GetSOAPFaultSubcode() { return m_wstrFaultSubCode; }
	const wstring& GetSOAPFaultSubcodeNS() { return m_wstrFaultSubCodeNS; }
	const wstring& GetSOAPFaultString() { return m_wstrFaultString; }
    map<wstring, wstring>& GetReasonTextMap() { return m_mapReasonText; }
    void AddReasonText(const wstring& wstrText, const wstring& wstrLangId);
	const wstring& GetSOAPFaultNode() { return m_wstrFaultNode; }
	bool GetSOAPFaultNeedDetail() { return m_bFaultNeedDetail; }
	void SetSOAPFaultNeedDetail(bool bValue) { m_bFaultNeedDetail = bValue; }
	void ClearFaultHeaderElems();
	int GetNumFaultHeaderElems() { return m_arrFaultHeaderElems.size(); }
	bool AddFaultHeaderElem(const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							const variant_t& varContent,
							bool bMustUnderstand,
							const wstring& wstrActor,
                            bool bRelay);
    bool GetFirstFaultHeaderElem(WMSOAPHeaderMsgElement **ppElem,
								long& lPosition);
	bool GetNextFaultHeaderElem(WMSOAPHeaderMsgElement **ppElem,
								long& lPosition);
	int GetNumFaultHeaderElemsLit() { return m_arrFaultHeaderElemsLit.size(); }
	bool GetFirstFaultHeaderElemLit(WMSOAPHeaderMsgElementLit **ppElem,
									long& lPosition);
	bool GetNextFaultHeaderElemLit(	WMSOAPHeaderMsgElementLit **ppElem,
									long& lPosition);
	bool AddFaultHeaderElemLit( const wstring& wstrNamespaceURI,
								const wstring& wstrName,
								const wstring& wstrLiteralXML,
								bool bMustUnderstand,
								const wstring& wstrActor,
                                bool bRelay,
								const wstring& wstrEncodingStyle);
	int GetNumFaultDetailElems() { return m_arrFaultDetailElems.size(); }
	void ClearFaultDetailElems();
	bool AddFaultDetailElem(const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							const variant_t& varContent);
	bool GetFirstFaultDetailElem(wstring& wstrNamespaceURI,
								wstring& wstrName,
								variant_t& varContent,
								long& lPosition);
	bool GetNextFaultDetailElem(wstring& wstrNamespaceURI,
								wstring& wstrName,
								variant_t& varContent,
								long& lPosition);
	bool GetFaultDetailElem(const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							variant_t& varContent);

	// SOAP Header entry (SOAP encoded, deserialized)
	void ClearHeaderElems();
	bool CheckMustUnderstand();

	int GetNumHeaderElems() { return m_arrHeaderElements.size(); }
	bool AddHeaderElem( const wstring& wstrNamespaceURI,
						const wstring& wstrName,
						const variant_t& varContent,
						bool bMustUnderstand,
						const wstring& wstrActor,
                        bool bRelay,
                        bool bRcvdInMsg = true);
	bool GetFirstHeaderElem(WMSOAPHeaderMsgElement **ppElem,
							long& lPosition);
	bool GetNextHeaderElem(	WMSOAPHeaderMsgElement **ppElem,
							long& lPosition);
	bool GetHeaderElem(	const wstring& wstrNamespaceURI,
						const wstring& wstrName,
						variant_t& varContent);
	// literal headers
	int GetNumHeaderElemsLit() { return m_arrHeaderElementsLit.size(); }
	bool GetFirstHeaderElemLit( WMSOAPHeaderMsgElementLit **ppElem,
								long& lPosition);
	bool GetNextHeaderElemLit(	WMSOAPHeaderMsgElementLit **ppElem,
								long& lPosition);
	bool AddHeaderElemLit(  const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							const wstring& wstrLiteralXML,
							bool bMustUnderstand,
							const wstring& wstrActor,
                            bool bRelay,
							const wstring& wstrEncodingStyle,
                            bool bRcvdInMsg = true);
	bool GetHeaderElemLit(	const wstring& wstrNamespaceURI,
							const wstring& wstrName,
							wstring& wstrLiteralXML);

	// literal body element
	bool SetBodyElemLit(const wstring& wstrLiteralXML,
						const wstring& wstrEncodingStyle);
	bool GetBodyElemLit(wstring& wstrLiteralXML);

	// SOAP Section 7.1 RPC elements
	int GetNumMethodParams() { return m_arrParamElements.size(); }

	bool AddMethodParam(const wstring& wstrNamespaceURI,
						const wstring& wstrName,
						const variant_t& varContent,
						bool bIsInParam,
						bool bIsOutParam);
	bool GetFirstMethodParam(   wstring& wstrNamespaceURI,
								wstring& wstrName,
								variant_t& varContent,
								bool& bIsInParam,
								bool& bIsOutParam,
								long& lPosition);
	bool GetNextMethodParam(wstring& wstrNamespaceURI,
							wstring& wstrName,
							variant_t& varContent,
							bool& bIsInParam,
							bool& bIsOutParam,
							long& lPosition);
	void ClearMethodParams();
	const wstring& GetMethodNS() { return m_wstrMethodNS; }
	void SetMethodNS(const wstring& wstrNS) { m_wstrMethodNS = wstrNS; }
	const wstring& GetMethodName() { return m_wstrMethodName; }
	void SetMethodName(const wstring& wstrName);
	_variant_t& GetReturnValue();
	void SetReturnValue(variant_t& varValue);
	void SetReturnValue(VARIANT varValue);
	void SetRetValName(const wstring& wstrName) { m_wstrRetValName = wstrName; }
	const wstring& GetRetValName() { return m_wstrRetValName; }
	bool ExplicitTypingEnabled() { return m_bExplicitTypingEnabled; }
    bool NodeTypeEnabled() { return m_bNodeTypeEnabled; }

	// SOAPAction HTTP Header
	const wstring& GetSOAPAction() { return m_wstrSOAPAction; }
    void SetSOAPAction(const wstring& wstrSOAPAction) { m_wstrSOAPAction = wstrSOAPAction; }

	// WSDL service info
	const wstring& GetServiceName() { return m_wstrServiceName; }
	const wstring& GetPortName() { return m_wstrPortName; }
	bool GetPortAddress(wstring& wstrAddress);

	// Node URI
	const wstring& GetNodeURI() { return m_wstrNodeURI; }
	void SetNodeURI(const wstring& wstrURI) { m_wstrNodeURI = wstrURI; }

    // Roles
    bool SetRoles(list<wstring>& listRoles);
    bool GetRoles(list<wstring>& listRoles);

    // MU header blocks
    bool GetMUHeaderBlocks( list<wstring>& listNamespaces,
                            list<wstring>& listLocalNames);

	// Message phase
	bool IsRequestPhase() { return m_bIsRequestPhase; }
	void SetRequestPhase(bool bFlag) { m_bIsRequestPhase = bFlag; }
	// Next hop URL
	const wstring& GetNextHopURL() { return m_wstrNextHopURL; }
	void SetNextHopURL(const wstring& wstrURL) { m_wstrNextHopURL = wstrURL; }
	bool IsIntermediary() { return (m_wstrNextHopURL.empty() == false); }
	// Message binding style (doc or rpc)
	bool IsRPCStyle();
	// No Content acessors
	bool IsNoContentResponse() { return m_bNoContent; }
	void SetNoContentResponse(bool bValue) { m_bNoContent = bValue; }

	// DIME attachements
	bool AddDIMEAttachmentReq(  const wstring& wstrId,
								const wstring& wstrType,
								long lTNF,
								IUnknown *pIUnknown,
								SAFEARRAY *pOptions = NULL);
	bool AddDIMEAttachmentResp( const wstring& wstrId,
								const wstring& wstrType,
								long lTNF,
								IUnknown *pIUnknown,
								SAFEARRAY *pOptions = NULL);
	bool GetFirstDIMEAttachmentReq( wstring& wstrId,
									wstring& wstrType,
									long& lTNF,
									IUnknown **ppIUnknown,
									SAFEARRAY **ppOptions,
									long& lPosition);
	bool GetNextDIMEAttachmentReq(  wstring& wstrId,
									wstring& wstrType,
									long& lTNF,
									IUnknown **ppIUnknown,
									SAFEARRAY **ppOptions,
									long& lPosition);
	bool GetDIMEAttachmentReq(  const wstring& wstrId,
								wstring& wstrType,
								long& lTNF,
								IUnknown **ppIUnknown,
								SAFEARRAY **ppOptions = NULL);
	bool GetFirstDIMEAttachmentResp(wstring& wstrId,
									wstring& wstrType,
									long& lTNF,
									IUnknown **ppIUnknown,
									SAFEARRAY **ppOptions,
									long& lPosition);
	bool GetNextDIMEAttachmentResp( wstring& wstrId,
									wstring& wstrType,
									long& lTNF,
									IUnknown **ppIUnknown,
									SAFEARRAY **ppOptions,
									long& lPosition);
	bool GetDIMEAttachmentResp( const wstring& wstrId,
								wstring& wstrType,
								long& lTNF,
								IUnknown **ppIUnknown,
								SAFEARRAY **ppOptions = NULL);
	long GetNumReqAttachments();
	long GetNumRespAttachments();
	void ClearAttachments();

    // SOAP version
    int GetSOAPVersion() { return m_nSOAPVersion; }
    void SetSOAPVersion(int nVersion) { m_nSOAPVersion = nVersion; }

    // deserializers
    WMSOAPReqDeserializer& GetReqDeserializer() { return m_ReqDeserializer; }
    WMSOAPRespDeserializer& GetRespDeserializer() {	return m_RespDeserializer; }


private:

    // SOAP version
    int                                 m_nSOAPVersion;

	// header
	vector<WMSOAPHeaderMsgElement *>	m_arrHeaderElements;
	vector<WMSOAPHeaderMsgElementLit *>	m_arrHeaderElementsLit;

	// literal body
	WMSOAPBodyElementLit				*m_pBodyElementLit;

	// method
	vector<WMSOAPParamMsgElement *>		m_arrParamElements;
	_variant_t							m_varReturn;
	wstring								m_wstrRetValName;
	wstring								m_wstrMethodNS;
	wstring								m_wstrMethodName;
	wstring								m_wstrSOAPAction;

	// SOAP fault handler
	wstring								m_wstrFaultCode;
	wstring								m_wstrFaultCodeNS;
	wstring								m_wstrFaultSubCode;
	wstring								m_wstrFaultSubCodeNS;
	wstring								m_wstrFaultString;
	wstring								m_wstrFaultNode;
    map<wstring, wstring>               m_mapReasonText;
	bool								m_bFaultNeedDetail;
	bool								m_bIsSOAPFault;
	bool								m_bIsLocalFault;
	vector<WMXMLMessageElement *>		m_arrFaultDetailElems;
	vector<WMSOAPHeaderMsgElement *>	m_arrFaultHeaderElems;
	vector<WMSOAPHeaderMsgElementLit *>	m_arrFaultHeaderElemsLit;

	// serializer, deserializer
	WMSOAPReqDeserializer				m_ReqDeserializer;
	WMSOAPRespDeserializer				m_RespDeserializer;
	WMSOAPSerializer					m_Serializer;

	// DIME attachments
	vector<DIMEPayload *>				m_arrAttachmentsReq;
	vector<DIMEPayload *>				m_arrAttachmentsResp;

	// no content flag
	bool								m_bNoContent;

	// put xsi:type attributes into element tags when serializing?
	bool								m_bExplicitTypingEnabled;
	bool								m_bNodeTypeEnabled;

	// the WSDL client
	Iwmwsdlclient2						*m_pIWSDLClient;

	// WSDL service info
	wstring								m_wstrServiceName;
	wstring								m_wstrPortName;

	// next hop URL
	wstring								m_wstrNextHopURL;

    // node URI
    wstring                             m_wstrNodeURI;

	// message phase (request | response)
	bool								m_bIsRequestPhase;

    // roles
    set<wstring>                        m_setRoles;
};

#endif // !defined(AFX_WMXMLMESSAGE_H__3E49EA5F_9AA0_4215_B570_BD4FB76A234D__INCLUDED_)
