// WMSOAPBindingHandlers.cpp: implementation of the CWMSOAPBindingHandlers class.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001 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.
//
//////////////////////////////////////////////////////////////////////
//
// SOAP extensibility elements - support for SOAP binding elements in WSDL
//  
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WMSOAPBindingHandlers.h"
#include "WMSOAPWSDLClient.h"
#include "charencode.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// SOAP extensibility elements

static wchar_t *g_pwszWebServicesDescSOAPNS = L"http://schemas.xmlsoap.org/wsdl/soap/";
static wchar_t *g_pwszWebServicesDescMIMENS = L"http://schemas.xmlsoap.org/wsdl/mime/";
static wchar_t *g_pwszWebServicesDescHTTPNS = L"http://schemas.xmlsoap.org/wsdl/http/";
static wchar_t *g_pwszWebServicesDescSOAP12NS = L"http://schemas.xmlsoap.org/wsdl/soap12/";
static wchar_t *g_pwszWebServicesDescNS = L"http://schemas.xmlsoap.org/wsdl/";

bool WMSOAPBindingHeaderFaultExt::GetHeaderPartMsg(  const wstring& wstrPartName,
												const wstring& wstrPartNS,
												wstring& wstrMsg,
												wstring& wstrMsgNS)
{
	if (wstrPartName == m_wstrPart && wstrPartNS == m_wstrNamespace)
	{
		GetMessage(wstrMsg, wstrMsgNS);
		return true;
	}
	return false;
}

bool WMSOAPBindingHeaderFaultExt::GetHeaderPartEncStyle(const wstring& wstrPartName,
												        const wstring& wstrPartNS,
												        wstring& wstrEncStyle)
{
	if (wstrPartName == m_wstrPart && wstrPartNS == m_wstrNamespace)
	{
		if (GetUse() == L"encoded")
        {
            wstrEncStyle = GetEncodingStyle();
    		return true;
        }
        return false;
	}
	return false;
}

void WMSOAPBindingHeaderFaultExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"headerfaultmessage";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		wstring wstrTemp = pAttr->GetValue();
		wstring::size_type pos = wstrTemp.find(':');
		if (pos != wstring::npos)
		{
			// get NS prefix
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstrTemp.substr(0, pos))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'soap:headerfault'");
			}
			m_wstrMessage = wstrTemp.substr(++pos);
		}
		else
		{
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstring(L""))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'soap:headerfault'");
			}
			m_wstrMessage = wstrTemp;
		}
	}
	else
	{
		// Required message attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'message' missing on element: 'soap:headerfault'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerfaultpart";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrPart = pAttr->GetValue();
	}
	else
	{
		// Required part attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'part' missing on element: 'soap:headerfault'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerfaultuse";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrUse = pAttr->GetValue();
	}
	else
	{
		// Required use attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'use' missing on element: 'soap:headerfault'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerfaultencodingStyle";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrEncodingStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerfaultnamespace";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrNamespace = pAttr->GetValue();
	}
}

void WMSOAPBindingHeaderExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"headermessage";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		wstring wstrTemp = pAttr->GetValue();
		wstring::size_type pos = wstrTemp.find(':');
		if (pos != wstring::npos)
		{
			// get NS prefix
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstrTemp.substr(0, pos))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'soap:header'");
			}
			m_wstrMessage = wstrTemp.substr(++pos);
		}
		else
		{
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstring(L""))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'soap:header'");
			}
			m_wstrMessage = wstrTemp;
		}
	}
	else
	{
		// Required message attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'message' missing on element: 'soap:header'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerpart";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrPart = pAttr->GetValue();
	}
	else
	{
		// Required part attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'part' missing on element: 'soap:header'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headeruse";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrUse = pAttr->GetValue();
	}
	else
	{
		// Required use attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'use' missing on element: 'soap:header'");
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headerencodingStyle";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrEncodingStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"headernamespace";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrNamespace = pAttr->GetValue();
	}
}

WMWSDLEventHandler *WMSOAPBindingHeaderExt::StartElement(const wstring& wstrURI,
														const wstring& wstrLocalName,
														const wstring& wstrQualifiedName,
														WMXMLAttributeMap& mapAttributes,
														NSPrefixMap& mapNSPrefixes,
														WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS)
	{
		if (wstrLocalName == L"headerfault")
		{
			WMSOAPBindingHeaderFaultExt *pSOAPFaultHeader = new WMSOAPBindingHeaderFaultExt();
			if (pSOAPFaultHeader == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			m_listSOAPFaultHeaders.push_back(pSOAPFaultHeader);
            pSOAPFaultHeader->SetNamespace(wstrURI);
			pSOAPFaultHeader->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pSOAPFaultHeader;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

void WMSOAPBindingBodyExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"bodyparts";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrParts = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"bodyuse";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrUse = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"bodyencodingStyle";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrEncodingStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"bodynamespace";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrNamespace = pAttr->GetValue();
	}
}

void WMSOAPBindingFaultExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"faultname";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrName = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"faultuse";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrUse = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"faultencodingStyle";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrEncodingStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"faultnamespace";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrNamespace = pAttr->GetValue();
	}
}

void WMSOAPBindingOpExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"operationstyle";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"operationsoapAction";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		// put quotes around it since SOAPAction values are quoted
		m_wstrSOAPAction = L"\"";
		m_wstrSOAPAction += pAttr->GetValue();
		m_wstrSOAPAction += L"\"";
	}
    if (GetNamespace() == g_pwszWebServicesDescSOAP12NS)
    {
	    // unqualified attribute name expected
	    wstrKey = GetNamespace();
	    wstrKey += L"operationsoapActionRequired";
	    if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	    {
		    WMXMLAttribute *pAttr = (*iter).second;
            if (pAttr->GetValue() == L"1" || pAttr->GetValue() == L"true")
            {
		        m_bSOAPActionRequired = true;
            }
	    }
    }
}

void WMSOAPBindingBindingExt::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"bindingstyle";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrStyle = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = GetNamespace();
	wstrKey += L"bindingtransport";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrTransport = pAttr->GetValue();
	}
}

void WMSOAPAddressExt::ReadAttributes(WMXMLAttributeMap& mapAttributes,
										  NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = GetNamespace();
	wstrKey += L"addresslocation";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		// insert into map
		m_wstrSOAPAddress = pAttr->GetValue();
	}
	else
	{
		// Required location attribute missing
		throw new WMWebServicesDescFault(L"WSDL Schema Error",
				L"Required attribute 'location' missing on element: 'soap:address'");
	}
}

// derived from base WSDL handlers

void WMSOAPFaultElemHandler::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = g_pwszWebServicesDescNS;
	wstrKey += L"faultname";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		// get the value
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrName = pAttr->GetValue();
	}
	// unqualified attribute name expected
	wstrKey = g_pwszWebServicesDescNS;
	wstrKey += L"faultmessage";
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		wstring wstrTemp = pAttr->GetValue();
		wstring::size_type pos = wstrTemp.find(':');
		if (pos != wstring::npos)
		{
			// get NS prefix
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstrTemp.substr(0, pos))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'fault'");
			}
			m_wstrMessage = wstrTemp.substr(++pos);
		}
		else
		{
			// default namespace
			NSPrefixMap::iterator iNS;
			if ((iNS = mapNSPrefixes.find(wstring(L""))) != mapNSPrefixes.end())
			{
				m_wstrMessageNS = (*iNS).second;
			}
			else
			{
				// unresolvable namespace prefix
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Unresolvable namespace for attribute 'message' on element: 'fault'");
			}
			m_wstrMessage = wstrTemp;
		}
	}
}

WMWSDLEventHandler *WMSOAPFaultElemHandler::StartElement(const wstring& wstrURI,
														const wstring& wstrLocalName,
														const wstring& wstrQualifiedName,
														WMXMLAttributeMap& mapAttributes,
														NSPrefixMap& mapNSPrefixes,
														WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS)
	{
		if (wstrLocalName == L"fault")
		{
            m_SOAPFault.SetNamespace(wstrURI);
			m_SOAPFault.ReadAttributes(mapAttributes, mapNSPrefixes);
			return &m_SOAPFault;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

bool WMSOAPOutputHandler::GetHeaderPartMsg(const wstring& wstrPartName,
											const wstring& wstrPartNS,
											wstring& wstrMsg,
											wstring& wstrMsgNS)
{
	list<WMSOAPBindingHeaderExt *>::iterator iter;
	for (iter = m_listSOAPHeaders.begin(); iter != m_listSOAPHeaders.end(); iter++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter;
		if (pSOAPHeader->GetHeaderPartMsg(wstrPartName, wstrPartNS, wstrMsg, wstrMsgNS) == true)
		{
			return true;
		}
	}
	return false;
}

bool WMSOAPOutputHandler::GetHeaderPartEncStyle(const wstring& wstrPartName,
											    const wstring& wstrPartNS,
											    wstring& wstrEncStyle)
{
	list<WMSOAPBindingHeaderExt *>::iterator iter;
	for (iter = m_listSOAPHeaders.begin(); iter != m_listSOAPHeaders.end(); iter++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter;
		if (pSOAPHeader->GetHeaderPartEncStyle(wstrPartName, wstrPartNS, wstrEncStyle) == true)
		{
			return true;
		}
	}
	return false;
}

bool WMSOAPOutputHandler::GetHeaderFaultPartMsg(const wstring& wstrPartName,
												const wstring& wstrPartNS,
												wstring& wstrMsg,
												wstring& wstrMsgNS)
{
	// traverse list of soap:header elements
	list<WMSOAPBindingHeaderExt *>::iterator iter1;
	for (iter1 = m_listSOAPHeaders.begin(); iter1 != m_listSOAPHeaders.end(); iter1++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter1;
		// now traverse list of soap:headerfault elements
		list<WMSOAPBindingHeaderFaultExt *>::iterator iter2;
		for (iter2 = pSOAPHeader->GetFaultHeaders().begin();
				iter2 != pSOAPHeader->GetFaultHeaders().end();
				iter2++)
		{
			WMSOAPBindingHeaderFaultExt *pSOAPFaultHeader = *iter2;
			if (pSOAPFaultHeader->GetHeaderPartMsg(wstrPartName, wstrPartNS, wstrMsg, wstrMsgNS) == true)
			{
				return true;
			}
		}
	}
	return false;
}

bool WMSOAPOutputHandler::GetHeaderFaultPartEncStyle(   const wstring& wstrPartName,
											            const wstring& wstrPartNS,
											            wstring& wstrEncStyle)
{
	// traverse list of soap:header elements
	list<WMSOAPBindingHeaderExt *>::iterator iter1;
	for (iter1 = m_listSOAPHeaders.begin(); iter1 != m_listSOAPHeaders.end(); iter1++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter1;
		// now traverse list of soap:headerfault elements
		list<WMSOAPBindingHeaderFaultExt *>::iterator iter2;
		for (iter2 = pSOAPHeader->GetFaultHeaders().begin();
				iter2 != pSOAPHeader->GetFaultHeaders().end();
				iter2++)
		{
			WMSOAPBindingHeaderFaultExt *pSOAPFaultHeader = *iter2;
			if (pSOAPFaultHeader->GetHeaderPartEncStyle(wstrPartName, wstrPartNS, wstrEncStyle) == true)
			{
				return true;
			}
		}
	}
	return false;
}

WMWSDLEventHandler *WMSOAPOutputHandler::StartElement(  const wstring& wstrURI,
												        const wstring& wstrLocalName,
												        const wstring& wstrQualifiedName,
												        WMXMLAttributeMap& mapAttributes,
												        NSPrefixMap& mapNSPrefixes,
												        WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS)
	{
		if (wstrLocalName == L"body")
		{
            m_SOAPBody.SetNamespace(wstrURI);
			m_SOAPBody.ReadAttributes(mapAttributes, mapNSPrefixes);
			return &m_SOAPBody;
		}
		else if (wstrLocalName == L"header")
		{
			WMSOAPBindingHeaderExt *pSOAPHeader = new WMSOAPBindingHeaderExt();
			if (pSOAPHeader == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			m_listSOAPHeaders.push_back(pSOAPHeader);
            pSOAPHeader->SetNamespace(wstrURI);
			pSOAPHeader->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pSOAPHeader;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

bool WMSOAPInputHandler::GetHeaderPartMsg(  const wstring& wstrPartName,
											const wstring& wstrPartNS,
											wstring& wstrMsg,
											wstring& wstrMsgNS)
{
	list<WMSOAPBindingHeaderExt *>::iterator iter;
	for (iter = m_listSOAPHeaders.begin(); iter != m_listSOAPHeaders.end(); iter++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter;
		if (pSOAPHeader->GetHeaderPartMsg(wstrPartName, wstrPartNS, wstrMsg, wstrMsgNS) == true)
		{
			return true;
		}
	}
	return false;
}

bool WMSOAPInputHandler::GetHeaderPartEncStyle( const wstring& wstrPartName,
											    const wstring& wstrPartNS,
											    wstring& wstrEncStyle)
{
	list<WMSOAPBindingHeaderExt *>::iterator iter;
	for (iter = m_listSOAPHeaders.begin(); iter != m_listSOAPHeaders.end(); iter++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter;
		if (pSOAPHeader->GetHeaderPartEncStyle(wstrPartName, wstrPartNS, wstrEncStyle) == true)
		{
			return true;
		}
	}
	return false;
}

bool WMSOAPInputHandler::GetHeaderFaultPartMsg(const wstring& wstrPartName,
												const wstring& wstrPartNS,
												wstring& wstrMsg,
												wstring& wstrMsgNS)
{
	// traverse list of soap:header elements
	list<WMSOAPBindingHeaderExt *>::iterator iter1;
	for (iter1 = m_listSOAPHeaders.begin(); iter1 != m_listSOAPHeaders.end(); iter1++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter1;
		// now traverse list of soap:headerfault elements
		list<WMSOAPBindingHeaderFaultExt *>::iterator iter2;
		for (iter2 = pSOAPHeader->GetFaultHeaders().begin();
				iter2 != pSOAPHeader->GetFaultHeaders().end();
				iter2++)
		{
			WMSOAPBindingHeaderFaultExt *pSOAPFaultHeader = *iter2;
			if (pSOAPFaultHeader->GetHeaderPartMsg(wstrPartName, wstrPartNS, wstrMsg, wstrMsgNS) == true)
			{
				return true;
			}
		}
	}
	return false;
}

bool WMSOAPInputHandler::GetHeaderFaultPartEncStyle(const wstring& wstrPartName,
												    const wstring& wstrPartNS,
												    wstring& wstrEncStyle)
{
	// traverse list of soap:header elements
	list<WMSOAPBindingHeaderExt *>::iterator iter1;
	for (iter1 = m_listSOAPHeaders.begin(); iter1 != m_listSOAPHeaders.end(); iter1++)
	{
		WMSOAPBindingHeaderExt *pSOAPHeader = *iter1;
		// now traverse list of soap:headerfault elements
		list<WMSOAPBindingHeaderFaultExt *>::iterator iter2;
		for (iter2 = pSOAPHeader->GetFaultHeaders().begin();
				iter2 != pSOAPHeader->GetFaultHeaders().end();
				iter2++)
		{
			WMSOAPBindingHeaderFaultExt *pSOAPFaultHeader = *iter2;
			if (pSOAPFaultHeader->GetHeaderPartEncStyle(wstrPartName, wstrPartNS, wstrEncStyle) == true)
			{
				return true;
			}
		}
	}
	return false;
}

WMWSDLEventHandler *WMSOAPInputHandler::StartElement(const wstring& wstrURI,
												const wstring& wstrLocalName,
												const wstring& wstrQualifiedName,
												WMXMLAttributeMap& mapAttributes,
												NSPrefixMap& mapNSPrefixes,
												WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS)
	{
		if (wstrLocalName == L"body")
		{
            m_SOAPBody.SetNamespace(wstrURI);
			m_SOAPBody.ReadAttributes(mapAttributes, mapNSPrefixes);
			return &m_SOAPBody;
		}
		else if (wstrLocalName == L"header")
		{
			WMSOAPBindingHeaderExt *pSOAPHeader = new WMSOAPBindingHeaderExt();
			if (pSOAPHeader == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			m_listSOAPHeaders.push_back(pSOAPHeader);
            pSOAPHeader->SetNamespace(wstrURI);
			pSOAPHeader->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pSOAPHeader;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

WMWSDLEventHandler *WMSOAPOperationHandler::StartElement(const wstring& wstrURI,
													const wstring& wstrLocalName,
													const wstring& wstrQualifiedName,
													WMXMLAttributeMap& mapAttributes,
													NSPrefixMap& mapNSPrefixes,
													WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS)
	{
		if (wstrLocalName == L"operation")
		{
            m_SOAPOperation.SetNamespace(wstrURI);
			m_SOAPOperation.ReadAttributes(mapAttributes, mapNSPrefixes);
			return &m_SOAPOperation;
		}
	}
	else if (wstrURI == g_pwszWebServicesDescNS)
	{
		if (wstrLocalName == L"input")
		{
			m_Input.SetNamespace(m_wstrNS);
			return &m_Input;
		}
		else if (wstrLocalName == L"output")
		{
			m_Output.SetNamespace(m_wstrNS);
			return &m_Output;
		}
		else if (wstrLocalName == L"fault")
		{
			WMSOAPFaultElemHandler *pFault = new WMSOAPFaultElemHandler();
			if (pFault == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			// insert into map
			m_listFaults.push_back(pFault);
			pFault->SetNamespace(m_wstrNS);
			pFault->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pFault;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

void WMSOAPOperationHandler::ReadAttributes(WMXMLAttributeMap& mapAttributes, NSPrefixMap& mapNSPrefixes)
{
	// unqualified attribute name expected
	wstring wstrKey = g_pwszWebServicesDescNS;
	wstrKey += L"operationname";
	WMXMLAttributeMap::iterator iter;
	if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
	{
		WMXMLAttribute *pAttr = (*iter).second;
		m_wstrName = pAttr->GetValue();
	}
}

WMWSDLEventHandler *WMSOAPBindingHandler::StartElement(const wstring& wstrURI,
													const wstring& wstrLocalName,
													const wstring& wstrQualifiedName,
													WMXMLAttributeMap& mapAttributes,
													NSPrefixMap& mapNSPrefixes,
													WMXMLElement *pElement)
{
	if ((wstrURI == g_pwszWebServicesDescSOAPNS || wstrURI == g_pwszWebServicesDescSOAP12NS) &&
            wstrLocalName == L"binding")
	{
        m_SOAPBinding.SetNamespace(wstrURI);
		m_SOAPBinding.ReadAttributes(mapAttributes, mapNSPrefixes);
		return &m_SOAPBinding;
	}
	else if (wstrURI == g_pwszWebServicesDescNS && wstrLocalName == L"operation")
	{
		// unqualified attribute name expected
		wstring wstrKey = wstrURI;
		wstrKey += wstrLocalName;
		wstrKey += L"name";
		WMXMLAttributeMap::iterator iter;
		if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
		{
			WMSOAPOperationHandler *pOperation = new WMSOAPOperationHandler();
			if (pOperation == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			WMXMLAttribute *pAttr = (*iter).second;
			// insert into map
			m_mapOperations.insert(map<wstring,
				WMOperationHandler *>::value_type(pAttr->GetValue(), pOperation));
			pOperation->SetNamespace(m_wstrNS);
			pOperation->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pOperation;
		}
		else
		{
			// Required name attribute missing
			throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Required attribute 'name' missing on element: 'operation'.");
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

WMSOAPOperationHandler *WMSOAPBindingHandler::GetSOAPOperation(const wstring& wstrOpName)
{
	WMOperationHandler *pOp;
	if ((pOp = GetOperation(wstrOpName)) == NULL)
	{
		return NULL;
	}
	return static_cast<WMSOAPOperationHandler *>(pOp);
}

WMSOAPOperationHandler *WMSOAPBindingHandler::GetOpBySOAPAction(const wstring& wstrSOAPAction)
{
	map<wstring, WMOperationHandler *>::iterator iM;
	for (iM = m_mapOperations.begin(); iM != m_mapOperations.end(); iM++)
	{
		WMSOAPOperationHandler *pOp;
		pOp = static_cast<WMSOAPOperationHandler *>((*iM).second);
		if (pOp != NULL && pOp->GetSOAPAction() == wstrSOAPAction)
		{
			return pOp;
		}
	}
	return NULL;
}

WMWSDLEventHandler *WMSOAPPortHandler::StartElement(const wstring& wstrURI,
								const wstring& wstrLocalName,
								const wstring& wstrQualifiedName,
								WMXMLAttributeMap& mapAttributes,
								NSPrefixMap& mapNSPrefixes,
								WMXMLElement *pElement)
{
	if ((wstrURI == g_pwszWebServicesDescSOAPNS ||
        wstrURI == g_pwszWebServicesDescSOAP12NS ||
        wstrURI == g_pwszWebServicesDescHTTPNS) &&
				wstrLocalName == L"address")
	{
        m_SOAPAddress.SetNamespace(wstrURI);
		m_SOAPAddress.ReadAttributes(mapAttributes, mapNSPrefixes);
		return &m_SOAPAddress;
	}
	return IGNORE_ELEMENT_HANDLER;
}

WMWSDLEventHandler *WMSOAPServiceHandler::StartElement(const wstring& wstrURI,
													const wstring& wstrLocalName,
													const wstring& wstrQualifiedName,
													WMXMLAttributeMap& mapAttributes,
													NSPrefixMap& mapNSPrefixes,
													WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescNS)
	{
		if (wstrLocalName == L"port")
		{
			// unqualified attribute name expected
			wstring wstrKey = wstrURI;
			wstrKey += wstrLocalName;
			wstrKey += L"name";
			WMXMLAttributeMap::iterator iter;
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMSOAPPortHandler *pPort = new WMSOAPPortHandler();
				if (pPort == NULL)
				{
					throw new WMWebServicesDescFault(L"Internal Error",
							L"Memory allocation failure.");
				}
				WMXMLAttribute *pAttr = (*iter).second;
				// insert into map
				m_mapPorts.insert(map<wstring,
					WMPortHandler *>::value_type(pAttr->GetValue(), pPort));
				pPort->SetNamespace(m_wstrNS);
				pPort->ReadAttributes(mapAttributes, mapNSPrefixes);
				return pPort;
			}
			else
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'name' missing on element: 'port'.");
			}
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

WMWSDLEventHandler *WMSOAPDefinitionsHandler::StartElement(const wstring& wstrURI,
														const wstring& wstrLocalName,
														const wstring& wstrQualifiedName,
														WMXMLAttributeMap& mapAttributes,
														NSPrefixMap& mapNSPrefixes,
														WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescNS)
	{
		// 'types' element is unique and un-named
		if (wstrLocalName == L"types")
		{
			m_Types.SetNamespace(m_wstrTNS);
			return &m_Types;
		}
		// unqualified attribute name expected
		wstring wstrKey = wstrURI;
		wstrKey += wstrLocalName;
		wstrKey += L"name";
		WMXMLAttributeMap::iterator iter;
		if (wstrLocalName == L"binding")
		{
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMSOAPBindingHandler *pBinding = new WMSOAPBindingHandler();
				if (pBinding == NULL)
				{
					throw new WMWebServicesDescFault(L"Internal Error",
							L"Memory allocation failure.");
				}
				WMXMLAttribute *pAttr = (*iter).second;
				// insert into map
				m_mapBindings.insert(map<wstring,
					WMBindingHandler *>::value_type(pAttr->GetValue(), pBinding));
				pBinding->SetNamespace(m_wstrTNS);
				pBinding->ReadAttributes(mapAttributes, mapNSPrefixes);
				return pBinding;
			}
			else
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'name' missing on element: 'binding'.");
			}
		}
		else if (wstrLocalName == L"service")
		{
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMSOAPServiceHandler *pService = new WMSOAPServiceHandler();
				if (pService == NULL)
				{
					throw new WMWebServicesDescFault(L"Internal Error",
							L"Memory allocation failure.");
				}
				WMXMLAttribute *pAttr = (*iter).second;
				// insert into map
				m_mapServices.insert(map<wstring,
					WMServiceHandler *>::value_type(pAttr->GetValue(), pService));
				pService->SetNamespace(m_wstrTNS);
				return pService;
			}
			else
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'name' missing on element: 'service'.");
			}
		}
		else if (wstrLocalName == L"message")
		{
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMMessageHandler *pMessage = new WMMessageHandler(m_Types);
				if (pMessage == NULL)
				{
					throw new WMWebServicesDescFault(L"Internal Error",
							L"Memory allocation failure.");
				}
				WMXMLAttribute *pAttr = (*iter).second;
				// insert into map
				m_mapMessages.insert(map<wstring,
					WMMessageHandler *>::value_type(pAttr->GetValue(), pMessage));
				pMessage->SetNamespace(m_wstrTNS);
				return pMessage;
			}
			else
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'name' missing on element: 'message'.");
			}
		}
		else if (wstrLocalName == L"portType")
		{
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMPortTypeHandler *pPortType = new WMPortTypeHandler();
				if (pPortType == NULL)
				{
					throw new WMWebServicesDescFault(L"Internal Error",
							L"Memory allocation failure.");
				}
				WMXMLAttribute *pAttr = (*iter).second;
				// insert into map
				m_mapPortTypes.insert(map<wstring,
					WMPortTypeHandler *>::value_type(pAttr->GetValue(), pPortType));
				pPortType->SetNamespace(m_wstrTNS);
				return pPortType;
			}
			else
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'name' missing on element: 'portType'.");
			}
		}
		else if (wstrLocalName == L"import")
		{
			// import definitions
			wstring wstrNamespace, wstrLocation;
			wstring wstrKey = wstrURI;
			wstrKey += wstrLocalName;
			wstrKey += L"namespace";	
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMXMLAttribute *pAttr = (*iter).second;
				wstrNamespace = pAttr->GetValue();
			}
			else
			{
				// Required namespace attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'namespace' missing on element: 'import'.");
			}
			wstrKey = wstrURI;
			wstrKey += wstrLocalName;
			wstrKey += L"location";	
			if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
			{
				WMXMLAttribute *pAttr = (*iter).second;
				wstrLocation = pAttr->GetValue();
			}
			else
			{
				// Required location attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Required attribute 'location' missing on element: 'import'.");
			}
			// ok, create WSDL reader
			WMSOAPWSDLImporter *pImporter = new WMSOAPWSDLImporter();
			string strLocation;
			WideStringToUTF8(wstrLocation, strLocation);
			if (pImporter->ReadServiceDesc(strLocation, m_strDocBase) == false)
			{
				// Required name attribute missing
				throw new WMWebServicesDescFault(L"WSDL Schema Error",
						L"Unable to process document referenced in 'import' element.");
			}
			// now copy schemas
			m_Types.MergeSchemas(wstrNamespace, pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetTypes());
			// now copy Message elements
			map<wstring, WMMessageHandler *>::iterator iMessages;
			for (iMessages = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetMessageMap().begin();
					iMessages != pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetMessageMap().end();
					iMessages++)
			{
				WMMessageHandler *pMsg = (*iMessages).second;
				// is it here already?
				if (m_mapMessages.find((*iMessages).first) == m_mapMessages.end())
				{
					// not present in current map, so add it
					WMMessageHandler *pTemp = new WMMessageHandler(m_Types, *pMsg);
					pTemp->SetNamespace(pMsg->GetNamespace());
					m_mapMessages.insert(map<wstring,
						WMMessageHandler *>::value_type((*iMessages).first, pTemp));
				}
			}
			// now take ownership of PortType element ptrs
			map<wstring, WMPortTypeHandler *>::iterator iPortTypes;
			for (iPortTypes = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetPortTypeMap().begin();
					iPortTypes != pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetPortTypeMap().end();)
			{
				// is it here already?
				if (m_mapPortTypes.find((*iPortTypes).first) == m_mapPortTypes.end())
				{
					// not present in current map, so add it
					m_mapPortTypes.insert(map<wstring,
					WMPortTypeHandler *>::value_type((*iPortTypes).first, (*iPortTypes).second));
					iPortTypes = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetPortTypeMap().erase(iPortTypes);
				}
				else
				{
					iPortTypes++;
				}
			}
			// now take ownership of Binding element ptrs
			map<wstring, WMBindingHandler *>::iterator iBindings;
			for (iBindings = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetBindingMap().begin();
					iBindings != pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetBindingMap().end();)
			{
				// is it here already?
				if (m_mapBindings.find((*iBindings).first) == m_mapBindings.end())
				{
					// not present in current map, so add it
					m_mapBindings.insert(map<wstring,
					WMBindingHandler *>::value_type((*iBindings).first, (*iBindings).second));
					iBindings = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetBindingMap().erase(iBindings);
				}
				else
				{
					iBindings++;
				}
			}
			// now take ownership of Service element ptrs
			map<wstring, WMServiceHandler *>::iterator iServices;
			for (iServices = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetServiceMap().begin();
					iServices != pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetServiceMap().end();)
			{
				// is it here already?
				if (m_mapServices.find((*iServices).first) == m_mapServices.end())
				{
					// not present in current map, so add it
					m_mapServices.insert(map<wstring,
						WMServiceHandler *>::value_type((*iServices).first, (*iServices).second));
					iServices = pImporter->GetWSDLDesc()->GetSOAPDefinitions().GetServiceMap().erase(iServices);
				}
				else
				{
					iServices++;
				}
			}
			// release
			delete pImporter;
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}

WMSOAPBindingHandler *WMSOAPDefinitionsHandler::GetSOAPBinding(const wstring& wstrServiceName,
													   const wstring& wstrPortName,
													   const wstring& wstrNamespace)
{
	WMBindingHandler *pBinding;
	if ((pBinding = GetBinding(wstrServiceName,
								wstrPortName,
								wstrNamespace)) == NULL)
	{
		return NULL;
	}
	return static_cast<WMSOAPBindingHandler *>(pBinding);
}

bool WMSOAPDefinitionsHandler::GetSOAPAddress(const wstring& wstrServiceName,
										  const wstring& wstrPortName,
										  const wstring& wstrNamespace,
										  wstring& wstrAddress)
{
	WMServiceHandler *pService = GetService(wstrServiceName, wstrNamespace);
	if (pService == NULL)
	{
		return false;
	}
	WMSOAPPortHandler *pPort =
		static_cast<WMSOAPPortHandler *>(pService->GetPort(wstrPortName));
	if (pPort == NULL)
	{
		return false;
	}
	wstrAddress = pPort->GetSOAPAddress();
	return true;
}

WMWSDLEventHandler *WMSOAPWSDLDesc::StartElement(const wstring& wstrURI,
													const wstring& wstrLocalName,
													const wstring& wstrQualifiedName,
													WMXMLAttributeMap& mapAttributes,
													NSPrefixMap& mapNSPrefixes,
													WMXMLElement *pElement)
{
	if (wstrURI == g_pwszWebServicesDescNS && wstrLocalName == L"definitions")
	{
		m_Definitions.ReadAttributes(mapAttributes, mapNSPrefixes);
		return &m_Definitions;
	}
	else if (IsXSDType(wstrURI) && wstrLocalName == L"schema")
	{
		// unqualified attribute name expected
		wstring wstrKey = wstrURI;
		wstrKey += wstrLocalName;
		wstrKey += L"targetNamespace";
		WMXMLAttributeMap::iterator iter;
		if ((iter = mapAttributes.find(wstrKey)) != mapAttributes.end())
		{
			WMSchemaHandler *pSchema = new WMSchemaHandler();
			if (pSchema == NULL)
			{
				throw new WMWebServicesDescFault(L"Internal Error",
						L"Memory allocation failure.");
			}
			WMXMLAttribute *pAttr = (*iter).second;
			// insert into map
			m_Definitions.GetTypes().GetSchemaMap().insert(map<wstring,
				WMSchemaHandler *>::value_type(pAttr->GetValue(), pSchema));
			pSchema->SetNamespace(wstrURI);
			pSchema->ReadAttributes(mapAttributes, mapNSPrefixes);
			return pSchema;
		}
		else
		{
			// Required name attribute missing
			throw new WMWebServicesDescFault(L"WSDL Schema Error",
					L"Required attribute 'targetNamespace' missing on element: 'schema'.");
		}
	}
	return IGNORE_ELEMENT_HANDLER;
}
