#include "StdAfx.h"
#include ".\workspacenode.h"

//////////////////////////////////////////////////////////////////////////////////////////
//	初期化など
//////////////////////////////////////////////////////////////////////////////////////////
CWorkspaceNode::CWorkspaceNode(void)
{
}

CWorkspaceNode::CWorkspaceNode(CString name)
{
	m_nodeName = name;
}

CWorkspaceNode::~CWorkspaceNode(void)
{
}

//	コピーオペレータ
void CWorkspaceNode::operator=(const CWorkspaceNode &other)
{
	//	データのコピー
	m_nodeName = other.m_nodeName;
	m_keyData.Copy(other.m_keyData);
	m_subNode.Copy(other.m_subNode);
}

//	全てクリア
void CWorkspaceNode::Clear(void)
{
	//	データ削除
	m_keyData.RemoveAll();
	m_subNode.RemoveAll();
}


//////////////////////////////////////////////////////////////////////////////////////////
//	Keyに対する処理(Public)
//////////////////////////////////////////////////////////////////////////////////////////
/*!
	データの設定

	このノードのデータに対するアクセス
*/
void CWorkspaceNode::SetKeyData(CString key, CString data, int noCase)
{
	int	index = FindKeyIndex(key,noCase);
	if(index == -1)
	{
		m_keyData.Add(key,data);
	}
	else
	{
		m_keyData[index].m_data = data;
	}
}

/*!
	データの取得

	このノードのデータに対するアクセス
*/
CString CWorkspaceNode::GetKeyData(CString key, CString defaultData, int noCase)
{
	int	index = FindKeyIndex(key,noCase);
	if(index == -1)
	{
		return(defaultData);
	}
	else
	{
		return(m_keyData[index].m_data);
	}
}


/*!
	データの削除

	このノードのデータに対するアクセス
*/
void CWorkspaceNode::DeleteKey(CString key)
{
	int index = FindKeyIndex(key,FALSE);
	if(index != -1)
		m_keyData.RemoveAt(index);
}


/*!
	キー数を取得
*/
int CWorkspaceNode::GetKeyCount()
{
	return((int)m_keyData.GetSize());
}

/*!
	全てのキーを文字列として取得
*/
int CWorkspaceNode::GetAllKey(IStringArrayPtr list)
{
	//	サイズ初期化
	int count = (int)m_keyData.GetSize();
	list->SetSize(count);

	//	設定
	for(int i=0;i<count;i++)
		list->SetString(i, m_keyData[i].m_key);

	return(count);
}

/*!
	全てのデータを文字列として取得
*/
int CWorkspaceNode::GetAllData(IStringArrayPtr list)
{
	//	サイズ初期化
	int count = (int)m_keyData.GetSize();
	list->SetSize(count);

	//	設定
	for(int i=0;i<count;i++)
		list->SetString(i, m_keyData[i].m_data);

	return(count);
}



/*!
	キーを検索

	\param	pathCompare	左からの部分一致を許可
*/
int CWorkspaceNode::FindKeyData(CString sData, int noCase, int pathCompare)
{
	if(pathCompare)
	{
		//	比較
		for(int i=0;i<m_keyData.GetCount();i++)
		{
			if(m_keyData[i].m_data.CompareNoCase(sData.Left(m_keyData[i].m_data.GetLength())) == 0)
				return(i);
		}

		return(-1);
	}
	else
		return(m_keyData.Find(sData, noCase));
}
	

/*!
	キーをまとめて設定
*/
void CWorkspaceNode::ClearAndSetKeys(CStringArray &keys, CStringArray &datas)
{
	Clear();

	//	サイズ変更
	m_keyData.SetSize(keys.GetSize());

	//	設定
	for(int i=0;i<keys.GetSize();i++)
	{
		m_keyData[i].m_key = keys[i];
		m_keyData[i].m_data = datas[i];
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
//	Keyに対する処理(Protect)
//////////////////////////////////////////////////////////////////////////////////////////
/*!
	Leafの検索
*/
int CWorkspaceNode::FindKeyIndex(CString &key,int noCase)
{
	return(m_keyData.Find(key, noCase));
}

//////////////////////////////////////////////////////////////////////////////////////////
//	サブノードに対する処理(Public)
//////////////////////////////////////////////////////////////////////////////////////////
/*!
	サブノードを検索する
*/
CWorkspaceNode *CWorkspaceNode::GetSubNode(CString path, CString &key)
{
	CString	topPath,subPath;
	if(ParsePath(path,topPath,subPath) == 0)
	{
		//	自分
		key = subPath;
		return this;
	}
	else
	{
		//	自分のサブノードを検索
		int index = FindSubNodeIndex(topPath);
		if(index == -1)
		{
			//	無いから、追加
			index = (int)m_subNode.GetSize();
			m_subNode.Add(CWorkspaceNode(topPath));
		}

		return(m_subNode[index].GetSubNode(subPath,key));	//	さらに下を検索
	}

}

/*!
	サブノードを追加
*/
void CWorkspaceNode::AddSubNode(CString name)
{
	ASSERT(name.Find("::") == -1);

	//	自分のサブノードを検索
	int index = FindSubNodeIndex(name);
	if(index == -1)
	{
		//	無いから、追加
		m_subNode.Add(CWorkspaceNode(name));
	}
}


/*!
	ノードを削除する

	# 関数内でのSCOPE_LOCK使用禁止！！
	# デッドロックする
*/
void CWorkspaceNode::DeleteNode(CString name)
{
	int index = FindSubNodeIndex(name);
	if(index != -1)
		m_subNode.RemoveAt(index);
}


/*!
	サブノード数を得る
*/
int CWorkspaceNode::GetSubNodeCount()
{
	return((int)m_subNode.GetSize());
}


/*!
	全てのサブノード名を文字列として取得

	自分のサブノードのみです。
	下位ノードへは検索に行きません
*/
int CWorkspaceNode::GetAllSubNode(IStringArrayPtr list)
{
	//	サイズ初期化
	int count = (int)m_subNode.GetSize();
	list->SetSize(count);

	//	設定
	for(int i=0;i<count;i++)
		list->SetString(i, m_subNode[i].m_nodeName);

	return(count);
}



//////////////////////////////////////////////////////////////////////////////////////////
//	サブノードに対する処理(Protected)
//////////////////////////////////////////////////////////////////////////////////////////
/*!
	サブノードを検索する
*/
int CWorkspaceNode::FindSubNodeIndex(CString name)
{
	for(int i=0;i<m_subNode.GetSize();i++)
	{
		if(m_subNode[i].m_nodeName == name)
			return(i);
	}
	return -1;
}


//////////////////////////////////////////////////////////////////////////////////////////
//	その他の関数(Protect)
//////////////////////////////////////////////////////////////////////////////////////////
/*!
	パス解析(「::」区切りを分解する)

	\param path		パス
	\param topPath	トップレベルのパス
	\param subPath	残り
	\return			0:自分のキー、1:まだサブキーがある
*/
int CWorkspaceNode::ParsePath(CString path, CString & topPath, CString & subPath)
{
	int	index = path.Find(_T("::"));
	if(index == -1)
	{
		topPath.Empty();
		subPath = path;
		return(0);
	}
	else
	{
		if(path == _T("::"))
		{
			topPath.Empty();
			subPath.Empty();
			return(0);
		}

		topPath = path.Mid(0,index);
		subPath = path.Mid(index + 2);
		return(1);
	}
}


/******************************************************
	入出力に関する処理
*******************************************************/
/*!
	サブノードを作成する
*/
CWorkspaceNode *CWorkspaceNode::AddNewSubNode(CString name)
{
	if(FindSubNodeIndex(name) != -1)
		return(NULL);

	m_subNode.Add(CWorkspaceNode(name));
	return &m_subNode[m_subNode.GetSize()-1];
}


/*!
	サブノードをインデックスで取得する
*/
CWorkspaceNode *CWorkspaceNode::GetSubNodeByIndex(int index)
{
	if(index < 0 || index >= m_subNode.GetCount())
		return(NULL);

	return(&m_subNode[index]);
}

/*!
	キーをインデックスで取得する
*/
CWorkspaceKeyData *CWorkspaceNode::GetKeyByIndex(int index)
{
	if(index < 0 || index >= m_keyData.GetCount())
		return(NULL);

	return(&m_keyData[index]);
}

