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

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

#pragma once
#include "types/WorkspaceTypes.h"
#include "IStringHelper.h"
#include "WorkspaceAccess.h"
#include "SyncObject.h"
#include "InterfaceAutoPtr.h"

//	クラス宣言
class CWorkspaceNode;
class CWorkspaceLock;
class CWorkspaceAccess;


/*!
	自動置き換え
*/
class IWorkspaceAutoSwap
{
public:
	//!	通常の取得
	virtual CUTF8String GetKeyDataSwap(IWorkspace *workspace, LPCU8STR orgKey, CUTF8String orgData) = 0;

	//!	削除
	virtual void Delete() = 0;
};
//!	ポインタ型
typedef IWorkspaceAutoSwap* IWorkspaceAutoSwapPtr;


/*!
	ワークスペース
*/
class CWorkspace : public IWorkspace
{
	friend class CWorkspaceAccess;
	friend class CWorkspaceLock;

public:
	CWorkspace(CUTF8String className = _U8(""));
	virtual ~CWorkspace(void);

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

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

	/////////////////////////////////////////////////////////////////////////////////////
	//	入出力に関する処理
	/////////////////////////////////////////////////////////////////////////////////////
	//!	XMLファイルへ出力
	int SaveToXMLFile(CUTF8String filePath);

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

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

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


	//!	別のCWorkspaceを複製
	void Duplicate(CWorkspace &copyFrom, CUTF8String srcPath = _U8(""), CUTF8String destPath = _U8(""));

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

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

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

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

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

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

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

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

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

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

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

	//!	全てのキー名を文字列として取得
	virtual int GetAllKeyPair(LPCU8STR path, IStringArrayPtr keys, IStringArrayPtr datas);

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

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

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


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

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

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

	//!	コピー内部処理(外部インタフェース用)
	void ExternalCopy(IWorkspace *src, CUTF8String srcPath, CWorkspaceNode *dNode, CIStringArrayWrap &tempKeys, CIStringArrayWrap &tempDatas);

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

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

	//!	クラス名
	CUTF8String				m_className;

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

	//!	自動置き換え
	CInterfaceAutoPtr<IWorkspaceAutoSwap>	m_autoSwap;

	//!	自動置き換え(デフォルト)
	CInterfaceAutoPtr<IWorkspaceAutoSwap>	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);

