// interopsvcdocObj.cpp : Implementation of CinteropsvcdocObj

#include "stdafx.h"
#include "interopsvcdocObj.h"

// CinteropsvcdocObj

#include "..\soap_source\xmlparser.h"
#include "..\soap_source\soap.h"
#include "..\wmsoapmsg\wmsoapmsg_i.c"
#include "..\wmsoapmsg\wmsoapmsg.h"

static wchar_t *g_pwszMsgNS = L"http://soapinterop.org/";

// CinteropsvcdocObj

STDMETHODIMP CinteropsvcdocObj::OnProcessBody(VARIANT SOAPMsgInterface, VARIANT_BOOL *pResult)
{
	*pResult = VARIANT_TRUE;
	// get interface ptr
	IDispatch *pIDispatch = SOAPMsgInterface.pdispVal;
	Iwmsoapmsg2 *pIwmsoapmsg;
	HRESULT hRes = pIDispatch->QueryInterface(IID_Iwmsoapmsg2, (void **)&pIwmsoapmsg);
	if (hRes != S_OK)
	{
		return E_FAIL;
	}
	// process
	if (ProcessMessage(pIwmsoapmsg) == false)
	{
		GenerateFault(pIwmsoapmsg);
	}
	pIwmsoapmsg->Release();
	return S_OK;
}

bool CinteropsvcdocObj::ProcessMessage(Iwmsoapmsg2 *pIwmsoapmsg)
{
	m_pComplexDocElem = NULL;

	BSTR bstrXML;
	wstring wstrXML;
	VARIANT_BOOL bResult;
	HRESULT hRes = pIwmsoapmsg->GetBodyElemLiteral( &bstrXML,
													&bResult);
	if (hRes != S_OK || bResult == VARIANT_FALSE)
	{
		return false;
	}
	// set up for parsing
	WMXMLParser Parser;
	bool bRtn = true;
	// parse the XML fragment representing the header entry
	try
	{
		Parser.ParseXML_WideString(bstrXML, NULL);
	}
	catch(int e)
	{
		int x = e;
		SysFreeString(bstrXML);
		return false;
	}
	SysFreeString(bstrXML);
	// get the WMXMLElement pointer representing root node of parse tree
	WMXMLElement *pRoot = Parser.DetachDocRoot();
	if (pRoot == NULL)
	{
		return false;
	}

	// reset flags
	m_bSingleTagFound = false;
	m_bSimpleDocFound = false;
	m_bComplexDocFound = false;

	// look for 'SingleTag' element
	WMXMLElement *pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"SingleTag"));
	if (pChild != NULL)
	{
		// get nested 'SingleTag' element
		WMXMLElement *pContent = pChild->GetChildElement(wstring(g_pwszMsgNS), wstring(L"SingleTag"));
		if (pContent != NULL)
		{
			m_wstrSingleTagValue = pContent->GetContent();
		}
		m_bSingleTagFound = true;
		goto response;
	}
	// look for 'SimpleDocument' element
	pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"SimpleDocument"));
	if (pChild != NULL)
	{
		// get nested 'SimpleDocument' element
		WMXMLElement *pContent = pChild->GetChildElement(wstring(g_pwszMsgNS), wstring(L"SimpleDocument"));
		if (pContent != NULL)
		{
			m_wstrSimpleDocValue = pContent->GetContent();
		}
		m_bSimpleDocFound = true;
		goto response;
	}
	// look for 'ComplexDocument' element
	pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"ComplexDocument"));
	if (pChild != NULL)
	{
		// get nested 'ComplexDocument' element
		WMXMLElement *pContent = pChild->GetChildElement(wstring(g_pwszMsgNS), wstring(L"ComplexDocument"));
		if (pContent != NULL)
		{
			// copy the element
			m_pComplexDocElem = new WMXMLElement(*pContent);
		}
		m_bComplexDocFound = true;
	}
response:
	delete pRoot;
	// create response
    long lSOAPVersion;
    pIwmsoapmsg->GetSOAPVersion(&lSOAPVersion);
	WMXMLElement *pBody = new WMXMLElement(wstring(L"SOAP-ENV:Body"));
	if (pBody != NULL)
	{
        if (lSOAPVersion == SOAP_VERSION_1_1)
        {
    		pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoapEnvelopeNS));
        }
        else
        {
    		pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS));
        }
		if (m_bSingleTagFound == true)
		{
			WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:SingleTagResponse"));
			if (pElem != NULL)
			{
				pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS));
				WMXMLElement *pContent = new WMXMLElement(wstring(L"iop:SingleTag"));
				if (pContent != NULL)
				{
					pContent->AppendContent(m_wstrSingleTagValue);
					pElem->AddChildElement(pContent);
				}
				pBody->AddChildElement(pElem);
			}
		}
		else if (m_bSimpleDocFound == true)
		{
			WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:SimpleDocumentResponse"));
			if (pElem != NULL)
			{
				pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS));
				WMXMLElement *pContent = new WMXMLElement(wstring(L"iop:SimpleDocument"));
				if (pContent != NULL)
				{
					pContent->AppendContent(m_wstrSimpleDocValue);
					pElem->AddChildElement(pContent);
				}
				pBody->AddChildElement(pElem);
			}
		}
		else if (m_bComplexDocFound == true)
		{
			WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:ComplexDocumentResponse"));
			if (pElem != NULL)
			{
				pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS));
				if (m_pComplexDocElem != NULL)
				{
					pElem->AddChildElement(m_pComplexDocElem);
				}
				pBody->AddChildElement(pElem);
			}
		}
		BSTR bstrXML = pBody->Serialize(NULL);
		BSTR bstrEncodingStyle = SysAllocString(L"");
		pIwmsoapmsg->SetBodyElemLiteral(bstrXML, bstrEncodingStyle, &bResult);
		SysFreeString(bstrXML);
		SysFreeString(bstrEncodingStyle);
		delete pBody;
	}
	return true;
}

bool CinteropsvcdocObj::GenerateFault(Iwmsoapmsg2 *pIwmsoapmsg)
{
    long lSOAPVersion;
    pIwmsoapmsg->GetSOAPVersion(&lSOAPVersion);
	BSTR bstrFaultcode, bstrFaultcodeNS;
	BSTR bstrFaultstring = SysAllocString(L"Message processing failed.");
    VARIANT_BOOL bResult = VARIANT_FALSE;
    if (lSOAPVersion == SOAP_VERSION_1_1)
    {
		bstrFaultcode = SysAllocString(L"Client");
        bstrFaultcodeNS = SysAllocString(g_pwszSoapEnvelopeNS);
		pIwmsoapmsg->SetSOAPFault(bstrFaultcode, bstrFaultcodeNS, bstrFaultstring, VARIANT_TRUE, &bResult);
    }
    else
    {
		bstrFaultcode = SysAllocString(L"Sender");
        bstrFaultcodeNS = SysAllocString(g_pwszSoap12EnvelopeNS);
        BSTR bstrSubcode = SysAllocString(L"");
        BSTR bstrSubcodeNS = SysAllocString(L"");
        BSTR bstrLangId = SysAllocString(L"en");
		pIwmsoapmsg->SetSOAP12Fault(bstrFaultcode, bstrFaultcodeNS, bstrSubcode, bstrSubcodeNS, bstrFaultstring, bstrLangId, &bResult);
        SysFreeString(bstrSubcode);
        SysFreeString(bstrSubcodeNS);
        SysFreeString(bstrLangId);
    }
	SysFreeString(bstrFaultcode);
	SysFreeString(bstrFaultcodeNS);
	SysFreeString(bstrFaultstring);
	return true;
}
