/*
	\file	CWorkspace.h
	\brief	階層化変数管理クラス

	2006/04/05	XML保存形式の変更
	2006/11/14	XML入出力方法変更
*/

#pragma once

#include ".\workspacenode.h"
#include ".\workspaceaccess.h"
#include "InterfaceTemplate.h"
#include "FilterAPIWorkspace.h"

/*!
	自動置き換え
*/
class IWorkspaceAutoSwap
{
public:
	virtual ~IWorkspaceAutoSwap() {};

	//!	通常の取得
	virtual CString GetKeyDataSwap(IWorkspace *workspace, const LPCSTR orgKey, CString orgData) = 0;
};
//	インターフェース定義
DEFINE_INTERFACE(IWorkspaceAutoSwap);

class CWorkspaceLock;
class CWorkspaceAccess;
class CWorkspace : public IWorkspace
{
	friend class CWorkspaceAccess;
	friend class CWorkspaceLock;
	friend class CWorkspaceStringList;

public:
	CWorkspace(CString className = _T(""));
	virtual ~CWorkspace(void);

	/////////////////////////////////////////////////////////////////////////////////////
	//	アクセス可能な関数
	/////////////////////////////////////////////////////////////////////////////////////
	//!	アクセスクラスを取得する
	CWorkspaceAccess GetAccess(CString path);

	//!	アクセスクラスを取得し、中身をクリア
	CWorkspaceAccess GetCleanAccess(CString path);

	/////////////////////////////////////////////////////////////////////////////////////
	//	入出力に関する処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	XMLファイルへ出力
	int SaveToXMLFile(CString filePath, CString savePath = _T(""));

	//!	XMLファイルよりロード
	int LoadFromXMLFile(CString filePath);


	//!	XML文字列へ出力
	CStringA ToXMLStringUTF8(CString savePath = _T(""));

	//!	XML文字列から生成
	int FromXMLStringUTF8(CStringA xml);

	//!	XML文字列へ出力
	CString ToXMLString(CString savePath = _T(""));

	//!	XML文字列から生成
	int FromXMLString(CStringA xml);

	/////////////////////////////////////////////////////////////////////////////////////
	//	設定
	/////////////////////////////////////////////////////////////////////////////////////
	//!	リードオンリー
	void SetReadOnly(int readOnly);

	//!	自動置き換え
	void SetAutoSwap(IWorkspaceAutoSwapPtr autoSwap)
	{
		m_autoSwap = autoSwap;
	};

	//!	自動置き換え
	void SetAutoSwapDefault(IWorkspaceAutoSwapPtr autoSwap)
	{
		m_autoSwapDefault = autoSwap;
	};

protected:
	/////////////////////////////////////////////////////////////////////////////////////
	//	初期化など
	/////////////////////////////////////////////////////////////////////////////////////
	//!	全データクリア
	virtual void Clear(LPCSTR path);

	//!	コピー
	virtual void Copy(LPCSTR destPath, LPCSTR srcPath, IWorkspacePtr srcWorkspace = NULL);

	/////////////////////////////////////////////////////////////////////////////////////
	//	排他処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	ロック
	virtual void Lock() { m_scopeLock.Lock(); };

	//!	アンロック
	virtual void Unlock() { m_scopeLock.Unlock(); };

	/////////////////////////////////////////////////////////////////////////////////////
	//	Keyに関する処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	データの設定
	virtual void SetKeyData(LPCSTR path, LPCSTR data, int noCase = FALSE);

	//!	データの取得
	virtual void GetKeyData(IAPIPassStringPtr dest, LPCSTR path, LPCSTR defaultData, int noCase = FALSE);

	//!	キーを検索
	virtual int FindKeyData(LPCSTR path, LPCSTR sData, int noCase = FALSE, int pathCompare = FALSE);

	//!	データの削除
	virtual void DeleteKey(LPCSTR path);

	//!	キー数を取得
	virtual int GetKeyCount(LPCSTR path);

	//!	全てのキー名を文字列として取得
	virtual int GetAllKey(LPCSTR path, IAPIPassStringArrayPtr list);

	//!	全てのデータを文字列として取得
	virtual int GetAllData(LPCSTR path, IAPIPassStringArrayPtr list);

	/////////////////////////////////////////////////////////////////////////////////////
	//	サブノードに関する処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	ノードを削除する
	virtual void DeleteNode(LPCSTR path);

	//!	サブノード数を得る
	virtual int GetSubNodeCount(LPCSTR path);

	//!	全てのサブノード名を文字列として取得
	virtual int GetAllSubNode(LPCSTR path, IAPIPassStringArrayPtr list);


protected:
	/////////////////////////////////////////////////////////////////////////////////////
	//	その他の処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	ノードパスに変更
	CString ToNodePath(CString path);

	//!	サブノードのポインタを取得
	CWorkspaceNode	*GetSubNode(CString path, CString &key);

	//!	コピー内部処理
	void InternalCopy(CWorkspaceNode *dest, CString srcPath);

	//!	コピー内部処理(外部インタフェース用)
	void ExternalCopy(IWorkspace *src, CString srcPath, CString destPath);

	/////////////////////////////////////////////////////////////////////////////////////
	//	メンバ変数
	/////////////////////////////////////////////////////////////////////////////////////
	//!	作業領域のルート
	CWorkspaceNode		m_root;

	//!	ロックオブジェクト
	CCriticalSection	m_scopeLock;

	//!	クラス名
	CString				m_className;

	//!	リードオンリー
	int					m_readOnly;

	//!	自動置き換え
	IWorkspaceAutoSwapPtr	m_autoSwap;

	//!	自動置き換え(デフォルト)
	IWorkspaceAutoSwapPtr	m_autoSwapDefault;

private:
	//!	コピー禁止
	CWorkspace(const CWorkspace &other);
	void operator=(const CWorkspace &other);
};


/*!
	ワークスペースロッククラス
*/
class CWorkspaceLock
{
public:
	CWorkspaceLock(CWorkspaceAccess wa)
	{
		m_ws = wa.GetRoot();
		m_ws->Lock();
	};

	virtual ~CWorkspaceLock()
	{
		m_ws->Unlock();
	};


	IWorkspace	*m_ws;
};


#define	WORKSPACE_LOCK(x) CWorkspaceLock __lock(x);

