#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 = other.m_keyData;
	m_subNode = 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);
	}
}

/*!
	キーの存在を確認

	このノードのデータに対するアクセス
*/
int CWorkspaceNode::KeyIsExist(CString &key, int noCase)
{
	int index = FindKeyIndex(key,noCase);
	if(index != -1)
		return(TRUE);
	return(FALSE);
}

/*!
	データの削除

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


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

/*!
	全てのキーを文字列として取得
*/
int CWorkspaceNode::GetAllKey(CStringArray &list)
{
	list.RemoveAll();

	int count = (int)m_keyData.GetSize();
	for(int i=0;i<count;i++)
		list.Add(m_keyData[i].m_key);

	return(count);
}


/*!
	全てのキーをコピーする
*/
void CWorkspaceNode::CopyAllKeys(CKeyDataArray &keyData)
{
	keyData.Copy(m_keyData);
}


/*!
	文字列中のキー名をデータに置き換えた文字列を取得する

	%Key-Name% を、該当するキーのデータで置き換えます
	noDataが設定されている場合、見つからない場合は、noDataに置き換えます
*/
CString CWorkspaceNode::GetKeySwapString(CString str,CString noData)
{
	int	count = (int)m_keyData.GetSize();

	//	全部検索
	for(int i=0;i<count;i++)
	{
		/*
		int index = str.Find("%" + m_keyData[i].m_key + "%");

		for(int j=0;j<100 && index != -1;j++)
		{
			str = str.Mid(0,index) + m_keyData[i].m_data + str.Mid(index + 2 + m_keyData[i].m_key.GetLength());
			index = str.Find("%" + m_keyData[i].m_key + "%");
		}
		*/

		str.Replace("%" + m_keyData[i].m_key + "%",m_keyData[i].m_data);
	}

	//	該当しない置き換えを削除
	if(!noData.IsEmpty() && noData.Find("%") == -1)
	{
		CString	tmp;
		for(int i=0;i<1000;i++)
		{
			int index = str.Find("%");
			if(index == -1)
			{
				tmp += str;
				break;
			}
			
			tmp += str.Mid(0,index);
			str = str.Mid(index+1);

			int index2 = str.Find("%");
			if(index == -1)
			{
				tmp += str;
				break;
			}

			//	%%?
			if(index2==0)
			{
				tmp += "%";
			}
			else
			{
				tmp += noData;

			}

			str = str.Mid(index2+1);
		}
		str = tmp;
	}

	return(str);
}

/*!
	キーを検索
*/
int CWorkspaceNode::FindKeyData(CString sData, int noCase)
{
	if(noCase)
	{
		for(int i=0;i<m_keyData.GetSize();i++)
			if(sData.CompareNoCase(m_keyData[i].m_data) == 0)
				return(i);
	}
	else
	{
		for(int i=0;i<m_keyData.GetSize();i++)
			if(sData == m_keyData[i].m_data)
				return(i);
	}

	return(-1);
}

/*!
	キーを検索
*/
int CWorkspaceNode::FindKeyDataPath(CString path, int eqPath)
{
	if(eqPath)
	{
		return(FindKeyData(path, TRUE));
	}
	else
	{
		//	比較
		for(int i=0;i<m_keyData.GetCount();i++)
		{
			if(m_keyData[i].m_data.CompareNoCase(path.Left(m_keyData[i].m_data.GetLength())) == 0)
				return(i);
		}

		return(-1);
	}
}
	


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

	if(!noCase)
	{
		for(int i=0;i<count;i++)
		{
			if(m_keyData[i].m_key == key)
				return(i);
		}
	}
	else
	{
		for(int i=0;i<count;i++)
		{
			if(m_keyData[i].m_key.CompareNoCase(key) == 0)
				return(i);
		}
	}
	return -1;
}

//////////////////////////////////////////////////////////////////////////////////////////
//	サブノードに対する処理(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 path, CString &key)
{
	CString	topPath,subPath;
	if(ParsePath(path,topPath,subPath) == 0)
	{
		//	自分が対称だ・・
		return;
	}
	else
	{
		//	自分のサブノードを検索
		int index = FindSubNodeIndex(topPath);
		if(index == -1)
		{
			//	無いから、追加
			index = (int)m_subNode.GetSize();
			m_subNode.Add(CWorkspaceNode(topPath));
		}

		//	さらに下位を追加
		m_subNode[index].AddSubNode(subPath,key);
	}

}


/*!
	ノードを削除する

	# 関数内での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(CStringArray &list)
{
	list.RemoveAll();

	int count = (int)m_subNode.GetSize();
	for(int i=0;i<count;i++)
		list.Add(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("::");
	if(index == -1)
	{
		topPath.Empty();
		subPath = path;
		return(0);
	}
	else if(index == 0)
	{
		topPath.Empty();
		subPath = path.Mid(index + 2);
		return(0);
	}
	else
	{
		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]);
}

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

	return(&m_keyData[index]);
}

