#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, CUTF8String path, CUTF8String workspaceClassType)
{
	m_curNode = root;
	m_inKeyLeaf = 0;
	m_depth.RemoveAll();
	m_workspaceClassType = workspaceClassType;

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

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

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

	//	解析
	StartScan(str);

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

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

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

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

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

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

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

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

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

		m_depth.RemoveTail();

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

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

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

			m_keyData = m_curNode->GetKeyData(m_keyName, _U8(""), FALSE);
			m_keyData += strData;
		}
		else
		{
			CUTF8String	strData;
			strData.SetString(data, len);

			m_keyData += strData;
		}

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


/////////////////////////////////////////////////////////////////////////////////////
//	補助
/////////////////////////////////////////////////////////////////////////////////////
/*!
	複数の文字列と or 比較
*/
int CWorkspaceXMLReader::MultiMatch(LPCU8STR tag, LPCSTR str1, LPCSTR str2, LPCSTR str3)
{
	//	比較
	if(str1 != NULL && strcmp((LPCSTR)tag, str1) == 0)
		return(TRUE);

	//	比較
	if(str2 != NULL && strcmp((LPCSTR)tag, str2) == 0)
		return(TRUE);

	//	比較
	if(str3 != NULL && strcmp((LPCSTR)tag, str3) == 0)
		return(TRUE);

	return(FALSE);
}

