// CCppClassGenerator.cpp
//
#include "stdafx.h"
#include "CppClassGenerator.h"
#include "XmlProjectSettings.h"
#include "XmlClassInfo.h"
#include "XmlMemberInfo.h"
#include "XmlProject.h"
#include "XmlMemberValidation_StaticEnum.h"
#include "XmlMemberValidation_StaticEnumItem.h"

CCppClassGenerator::CCppClassGenerator()
{}

CCppClassGenerator::~CCppClassGenerator()
{}

void CCppClassGenerator::Generate()
{
	// generate header file
	//
	GenerateHeader();
	
	// generate implementation file
	//
	GenerateImplementation();
}
	
void CCppClassGenerator::GenerateHeader()
{
	cmString fileName;
	cmString pathName;
	
	Head_generateHeader();
	Head_generateIfDefBegin();
	Head_generateIncludeSection();
	Head_generateForwardDecl();
	Head_generateClassBegin();
	Head_generateConstructor();
	Head_generateDestructor();
	Head_generateEnumDeclaration();
	Head_generateUtils();
	Head_generateSerialization();
	Head_generateGetSet();
	Head_generateMembers();
	Head_generateClassEnd();
	Head_generateIfDefEnd();

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

	hGeneratedFiles_[fileName] = pathName + fileName;
}

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

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

void CCppClassGenerator::Head_generateIncludeSection()
{
	headCode_ += _T("#include <string>") + xCrLf;
	headCode_ += _T("#include \"XmlSerializable.h\"") + xCrLf;
	headCode_ += _T("#include \"cmString.h\"") + xCrLf;
	// include children header files
	//
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* member;
	CXmlClassInfo* classInfo;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		member = it->second;
	
		if (member->GetDataType() == enDataType_Class) {
			cmString name;
			cmString p;

			classInfo = dynamic_cast<CXmlClassInfo*>(member);
			if (!classInfo->GetDefinitionInheritance()) {
				name = member->GetName();
				p = GetCardinalityPostfix(member);
			} else {
				CXmlClassInfo* inheritClassInfo;

				inheritClassInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				name = inheritClassInfo->GetName();
				p = GetCardinalityPostfix(inheritClassInfo);
			}

			headCode_ += _T("#include \"") + GetClassName(name) + p + _T(".h\"");
			headCode_ += xCrLf;
		}
	}

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

void CCppClassGenerator::Head_generateForwardDecl()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* member;

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

			classInfo = dynamic_cast<CXmlClassInfo*>(member);
			if (classInfo->GetDefinitionInheritance()) {
				inheritClassInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				name = inheritClassInfo->GetName();
			} else {
				name = classInfo->GetName();
			}
			headCode_ += _T("class ") + GetClassName(name) + _T(";") + xCrLf;
		}
	}

	headCode_ += xCrLf;
}

void CCppClassGenerator::Head_generateClassBegin()
{
	headCode_ += _T("class AFX_EXT_CLASS ") + GetClassName() + _T(": public CXmlSerializable") + xCrLf;
	headCode_ += _T("{") + xCrLf;
}

void CCppClassGenerator::Head_generateConstructor()
{
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + GetClassName() + _T("();") + xCrLf;
	headCode_ += xTab + GetClassName() + _T("(const ") + GetClassName() + _T("& copy);") + xCrLf;
}

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

void CCppClassGenerator::Head_generateUtils()
{
	headCode_ += xTab + _T("// utils") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + _T("void operator=(const ") + GetClassName() + _T("& copy);") + xCrLf + xCrLf;
	headCode_ += xTab + _T("void SetDefaults();")  + xCrLf;
	headCode_ += xTab + _T("void Clear();")  + xCrLf;
	headCode_ += xTab + _T("virtual cmString GetXmlNodeName(){return _T(\"") + classInfo_->GetName() + _T("\");}") + xCrLf;
	headCode_ += xCrLf;
	headCode_ += _T("protected:") + xCrLf;
	headCode_ += xTab + _T("void Copy(const ") + GetClassName() + _T("& copy);")  + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassGenerator::Head_generateGetSet()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	cmString p;

	headCode_ += xTab + _T("// Get/Set methods") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("public:") + xCrLf + xCrLf;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
			
		if (element->GetDataType() == enDataType_Class) {
			CXmlClassInfo* classInfo;
			//CXmlClassInfo* inheritClassInfo;
			cmString name;

			classInfo = dynamic_cast<CXmlClassInfo*>(element);
			/* COMMENTED 2004.12.11
			if (classInfo->GetDefinitionInheritance()) {
				inheritClassInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				name = inheritClassInfo->GetName();
				p = GetCardinalityPostfix(inheritClassInfo);
			} else {
				name = classInfo->GetName();
				p = GetCardinalityPostfix(classInfo);
			}*/
			
			if (classInfo->GetDefinitionInheritance())
				classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
			
			name = classInfo->GetName();
			p = GetCardinalityPostfix(classInfo);

			headCode_ += xTab + GetClassName(name) + p + _T("& ");
			//headCode_ += "Get" + name + p + "();" + xCrLf;
			headCode_ += _T("Get") + name + p + _T("();") + xCrLf; // 2004.11.18

			//headCode_ += xTab + "void Set" + name + p + "(";
			headCode_ += xTab + _T("void Set") + name + p + _T("("); // 2004.11.18
			headCode_ += GetClassName(name) + p + _T("& ");
			headCode_ += name + p + _T(");") + xCrLf;
			headCode_ += xCrLf;

		} else {
			cmString type;
			CXmlMemberInfo* member;

			member = dynamic_cast<CXmlMemberInfo*>(element);

			if (member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				type = _T("en") + member->GetName();
				headCode_ += xTab + type + _T(" Get") + element->GetName() + _T("() const;") + xCrLf;
				headCode_ += xTab + TypeOf(member->GetDataType()) + _T(" Get") + member->GetName() + _T("_Value() const;") + xCrLf;
				headCode_ += xTab + _T("void Set") + member->GetName() + _T("(") + type + _T(" ") + member->GetName() + _T(");") + xCrLf; 
			} else {
				type = TypeOf(member->GetDataType());
				headCode_ += xTab + type + _T(" Get") + member->GetName() + _T("() const;") + xCrLf;
				if (element->GetDataType() == enDataType_String)
					headCode_ += xTab + _T("void Set") + member->GetName() + _T("(const ") + type + _T("& ") + member->GetName() + _T(");") + xCrLf;
				else
					headCode_ += xTab + _T("void Set") + member->GetName() + _T("(") + type + _T(" ") + member->GetName() + _T(");") + xCrLf;

				if (IsSmartLong(member)) {
					headCode_ += xTab + _T("void __SetHexDisplay_") + member->GetName() + _T("(bool hexDisplay);") + xCrLf;
					headCode_ += xTab + _T("bool __GetHexDisplay_") + member->GetName() + _T("() const;") + xCrLf;
				}

			}
			
			headCode_ += xCrLf;
		}
	}
}

void CCppClassGenerator::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_ += xCrLf;
}

void CCppClassGenerator::Head_generateMembers()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	
	headCode_ += xTab + _T("// inner members") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("protected:") + xCrLf;

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

			classInfo = dynamic_cast<CXmlClassInfo*>(element);
			if (classInfo->GetDefinitionInheritance()) {
				CXmlClassInfo* inheritClassInfo;

				inheritClassInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				name = inheritClassInfo->GetName();
				p = GetCardinalityPostfix(inheritClassInfo);
			} else {
				name = classInfo->GetName();
				p = GetCardinalityPostfix(element);
			}

			headCode_ += xTab + GetClassName(name) + p + _T(" ");
			headCode_ += GetCamelCase(name) + p + _T("_;") + xCrLf;
		} else {
			CXmlMemberInfo* member;

			member = dynamic_cast<CXmlMemberInfo*>(element);

			if (member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				headCode_ += xTab + _T("en") + member->GetName() + _T(" ") + GetCamelCase(element->GetName()) + _T("_;") + xCrLf;
			} else {
				cmString type;

				type = TypeOf(element->GetDataType());

				headCode_ += xTab + type + _T(" ") + GetCamelCase(element->GetName()) + _T("_;") + xCrLf;
				if (IsSmartLong(member))
					headCode_ += xTab + _T("bool __hexDisplay_") + element->GetName() + _T("_;") + xCrLf;
			}
		}
	}
}

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

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

void CCppClassGenerator::GenerateImplementation()
{
	cmString fileName;
	cmString pathName;
	
	Impl_generateHeader();
	Impl_generateIncludeSection();
	
	Impl_generateConstructor();
	Impl_generateDestructor();
	Impl_generateUtils();
	Impl_generateGetSet();
	Impl_generateSerialization();

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

	cppGeneratedFiles_[fileName] = pathName + fileName;
}

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

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

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

	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())
				implCode_ += _T("#include \"") + GetClassName(classInfo->GetName()) + _T(".h\"") + xCrLf;
		}
	}

	implCode_ +=  xCrLf;
}

void CCppClassGenerator::Impl_generateConstructor()
{
	// default constructor
	//
	implCode_ += GetClassName() + _T("::") + GetClassName() + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("SetDefaults();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// copy constructor
	//
	implCode_ += GetClassName() + _T("::") + GetClassName() + _T("(const ") + GetClassName() + _T("& ") + GetCamelCase(classInfo_->GetName()) + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Copy(") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassGenerator::Impl_generateDestructor()
{
	implCode_ += GetClassName() + _T("::~") + GetClassName() + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassGenerator::Impl_generateUtils()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	CXmlMemberInfo* member;
	CXmlClassInfo* classInfo;
	cmString p;
	cmString name;

	// operator =
	//
	implCode_ += _T("void ") +  GetClassName() + _T("::operator=(const ") + GetClassName() + _T("& ") + GetCamelCase(classInfo_->GetName()) + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Copy(") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// copy
	//
	implCode_ += _T("void ") + GetClassName() + _T("::Copy(const ") + GetClassName() + _T("& ") + GetCamelCase(classInfo_->GetName()) + _T(")")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	implCode_ += xCrLf;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;

		if (element->GetDataType() == enDataType_Class) {
			classInfo = dynamic_cast<CXmlClassInfo*>(element);
			if (classInfo->GetDefinitionInheritance()) {
				classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
			}
			p = GetCardinalityPostfix(classInfo);
			name = classInfo->GetName();
			implCode_ += xTab + GetCamelCase(name) + p + _T("_ = ") + GetCamelCase(classInfo_->GetName()) + _T(".") + GetCamelCase(name) + p + _T("_;") + xCrLf;
		} else {
			if (IsSmartLong(dynamic_cast<CXmlMemberInfo*>(element)))
				implCode_ += xTab + _T("__hexDisplay_") + element->GetName() + _T("_ = ") + GetCamelCase(classInfo_->GetName()) + _T(".__hexDisplay_") + element->GetName() + _T("_;") + xCrLf;
			implCode_ += xTab + GetCamelCase(element->GetName()) + _T("_ = ") + GetCamelCase(classInfo_->GetName()) + _T(".") + GetCamelCase(element->GetName()) + _T("_;") + xCrLf;
		}
	}
	implCode_ +=_T("}") + xCrLf;
	implCode_ += xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + _T("::SetDefaults()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
		member = dynamic_cast<CXmlMemberInfo*>(element);

		if (member == NULL)
			continue;

		if (member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
			
			implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = (en") + member->GetName() + _T(")0;") + xCrLf;

		} else	{
			switch (member->GetDataType()) {
				case enDataType_Class:
					classInfo = dynamic_cast<CXmlClassInfo*>(member);
					if (classInfo->GetDefinitionInheritance()) {
						classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
					}
					p = GetCardinalityPostfix(classInfo);
					name = classInfo->GetName();
					implCode_ += xTab + GetCamelCase(name) + p + _T("_.SetDefaults();") + xCrLf;
					break;

				case enDataType_Long:
					if (IsSmartLong(member))
						implCode_ += xTab + _T("__hexDisplay_") + member->GetName() + _T("_ = false;") + xCrLf;
				case enDataType_Double:
					implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = 0;") + xCrLf;
					break;

				case enDataType_Boolean:
					implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = false;") + xCrLf;
					break;

				case enDataType_String:
					implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = _T(\"\");") + xCrLf;
					break;
			}
		}
	}
	implCode_ += _T("}") + xCrLf + xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + _T("::Clear()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
	
		if (element->GetDataType() == enDataType_Class) {
			classInfo = dynamic_cast<CXmlClassInfo*>(element);
			if (classInfo->GetDefinitionInheritance())
				classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
			p = GetCardinalityPostfix(classInfo);
			implCode_ += xTab + GetCamelCase(classInfo->GetName()) + p + _T("_.Clear();") + xCrLf;
		}
	}

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

void CCppClassGenerator::Impl_generateGetSet()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	cmString type;
	cmString name;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
	
		if (element->GetDataType() == enDataType_Class) {
			CXmlClassInfo* classInfo;
			CXmlClassInfo* inheritClassInfo;
			cmString name;
			cmString p;

			classInfo = dynamic_cast<CXmlClassInfo*>(element);
			if (classInfo->GetDefinitionInheritance()) {
				inheritClassInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				name = inheritClassInfo->GetName();
				p = GetCardinalityPostfix(inheritClassInfo);
			} else {
				name = classInfo->GetName();
				p = GetCardinalityPostfix(element);
			}

			type = GetClassName(name) + p;	
			
			implCode_ += type + _T("& ") + GetClassName() + _T("::Get") + name + p + _T("()") + xCrLf;
			implCode_ += _T("{") + xCrLf;
			implCode_ += xTab + _T("return ") + GetCamelCase(name) + p + _T("_;") + xCrLf;
			implCode_ += _T("}") + xCrLf;
			implCode_ += xCrLf;

			implCode_ += _T("void ") + GetClassName() + _T("::Set") + name + p + _T("(") + type + _T("& ") + GetCamelCase(name) + p + _T(")") + xCrLf;
			implCode_ += _T("{") + xCrLf;
			implCode_ += xTab + GetCamelCase(name) + p + _T("_ = ") + GetCamelCase(name) + p + _T(";") + xCrLf;
			implCode_ += _T("}") + xCrLf;
			implCode_ += xCrLf;

			
		} else {
			CXmlMemberInfo* member;
			
			member = dynamic_cast<CXmlMemberInfo*>(element);

			if (member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				CXmlMemberValidation_StaticEnum* staticEnum;
				CXmlMemberValidation_StaticEnumItem* item;
				StaticEnumItems* items;
								
				staticEnum = member->GetValidationInfo()->GetStaticEnum();
				items = staticEnum->GetItems();

				type = _T("en") + member->GetName();

				implCode_ += GetClassName() + _T("::") + type + _T(" ") + GetClassName() + _T("::Get") + member->GetName() + _T("() const") + xCrLf;
				implCode_ += _T("{") + xCrLf;
				implCode_ += xTab + _T("return ") + GetCamelCase(member->GetName()) + _T("_;") + xCrLf;
				implCode_ += _T("}") + xCrLf;
				implCode_ += xCrLf;

				implCode_ += _T("void ")+ GetClassName() + _T("::Set") + member->GetName() + _T("(") + GetClassName() + _T("::") + type + _T(" ") + GetCamelCase(member->GetName()) + _T(")") + xCrLf;
				implCode_ += _T("{") + xCrLf;
				implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = ") + GetCamelCase(member->GetName()) + _T(";") + xCrLf;
				implCode_ += _T("}") + xCrLf;
				implCode_ += xCrLf;

				implCode_ += TypeOf(member->GetDataType()) + _T(" ") + GetClassName() + _T("::Get") + member->GetName() + _T("_Value() const") + xCrLf;
				implCode_ += _T("{") + xCrLf;
				implCode_ += xTab + TypeOf(member->GetDataType()) + _T(" ret;") + xCrLf;
				implCode_ += xCrLf;
				implCode_ += xTab + _T("switch(")+ GetCamelCase(member->GetName()) + _T("_) {") + xCrLf;
				
				for (int i = 0; i < items->size(); i++) {
					item = (*items)[i];

					implCode_ += xTab + xTab + _T("case en") + member->GetName() + _T("_") + item->GetItemName() + _T(":") + xCrLf;
					if (member->GetDataType() == enDataType_String)
						implCode_ += xTab + xTab + xTab + _T("ret = _T(\"") + item->GetItemValue() + _T("\");") + xCrLf;
					else
						implCode_ += xTab + xTab + xTab + _T("ret = ") + item->GetItemValue() + _T(";") + xCrLf;
					implCode_ += xTab + xTab + xTab + _T("break;") + xCrLf;
					implCode_ += xCrLf;
				}

				implCode_ += xTab + _T("}") + xCrLf;
				implCode_ += xTab + _T("return ret;") + xCrLf;
				implCode_ += _T("}") + xCrLf;
				implCode_ += xCrLf;	
			} else {
				type = TypeOf(member->GetDataType());

				implCode_ += type + _T(" ") + GetClassName() + _T("::Get") + member->GetName() + _T("() const") + xCrLf;
				implCode_ += _T("{") + xCrLf;
				implCode_ += xTab + _T("return ") + GetCamelCase(member->GetName()) + _T("_;") + xCrLf;
				implCode_ += _T("}") + xCrLf + xCrLf;

				if (member->GetDataType() == enDataType_String)
					implCode_ += _T("void ") + GetClassName() + _T("::Set") + member->GetName() + _T("(const ") + type + _T("& ") + GetCamelCase(member->GetName()) + _T(")") + xCrLf;
				else
					implCode_ += _T("void ") + GetClassName() + _T("::Set") + member->GetName() + _T("(") + type + _T(" ") + GetCamelCase(member->GetName()) + _T(")") + xCrLf;
				
				implCode_ += _T("{") + xCrLf;
				implCode_ += xTab + GetCamelCase(member->GetName()) + _T("_ = ") + GetCamelCase(member->GetName()) + _T(";") + xCrLf;
				implCode_ += _T("}") + xCrLf + xCrLf;


				if (IsSmartLong(member)) {
					implCode_ += _T("void ") + GetClassName() + _T("::__SetHexDisplay_") + member->GetName() + _T("(bool hexDisplay)") + xCrLf;
					implCode_ += _T("{") + xCrLf;
					implCode_ += xTab + _T("__hexDisplay_") + member->GetName() + _T("_ = hexDisplay;") + xCrLf;
					implCode_ += _T("}") + xCrLf + xCrLf;

					implCode_ += _T("bool ") + GetClassName() + _T("::__GetHexDisplay_") + member->GetName() + _T("() const") + xCrLf;
					implCode_ += _T("{") + xCrLf;
					implCode_ += xTab + _T("return __hexDisplay_") + member->GetName() + _T("_;") + xCrLf;
					implCode_ += _T("}") + xCrLf + xCrLf;

				}

			}
		}

		

	}
}

void CCppClassGenerator::Impl_generateSerialization()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	CXmlMemberInfo* member;
	CXmlClassInfo* classInfo;
	cmString buf;
	cmString p;
	cmString name;
	
	//////////////////////////////////////////////////////////////////////
	// BuildFromXml
	//
	implCode_ += _T("bool ") + GetClassName() + _T("::BuildFromXml(IXMLDOMNode* node)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("cmString tmp;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("SetDefaults();") + xCrLf;
	implCode_ += xCrLf;
	members = classInfo_->GetMembers();
	
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
	
		if (element->GetDataType() == enDataType_Class) {
			enCardinality c;

			classInfo = dynamic_cast<CXmlClassInfo*>(element);	
			if (classInfo->GetDefinitionInheritance())
				classInfo = dynamic_cast<CXmlClassInfo*>(project_->GetRootElement()->GetMemberById(classInfo->GetInherithClassId()));
			
			p = GetCardinalityPostfix(classInfo);
			c = classInfo->GetCardinalityInfo()->GetCardinality();

			if ((c == enCardinality_Map || c == enCardinality_Array) && !classInfo->GetCardinalityInfo()->GetUseContainerNode()) {
				implCode_ += xTab + GetCamelCase(classInfo->GetName()) + p + _T("_.BuildFromXml(node);") + xCrLf;
			} else {
				implCode_ += xTab + _T("ExtractMemberNode(node, _T(\"") + classInfo->GetName() + p + _T("\"), ") + GetCamelCase(classInfo->GetName()) + p + _T("_);") + xCrLf;;
			}
		} else {
			member = dynamic_cast<CXmlMemberInfo*>(element);
			
			switch (member->GetPersistenceMode()) {
				case enPersistenceMode_AsChildNode:
					if (IsSmartLong(member)) {
						implCode_ += xTab + _T("ExtractMemberNode(node, _T(\"") + element->GetName() + _T("\"), tmp);") + xCrLf;
						implCode_ += xTab + _T("__hexDisplay_") + element->GetName() + _T("_ = tmp.IsHexadecimalNumber();") + xCrLf;
						implCode_ += xTab + _T("if (tmp.IsHexadecimalNumber())") + xCrLf;
						implCode_ += xTab + xTab + GetCamelCase(element->GetName()) + _T("_ = tmp.HexStringToNumber();") + xCrLf;
						implCode_ += xTab + _T("else") + xCrLf;
						implCode_ += xTab + xTab + GetCamelCase(element->GetName()) + _T("_ = (long)tmp;") + xCrLf;
					} else {
						implCode_ += xTab + _T("ExtractMemberNode(node, _T(\"") + element->GetName() + _T("\"), ");
						if (member && member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
							// enum values need cast to int
							//
							implCode_ += _T("(int&)");
						} 
						implCode_ += GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
					}
					break;

				case enPersistenceMode_AsAttribute:
					if (IsSmartLong(member)) {
						implCode_ += xTab + _T("ExtractAttributeNode(node, _T(\"") + element->GetName() + _T("\"), tmp);") + xCrLf;
						implCode_ += xTab + _T("__hexDisplay_") + element->GetName() + _T("_ = tmp.IsHexadecimalNumber();") + xCrLf;
						implCode_ += xTab + _T("if (tmp.IsHexadecimalNumber())") + xCrLf;
						implCode_ += xTab + xTab + GetCamelCase(element->GetName()) + _T("_ = tmp.HexStringToNumber();") + xCrLf;
						implCode_ += xTab + _T("else") + xCrLf;
						implCode_ += xTab + xTab + GetCamelCase(element->GetName()) + _T("_ = (long)tmp;") + xCrLf;
					} else {
						implCode_ += xTab + _T("ExtractAttributeNode(node, _T(\"") + element->GetName() + _T("\"), ");
						if (member && member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
							// enum values need cast to int
							//
							implCode_ += _T("(int&)");
						} 
						implCode_ += GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
					}
					break;

				case enPersistenceMode_AsTextNode:
					implCode_ += xTab + _T("ExtractTextNode(node, ");
					if (member && member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
						// enum values need cast to int
						//
						implCode_ += _T("(int&)");
					} 
					implCode_ += GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
					break;

				case enPersistenceMode_AsCDATA:
					implCode_ += xTab + _T("ExtractCDATAMemberNode(node, ") + GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
					break;

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

	//////////////////////////////////////////////////////////////////////
	// AppendToDOMDocument
	//
	implCode_ += _T("bool ") + GetClassName() + _T("::AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
		
	implCode_ += xTab + _T("IXMLDOMElement* newElement;") + xCrLf;
	implCode_ += xTab + _T("HRESULT hr;") + xCrLf;
	implCode_ += xTab + _T("cmString tmp;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("hr = xmlDoc->createElement(CComBSTR((const TCHAR*)GetXmlNodeName()), &newElement);") + xCrLf;
	implCode_ += xCrLf;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;
	
		member = dynamic_cast<CXmlMemberInfo*>(element);

		switch (element->GetDataType()) {
			case enDataType_Class:
				classInfo = dynamic_cast<CXmlClassInfo*>(element);
				if (classInfo->GetDefinitionInheritance())
					classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));
				
				p = GetCardinalityPostfix(classInfo);
				name = classInfo->GetName();
				implCode_ += xTab + GetCamelCase(name) + p + _T("_.AppendToDOMDocument(xmlDoc, newElement);") + xCrLf;
				break;

			case enDataType_Double:
				switch (member->GetPersistenceMode()) {
					case enPersistenceMode_AsChildNode:
						buf.Format(_T("%d"), (dynamic_cast<CXmlMemberInfo*>(element))->GetDecimalPlaces());
						implCode_ += xTab + _T("AppendMemberNode(_T(\"") + element->GetName() + _T("\"), ") + GetCamelCase(element->GetName()) + _T("_, ") + buf + _T(", newElement, xmlDoc);") + xCrLf;	
						break;

					case enPersistenceMode_AsAttribute:
						buf.Format(_T("%d"), (dynamic_cast<CXmlMemberInfo*>(element))->GetDecimalPlaces());
						implCode_ += xTab + _T("AppendAttributeNode(_T(\"") + element->GetName() + _T("\"), ") + GetCamelCase(element->GetName()) + _T("_, ") + buf + _T(", newElement, xmlDoc);") + xCrLf;	
						break;

					case enPersistenceMode_AsTextNode:
						buf.Format(_T("%d"), (dynamic_cast<CXmlMemberInfo*>(element))->GetDecimalPlaces());
						implCode_ += xTab + _T("AppendTextNode(") + GetCamelCase(element->GetName()) + _T("_, ") + buf + _T(", newElement, xmlDoc);") + xCrLf;	
						break;

				}
				break;

			default:
				switch (member->GetPersistenceMode()) {
					case enPersistenceMode_AsChildNode:
						if (IsSmartLong(member)) {
							implCode_ += xTab + _T("if (__hexDisplay_") + element->GetName() + _T("_)") + xCrLf;
							implCode_ += xTab + xTab + _T("tmp.Format(_T(\"0x%X\"), ") + GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
							implCode_ += xTab + _T("else") + xCrLf;
							implCode_ += xTab + xTab + _T("tmp.Format(_T(\"%d\"), ") + GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
							implCode_ += xTab + _T("AppendMemberNode(_T(\"") + element->GetName() + _T("\"), tmp, newElement, xmlDoc);") + xCrLf;	
						} else {
							implCode_ += xTab + _T("AppendMemberNode(_T(\"") + element->GetName() + _T("\"), ") + GetCamelCase(element->GetName()) + _T("_, newElement, xmlDoc);") + xCrLf;	
						}
						break;
					
					case enPersistenceMode_AsAttribute:
						if (IsSmartLong(member)) {
							implCode_ += xTab + _T("if (__hexDisplay_") + element->GetName() + _T("_)") + xCrLf;
							implCode_ += xTab + xTab + _T("tmp.Format(_T(\"0x%X\"), ") + GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
							implCode_ += xTab + _T("else") + xCrLf;
							implCode_ += xTab + xTab + _T("tmp.Format(_T(\"%d\"), ") + GetCamelCase(element->GetName()) + _T("_);") + xCrLf;
							implCode_ += xTab + _T("AppendAttributeNode(_T(\"") + element->GetName() + _T("\"), tmp, newElement, xmlDoc);") + xCrLf;	
						} else {
							implCode_ += xTab + _T("AppendAttributeNode(_T(\"") + element->GetName() + _T("\"), ") + GetCamelCase(element->GetName()) + _T("_, newElement, xmlDoc);") + xCrLf;	
						}
						break;

					case enPersistenceMode_AsTextNode:
						implCode_ += xTab + _T("AppendTextNode(") + GetCamelCase(element->GetName()) + _T("_, newElement, xmlDoc);") + xCrLf;	
						break;

					case enPersistenceMode_AsCDATA:
						implCode_ += xTab + _T("AppendCDATAMemberNode(") + GetCamelCase(element->GetName()) + _T("_, newElement, xmlDoc);") + xCrLf;	
						break;
				}
		}	
	}

	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;
	implCode_ += xTab + _T("return true;") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassGenerator::Head_generateEnumDeclaration()
{
	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* element;
	CXmlMemberInfo* member;
	cmString p;
	cmString name;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		element = it->second;

		if (element->GetDataType() != enDataType_Class) {
			member = dynamic_cast<CXmlMemberInfo*>(element);
			
			if (member->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				CXmlMemberValidation_StaticEnum* staticEnum;
				CXmlMemberValidation_StaticEnumItem* item;
				StaticEnumItems* items;
				
				staticEnum = member->GetValidationInfo()->GetStaticEnum();
				
				items = staticEnum->GetItems();
				headCode_ += xTab + _T("// enum for member \"") + member->GetName() + _T("\"") + xCrLf;
				headCode_ += xTab + _T("//") + xCrLf;
				headCode_ += xTab + _T("typedef enum en") + member->GetName() + _T(" {") + xCrLf;

				for (int i = 0;i < items->size(); i++) {
					cmString tmp;

					item = (*items)[i];
					tmp.Format(_T("%ld"), item->GetItemEnumValue());

					if (i != 0)
						headCode_ += _T(",") + xCrLf;
					headCode_ += xTab + xTab + _T("en") + member->GetName() + _T("_") + item->GetEscapedItemValue();
					headCode_ += _T(" = ");
					headCode_ += tmp;
				}
				headCode_ += xCrLf;
				headCode_ += xTab + _T("};") + xCrLf;

			}
		}
		headCode_ += xCrLf;
	}
}


