// CAtlClassArrayGenerator.cpp
//
#include "stdafx.h"
#include "AtlClassArrayGenerator.h"
#include "XmlProjectSettings.h"
#include "XmlClassInfo.h"
#include "XmlMemberInfo.h"
#include "XmlProject.h"

CAtlClassArrayGenerator::CAtlClassArrayGenerator()
{}

CAtlClassArrayGenerator::~CAtlClassArrayGenerator()
{}

void CAtlClassArrayGenerator::Generate()
{
	// generate header file
	//
	GenerateHeader();
	
	// generate implementation file
	//
	GenerateImplementation();
}
	
void CAtlClassArrayGenerator::GenerateHeader()
{
	cmString fileName;
	cmString pathName;

	Head_generateHeader();
	Head_generateIfDefBegin();
	Head_generateIncludeSection();
	Head_generateForwardDecl();
	Head_generateClassBegin();
	Head_generateConstructor();
	Head_generateDestructor();
	Head_generateMethods();
	Head_generateSerialization();
	Head_generateMembers();
	Head_generateClassEnd();
	Head_generateIfDefEnd();

	pathName = BuildGeneratedSourcePath() + _T("include\\");
	fileName = GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h");
	SaveFile(pathName + fileName, headCode_);

	hGeneratedFiles_[fileName] = pathName + fileName; 
}

void CAtlClassArrayGenerator::Head_generateHeader()
{
	headCode_ += _T("// ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h") + xCrLf;
	headCode_ += _T("// ") + xCrLf; 
	headCode_ += GetGenerationTimeStamp();
}

void CAtlClassArrayGenerator::Head_generateIfDefBegin()
{
	headCode_ += _T("#if !defined(") + DefineOf(GetClassName()) + GetCardinalityPostfix(classInfo_) + _T(")") + xCrLf;
	headCode_ += _T("#define ") + DefineOf(GetClassName()) + GetCardinalityPostfix(classInfo_) + xCrLf;
	headCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Head_generateIncludeSection()
{
	headCode_ += _T("#include <vector>") + xCrLf;
	headCode_ += _T("#include \"cmString.h\"") + xCrLf;
	headCode_ += _T("#include \"XmlSerializable.h\"") + xCrLf;
	headCode_ += _T("#include \"ProjectConfigAtl.h\"") + xCrLf;

	// include contained class header
	//
	headCode_ += _T("#include \"") + GetClassName(classInfo_->GetName()) + _T(".h\"") + xCrLf;
	headCode_ += xCrLf;

	headCode_ += xCrLf;
	headCode_ += _T("using namespace std;") + xCrLf;
	headCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Head_generateForwardDecl()
{
}

void CAtlClassArrayGenerator::Head_generateClassBegin()
{
	//headCode_ += "class " + GetClassName() + GetCardinalityPostfix(classInfo_) + ": public CXmlSerializable" + xCrLf;
	//headCode_ += "{" + xCrLf;

	cmString prefix;
	cmString name;
	cmString p;

	p =  GetCardinalityPostfix(classInfo_);
	prefix = project_->GetProjectSettings()->GetAtlSettings()->GetClassPrefix();
	name = GetClassName() + p;
	
	headCode_ += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	headCode_ += _T("// ") + name + xCrLf;
	headCode_ += _T("class ATL_NO_VTABLE ") + name + _T(":") + xCrLf; 
	headCode_ += _T("public CComObjectRootEx<CComSingleThreadModel>,") + xCrLf;
	headCode_ += _T("public CComCoClass<") + name + _T(", &CLSID_") + classInfo_->GetName() + p + _T(">,") + xCrLf;
	headCode_ += _T("public IDispatchImpl<I") + name + _T(", &IID_I") + name + _T(", &LIBID_") + ToUpperCase(prefix) + _T("Lib>,") + xCrLf;
	headCode_ += _T("public CXmlSerializable") + xCrLf;
	headCode_ += _T("{") + xCrLf;
	headCode_ += xCrLf;
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + _T("DECLARE_REGISTRY_RESOURCEID(IDR_") + ToUpperCase(classInfo_->GetName() + p) + _T(")") + xCrLf;
	headCode_ += xTab + _T("DECLARE_NOT_AGGREGATABLE(") + name + _T(")") + xCrLf;
	headCode_ += xCrLf;
	headCode_ += xTab + _T("DECLARE_PROTECT_FINAL_CONSTRUCT()") + xCrLf;
	headCode_ += xCrLf;
	headCode_ += xTab + _T("BEGIN_COM_MAP(") + name + _T(")") + xCrLf;
	headCode_ += xTab + xTab + _T("COM_INTERFACE_ENTRY(I") + name + _T(")") + xCrLf;
	headCode_ += xTab + xTab + _T("COM_INTERFACE_ENTRY(IDispatch)") + xCrLf;
	headCode_ += xTab + _T("END_COM_MAP()") + xCrLf;
	headCode_ += xCrLf;

}

void CAtlClassArrayGenerator::Head_generateConstructor()
{
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("();") + xCrLf;
}

void CAtlClassArrayGenerator::Head_generateDestructor()
{
	headCode_ += xTab + _T("virtual ~") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("();") + xCrLf + xCrLf;
}

void CAtlClassArrayGenerator::Head_generateMethods()
{
	cmString n;
	cmString p;

	n = GetClassName();
	p = GetCardinalityPostfix(classInfo_);

	headCode_ += xTab + _T("// I") + n + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(CleanUp)();") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(RestoreDefaults)();") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(GetSize)(/*[out, retval]*/ long* retval);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(GetItem)(/*[in]*/ long index, /*[out, retval]*/ I") + n + _T("** retval);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Insert)(/*[in]*/ long index, /*[in]*/ I") + n + _T("* item);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Delete)(/*[in]*/ long index);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Append)(/*[in]*/ I") + n + _T("* item);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Save)(/*[in]*/ BSTR fileName, /*[out, retval]*/ VARIANT_BOOL* retval);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Load)(/*[in]*/ BSTR fileName, /*[out, retval]*/ VARIANT_BOOL* retval);") + xCrLf;
	headCode_ += xTab + _T("STDMETHOD(Copy)(/*[in]*/ I") + n + p + _T("* source);") + xCrLf;
	
	headCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Head_generateSerialization()
{
	headCode_ += xTab + _T("// serialization") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += xTab + _T("public:") + xCrLf;
	headCode_ += xTab + _T("virtual bool BuildFromXml(IXMLDOMNode* node);") + xCrLf;
	headCode_ += xTab + _T("virtual bool AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement);") + xCrLf;
	headCode_ += xTab + _T("void SetDefaults();")  + xCrLf;
	headCode_ += xTab + _T("void Clear();")  + xCrLf;
	headCode_ += xTab + _T("virtual cmString GetXmlNodeName(){return xmlNodeName_;}") + xCrLf;
	headCode_ += xTab + _T("static cmString xmlNodeName_;") + xCrLf;
	headCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Head_generateMembers()
{
	cmString p;
	cmString n;

	p = GetCardinalityPostfix(classInfo_);
	n = classInfo_->GetName();

	headCode_ += xTab + _T("// inner members") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("protected:") + xCrLf;

	headCode_ += xTab + _T("vector<CComObject<") + GetClassName() + _T(">* > ") + GetCamelCase(n) + p  + _T("_;");
}

void CAtlClassArrayGenerator::Head_generateClassEnd()
{
	headCode_ += xCrLf;
	headCode_ += _T("};") + xCrLf;
	headCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Head_generateIfDefEnd()
{
	headCode_ += _T("#endif //!defined(") + DefineOf(GetClassName() + GetCardinalityPostfix(classInfo_)) + _T(")") + xCrLf + xCrLf;
}

void CAtlClassArrayGenerator::GenerateImplementation()
{
	cmString fileName;
	cmString pathName;

	Impl_generateHeader();
	Impl_generateIncludeSection();
	
	Impl_generateConstructor();
	Impl_generateDestructor();
	Impl_generateMethods();
	Impl_generateSerialization();

	pathName = BuildGeneratedSourcePath() + _T("src\\");
	fileName =  GetClassName() + GetCardinalityPostfix(classInfo_) +  _T(".cpp");
	SaveFile(pathName + fileName, implCode_);

	cppGeneratedFiles_[fileName] = pathName + fileName; 
}

void CAtlClassArrayGenerator::Impl_generateHeader()
{
	implCode_ += _T("// ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".cpp") + xCrLf;
	implCode_ += _T("// ") + xCrLf; 
	implCode_ += GetGenerationTimeStamp();
}

void CAtlClassArrayGenerator::Impl_generateIncludeSection()
{
	implCode_ += _T("#include \"stdafx.h\"") + xCrLf;
	implCode_ += _T("#include \"") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h\"") + xCrLf;

	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* member;
	cmString name;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() == enDataType_Class) {
			CXmlClassInfo* classInfo;

			classInfo = dynamic_cast<CXmlClassInfo*>(member);
			if (classInfo->GetDefinitionInheritance())
				classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));

			name = classInfo->GetName();
			implCode_ += _T("#include \"") + GetClassName(name) + _T(".h\"") + xCrLf;
		}
	}

	implCode_ +=  xCrLf;
}

void CAtlClassArrayGenerator::Impl_generateConstructor()
{
	cmString p;

	p = GetCardinalityPostfix(classInfo_);

	implCode_ += _T("cmString ") + GetClassName() + p + _T("::xmlNodeName_ = _T(\"") + classInfo_->GetName() + p + _T("\");") + xCrLf;	
	implCode_ += xCrLf;

	// default constructor
	//
	implCode_ += GetClassName() + p + _T("::") + GetClassName() + p + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Impl_generateDestructor()
{
	cmString p;

	p = GetCardinalityPostfix(classInfo_);

	implCode_ += GetClassName() + p + _T("::~") + GetClassName() + p + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CleanUp();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CAtlClassArrayGenerator::Impl_generateMethods()
{
	cmString p;
	cmString n;

	p = GetCardinalityPostfix(classInfo_);
	n = classInfo_->GetName();

	// copy
	//
	cmString vectName;

	vectName = GetCamelCase(n) + p;
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Copy(I") + GetClassName() + p + _T("* source)")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CleanUp();") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("long size;") + xCrLf;
	implCode_ += xTab + _T("I") + GetClassName() + _T("* sourceItem;") + xCrLf;
	implCode_ += xCrLf;

	implCode_ += xTab + _T("source->GetSize(&size);") + xCrLf;
	implCode_ += xTab + _T("for (long i = 0; i < size; i++) {") + xCrLf;
	implCode_ += xTab + xTab + _T("CComObject<") + GetClassName() + _T(">* newItem;") + xCrLf;
	implCode_ += xCrLf;
//	implCode_ += xTab + xTab + "newItem = new CComObject<" + GetClassName() + ">;" + xCrLf;
	implCode_ += xTab + xTab + _T("CComObject<") + GetClassName() + _T(">::CreateInstance(&newItem);") + xCrLf;
	implCode_ += xTab + xTab + _T("source->GetItem(i, &sourceItem);") + xCrLf;
	implCode_ += xTab + xTab + _T("newItem->Copy(sourceItem);") + xCrLf;
	implCode_ += xTab + xTab + _T("newItem->AddRef();") + xCrLf;
	implCode_ += xTab + xTab + _T("sourceItem->Release();") + xCrLf;
	implCode_ += xTab + xTab + vectName  + _T("_.insert(") + vectName + _T("_.begin() + i, newItem);") + xCrLf;
	implCode_ += xTab + _T("}") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// RestoreDefaults
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::RestoreDefaults()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CleanUp();") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// CleanUp
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::CleanUp()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("for (long i = 0; i < ") + vectName + _T("_.size(); i++) {") + xCrLf; 
	implCode_ += xTab + xTab + vectName + _T("_[i]->CleanUp();") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_[i]->Release();") + xCrLf;
	implCode_ += xTab + _T("}") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + vectName + _T("_.clear();") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// GetSize
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::GetSize(long* size)")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("*size = ") + vectName + _T("_.size();") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// Insert
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Insert(long index, I") + GetClassName() + _T("* ") + GetCamelCase(classInfo_->GetName()) + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CComObject<") + GetClassName() + _T(">* newItem;") + xCrLf;
	implCode_ += xCrLf;
//	implCode_ += xTab + "newItem = new CComObject<" + GetClassName() + ">;" + xCrLf;
	implCode_ += xTab + _T("CComObject<") + GetClassName() + _T(">::CreateInstance(&newItem);") + xCrLf;
	implCode_ += xTab + _T("newItem->AddRef();") + xCrLf;
	implCode_ += xTab + _T("newItem->Copy(") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	implCode_ += xTab + vectName + _T("_.insert(") + vectName + _T("_.begin() + index, newItem);") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ +=_T("}") + xCrLf;
	implCode_ += xCrLf;

	// Append
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Append(I") + GetClassName() + _T("* ") + GetCamelCase(classInfo_->GetName()) + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CComObject<") + GetClassName() + _T(">* newItem;") + xCrLf;
	implCode_ += xCrLf;
//	implCode_ += xTab + "newItem = new CComObject<" + GetClassName() + ">;" + xCrLf;
	implCode_ += xTab + _T("CComObject<") + GetClassName() + _T(">::CreateInstance(&newItem);") + xCrLf;
	implCode_ += xTab + _T("newItem->AddRef();") + xCrLf;
	implCode_ += xTab + _T("newItem->Copy(") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	implCode_ += xTab + vectName + _T("_.push_back(newItem);") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ +=_T("}") + xCrLf;
	implCode_ += xCrLf;

	// Delete
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Delete(long index)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("if (index >= 0 && index < ") + vectName + _T("_.size()) {") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_[index]->CleanUp();") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_[index]->Release();") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_.erase(") + vectName + _T("_.begin() + index);") + xCrLf;
	implCode_ += xTab + _T("}") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// GetItem
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::GetItem(long index, I") + GetClassName(n) + _T("** retval)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("if (index >= 0 && index < ") + vectName + _T("_.size())") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_[index]->QueryInterface(IID_I") + GetClassName(n) + _T(", (void**)retval);") + xCrLf;
	implCode_ += xTab + _T("else") + xCrLf;
	implCode_ += xTab + xTab + _T("*retval = NULL;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + p + _T("::SetDefaults()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("RestoreDefaults();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + p + _T("::Clear()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("CleanUp();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	//////////////////////////////////////////////////////////////////////
	// loadFromFile
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Load(BSTR fileName, VARIANT_BOOL* retval)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("USES_CONVERSION;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("bool ret;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("ret = LoadFromXmlFile(W2T(fileName));") + xCrLf;
	implCode_ += xTab + _T("*retval = ret ? VARIANT_TRUE : VARIANT_FALSE;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	//////////////////////////////////////////////////////////////////////
	// saveToFile
	//
	implCode_ += _T("STDMETHODIMP ") + GetClassName() + p + _T("::Save(BSTR fileName, VARIANT_BOOL* retval)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("USES_CONVERSION;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("bool ret;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("ret = SaveToXmlFile(W2T(fileName));") + xCrLf;
	implCode_ += xTab + _T("*retval = ret ? VARIANT_TRUE : VARIANT_FALSE;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("return S_OK;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

}

void CAtlClassArrayGenerator::Impl_generateSerialization()
{
	ClassMemberMap::iterator it;
	cmString p;
	cmString arrayName;
	
	p = GetCardinalityPostfix(classInfo_);
	arrayName = GetCamelCase(classInfo_->GetName()) + p;

	//////////////////////////////////////////////////////////////////////
	// BuildFromXml
	//
	implCode_ += _T("bool ") + GetClassName() + p + _T("::BuildFromXml(IXMLDOMNode*node)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("USES_CONVERSION;") + xCrLf + xCrLf;

	implCode_ += xTab + _T("IXMLDOMNode* childNode;") + xCrLf;
    implCode_ += xTab + _T("IXMLDOMNodeList* children;") + xCrLf;
	implCode_ += xTab + _T("CComBSTR nodeName;") + xCrLf;
	implCode_ += xTab + _T("long size;") + xCrLf;
	implCode_ += xTab + _T("HRESULT hr;") + xCrLf;
	implCode_ += xTab + _T("cmString tmp;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("SetDefaults();") + xCrLf;
	implCode_ += xCrLf;

	implCode_ += xTab + _T("hr = node->get_childNodes(&children);") + xCrLf;
	implCode_ += xTab + _T("hr = children->get_length(&size);") + xCrLf;
	implCode_ += xTab + _T("for (long i = 0; i < size; i++) {") + xCrLf;
	implCode_ += xTab + xTab + _T("hr = children->get_item(i, &childNode);") + xCrLf;
	implCode_ += xTab + xTab + _T("hr = childNode->get_nodeName(&nodeName);") + xCrLf;
	implCode_ += xTab + xTab + _T("tmp = nodeName;")+ xCrLf;
	implCode_ += xTab + xTab + _T("if (") + GetClassName() + _T("::xmlNodeName_.CompareNoCase(tmp) == 0) {") + xCrLf;
	implCode_ += xTab + xTab + xTab + _T("CComObject<") + GetClassName() + _T(">* newItem;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + xTab + xTab + _T("CComObject<") + GetClassName() + _T(">::CreateInstance(&newItem);") + xCrLf;
	implCode_ += xTab + xTab + xTab + _T("newItem->AddRef();") + xCrLf;
	implCode_ += xTab + xTab + xTab + _T("newItem->BuildFromXml(childNode);") + xCrLf;
	implCode_ += xTab + xTab + xTab + arrayName + _T("_.push_back(newItem);") + xCrLf;
	implCode_ += xTab + xTab + _T("}") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("}") + xCrLf + xCrLf;

	implCode_ += xTab + _T("return true;") + xCrLf;

	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	//////////////////////////////////////////////////////////////////////
	// AppendToDOMDocument
	//
	implCode_ += _T("bool ") + GetClassName() + p + _T("::AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	if (classInfo_->GetCardinalityInfo()->GetUseContainerNode()) {
		implCode_ += xTab + _T("IXMLDOMElement* newElement;") + xCrLf;
		implCode_ += xTab + _T("HRESULT hr;") + xCrLf;
		implCode_ += xCrLf;
		implCode_ += xTab + _T("hr = xmlDoc->createElement(CComBSTR((const TCHAR*)GetXmlNodeName()), &newElement);") + xCrLf;
		implCode_ += xTab + _T("if (FAILED(hr))") + xCrLf;
		implCode_ += xTab + xTab + _T("return false;") + xCrLf;
		implCode_ += xCrLf;	
		implCode_ += xTab + _T("for (int i = 0; i < ") + arrayName + _T("_.size(); i++)") + xCrLf;
		implCode_ += xTab + xTab + arrayName + _T("_[i]->AppendToDOMDocument(xmlDoc, newElement);") + xCrLf;
		implCode_ += xCrLf;
		implCode_ += xTab + _T("if (parentElement)") + xCrLf;
		implCode_ += xTab + xTab + _T("hr = parentElement->appendChild(newElement, NULL);") + xCrLf;
		implCode_ += xTab + _T("else") + xCrLf;
		implCode_ += xTab + xTab + _T("hr = xmlDoc->appendChild(newElement, NULL);") + xCrLf;
		implCode_ += xCrLf;
	} else {
		implCode_ += xCrLf;
		implCode_ += xTab + _T("for (int i = 0; i < ") + arrayName + _T("_.size(); i++)") + xCrLf;
		implCode_ += xTab + xTab + arrayName + _T("_[i]->AppendToDOMDocument(xmlDoc, parentElement);") + xCrLf;
		implCode_ += xCrLf;
	}
	
	implCode_ += xTab + _T("return true;") + xCrLf;
	implCode_ += _T("}") + xCrLf + xCrLf;
}