#include "StdAfx.h"
#include "WorkspaceXMLReader.h"

#define	ATTR_KEY	0
#define	ATTR_DATA	1

CWorkspaceXMLReader::CWorkspaceXMLReader(void)
{
}

CWorkspaceXMLReader::~CWorkspaceXMLReader(void)
{
}

void CWorkspaceXMLReader::LoadFromFile(CWorkspaceNode *root, CString path, CString workspaceClassType)
{
	m_curNode = root;
	m_inKeyLeaf = 0;
	m_depth.RemoveAll();
	m_workspaceClassType = workspaceClassType;

	//	解析
	StartScan(LoadXmlFile(path));

	//	最終チェック
	if(m_depth.GetCount())
		throw CXMLTextParserException(_T("Subnodeが閉じていません"), 0);
}

/*!
	XML読み込み(throw CXMLTextParserException)
*/
void CWorkspaceXMLReader::FromString(CWorkspaceNode *root, CString str, CString workspaceClassType)
{
	m_curNode = root;
	m_inKeyLeaf = 0;
	m_depth.RemoveAll();
	m_workspaceClassType = workspaceClassType;

	//	解析
	StartScan(str);

	//	最終チェック
	if(m_depth.GetCount())
		throw CXMLTextParserException(_T("Subnodeが閉じていません"), 0);
}

/////////////////////////////////////////////////////////////////////////////////////
//	実装
/////////////////////////////////////////////////////////////////////////////////////
/*!
	開始タグ
*/
void CWorkspaceXMLReader::OnStartTag(LPCSTR tag, LPCSTR *atts)
{
	//	チェック
	if(m_inKeyLeaf)
		throw CXMLTextParserException(_T("Key内にタグは記述できません"), 0);

	//	タグ種別
	if(_tcscmp(tag, _T("CWorkspaceClass")) == 0 || _tcscmp(tag, _T("CConfigClass")) == 0)	//	開始
	{
		//	開始位置チェック
		if(m_depth.GetCount() != 0)
			throw CXMLTextParserException(_T("無効なCWorkspaceClassタグです"), 0);

		//	タイプチェック
		if(GetAttrCount(atts) != 2 || _tcscmp(atts[ATTR_KEY], _T("type")) != 0)
			throw CXMLTextParserException(_T("無効なCWorkspaceClassタグです"), 0);

		//	クラス名チェック
		if(_tcscmp(atts[ATTR_DATA], m_workspaceClassType) != 0)
			throw CXMLTextParserException(_T("ワークスペース名が異なります、ロードできません"), 0);
	}
	else if(_tcscmp(tag, _T("Subnode")) == 0 || _tcscmp(tag, _T("Node")) == 0)	//	ノード
	{
		//	タイプチェック
		if(GetAttrCount(atts) != 2 || _tcscmp(atts[ATTR_KEY], _T("name")) != 0)
			throw CXMLTextParserException(_T("無効なSubnodeタグです"), 0);

		//	最上位？
		if(m_depth.GetCount() == 0)
		{
			//	クラス名チェック
			if(_tcscmp(atts[ATTR_DATA], m_workspaceClassType) != 0)
				throw CXMLTextParserException(_T("ワークスペース名が異なります、ロードできません"), 0);
			else
				m_depth.AddHead(m_curNode);
		}
		else
		{
			//	追加
			m_curNode = m_curNode->GetSubNodeByName(atts[ATTR_DATA], TRUE); 
			if(m_curNode == NULL)
				throw CXMLTextParserException(_T("同名のSubnodeが存在します"), 0);
			m_depth.AddHead(m_curNode);
		}
	}
	else if(_tcscmp(tag, _T("Key")) == 0 || _tcscmp(tag, _T("Leaf")) == 0)	//	キー
	{
		//	チェック
		if(m_depth.GetCount() == 0 || GetAttrCount(atts) != 2 || 
			(_tcscmp(atts[ATTR_KEY], _T("name")) != 0 && _tcscmp(atts[ATTR_KEY], _T("key")) != 0))
			throw CXMLTextParserException(_T("無効なKeyタグです"), 0);

		m_inKeyLeaf = 1;
		m_onDataCount = 0;
		m_keyName = atts[ATTR_DATA];
		m_keyData.Empty();
	}
	else	//	エラー
	{
		throw CXMLTextParserException(_T("無効なタグです"), 0);
	}
}

/*!
	終了タグ
*/
void CWorkspaceXMLReader::OnEndTag(LPCSTR tag)
{
	//	タグ種別
	if(_tcscmp(tag, _T("CWorkspaceClass")) == 0 || _tcscmp(tag, _T("CConfigClass")) == 0)	//	開始
	{
		//	チェック
		if(m_inKeyLeaf)
			throw CXMLTextParserException(_T("Key内にタグは記述できません"), 0);
	}
	else if(_tcscmp(tag, _T("Subnode")) == 0 || _tcscmp(tag, _T("Node")) == 0)	//	ノード
	{
		//	チェック
		if(m_inKeyLeaf)
			throw CXMLTextParserException(_T("Key内にタグは記述できません"), 0);

		//	ノード深さチェック
		if(m_depth.GetCount() <= 0)
			throw CXMLTextParserException(_T("Subnodeタグの対応が異常です"), 0);

		m_depth.RemoveHead();

		//	最上位？
		if(m_depth.GetCount() != 0)
			m_curNode = m_depth.GetHead();
		else
			m_curNode = NULL;
	}
	else if(_tcscmp(tag, _T("Key")) == 0 || _tcscmp(tag, _T("Leaf")) == 0)	//	キー
	{
		//	チェック
		if(!m_inKeyLeaf)
			throw CXMLTextParserException(_T("無効な終了タグです"), 0);

		//	必要なら再設定
		if(m_onDataCount >= 2)
			m_curNode->SetKeyData(m_keyName, m_keyData, FALSE);
		m_onDataCount = 0;
		m_inKeyLeaf = 0;
	}
	else	//	エラー
	{
		throw CXMLTextParserException(_T("無効なタグです"), 0);
	}
}

/*!
	データ
*/
void CWorkspaceXMLReader::OnData(const CHAR *data, int len)
{
	if(m_inKeyLeaf)
	{
		//	再度呼び出し？
		if(m_onDataCount == 0)
			m_curNode->SetKeyData(m_keyName, m_sjis.ToCString(data, len), FALSE);
		else if(m_onDataCount == 1)
		{
			m_keyData = m_curNode->GetKeyData(m_keyName, "", FALSE);
			m_keyData += m_sjis.ToCString(data, len);
		}
		else
			m_keyData += m_sjis.ToCString(data, len);

		//	呼び出しカウント
		m_onDataCount++;
	}
}

