/***********************
** NameDirectory.cpp
***********************/
#include <sstream>
#include <iostream>
#include <CXXLCOMPOSITE.HPP>
#include <CXXLLIST.HPP>
#include <CENTRALIZEDMGR.HPP>
#include "NameDirectory.h"
using namespace std;
using namespace CxxlMan;
// cxxlPreserve2 元件的識別碼,沒對外公佈
#define CNameList_ClassID L"C458BFCF-BB67-4e2e-91C6-43FBFE6EA8C3"
#define DataBase_ClassID L"0C494B0B-D168-480c-97BD-6C6E8D4BD165"
extern "C" CXXL_DLLEXPORT
cxxlObject * cxxlCDECL CxxlMan_ObjectFactory(const wchar_t *ClassID,
void *Arg, ISpirit *spirit);
struct Data:public cxxlObject
{
UNICODE_String Name;
int Age;
Data(const UNICODE_String &Name_Arg, int Age_Arg)
:cxxlObject(Spirit_Urgent),
Name(6) // 固定 5 個字元加一個結尾字元共 6 個字元空間
{
int StrLength = Name_Arg.StrLength();
if(StrLength > 5)
{
for(int i = 0; i < 6; ++i)
Name[i] = Name_Arg[i];
Name[5] = L'\0';
}
else
Name = Name_Arg;
Age = Age_Arg;
}
};
// 雖然在這沒必要,為了示範物件連結仍從 cxxlPreserve2 延伸
class DataBase:virtual public cxxlPreserve2
{
Smart_Ptr<cxxlComposite<Data, false> > Data_Composite; // 實際存放的地方
Smart_Ptr<cxxlComposite<Data, false> > Data_Composite_bp; // 永存處理時的暫時存放區
// 儲存容器藉此取得要永續存取的屬性資料
// 延伸類別須以 virtual 的形式覆寫
// 並且須呼叫上層類別的此函數
virtual bool cxxlFASTCALL Ref(Filter *F)
{
if(F != NULL && cxxlPreserve2::Ref(F))
{
LoadFilter *pLoadFilter = dynamic_cast<LoadFilter*>(F);
if(pLoadFilter == NULL) // 表示 F 是 SaveFilter
{
Smart_Ptr<cxxlList<cxxlComposite<Data, false> > > DataComposite_List =
Data_Composite->cxxlList_Create();
unsigned long Count = DataComposite_List->GetCount();
F->Ref(&Count, 1, L"DataCount");
DataComposite_List->ResetPT(toHead);
Smart_Ptr<cxxlComposite<Data, false> > DataComposite_Ptr = (*DataComposite_List)++;
for(unsigned long i = 0;
i < Count;
++i, DataComposite_Ptr = (*DataComposite_List)++)
{
Smart_Ptr<Data> Data_Ptr = DataComposite_Ptr->GetObj();
F->Ref((wchar_t*)(const wchar_t*)Data_Ptr->Name,
Data_Ptr->Name.StrLength()+1, L"Name");
F->Ref(&Data_Ptr->Age, 1, L"Age");
}
}
else // F 是 LoadFilter
{
if(pLoadFilter->isChk())
{
unsigned long *DataCount;
size_t Count;
if(pLoadFilter->LoadChk((const long **)&DataCount, &Count, L"DataCount") == false)
return false;
Data_Composite_bp = new cxxlComposite<Data, false>(L"Roll",Spirit_Urgent);
for(unsigned long i = 0; i < *DataCount; ++i)
{
const wchar_t *data_name;
const int *data_age;
if(pLoadFilter->LoadChk(&data_name,&Count,L"Name") == false)
return false;
if(pLoadFilter->LoadChk(&data_age,&Count,L"Age") == false)
return false;
Smart_Ptr<Data> Data_Ptr(new Data(L"",0));
Data_Composite_bp->Add(Data_Ptr,data_name);
}
}
else // 實際讀取階段
{
unsigned long Count;
F->Ref(&Count,1, L"DataCount");
Smart_Ptr<cxxlList<cxxlComposite<Data, false> > > DataComposite_List =
Data_Composite_bp->cxxlList_Create();
DataComposite_List->ResetPT(toHead);
Smart_Ptr<cxxlComposite<Data, false> >
DataComposite_Ptr = (*DataComposite_List)++;
for(unsigned long i = 0; i < Count; ++i,
DataComposite_Ptr = (*DataComposite_List)++)
{
Smart_Ptr<Data> Data_Ptr = DataComposite_Ptr->GetObj();
F->Ref((wchar_t*)(const wchar_t*)Data_Ptr->Name, 0, (wchar_t*)NULL);
F->Ref(&(Data_Ptr->Age), 0, (wchar_t*)NULL);
}
Data_Composite = Data_Composite_bp;
}
}
return true;
}
else
return false;
}
public:
// Constructor
DataBase()
:cxxlObject(Spirit_Urgent),
cxxlPreserve2(DataBase_ClassID), // 在建構時指定 ClassID
Data_Composite(new cxxlComposite<Data, false>(L"Roll",Spirit_Urgent), this),
Data_Composite_bp(NULL, this)
{
}
// Destructor
virtual ~DataBase()
{
}
void Add(const Smart_Ptr<Data> &Data_Arg, const UNICODE_String &Name_Arg)
{
Data_Composite->Add(Data_Arg, Name_Arg);
}
Smart_Ptr<Data> GerData(const UNICODE_String &Name_Arg)
{
return Data_Composite->GetObj(Name_Arg);
}
Smart_Ptr<cxxlList<Data> > GerAllData()
{
Smart_Ptr<cxxlList<cxxlComposite<Data, false> > >
DataComposite_List = Data_Composite->cxxlList_Create();
Smart_Ptr<cxxlList<Data> > Data_List = new cxxlList<Data>();
DataComposite_List->ResetPT(toHead);
for(Smart_Ptr<cxxlComposite<Data, false> > DataComposite_Ptr = (*DataComposite_List)++;
DataComposite_Ptr.isNULL() == false;
DataComposite_Ptr = (*DataComposite_List)++)
{
Data_List->Push_Back(DataComposite_Ptr->GetObj());
}
return Data_List;
}
// 實作的 Preserve2 元件還要再加上這個
friend cxxlObject * cxxlCDECL
CxxlMan_ObjectFactory(const wchar_t *ClassID, void *Arg, ISpirit *spirit);
};
// INameList 的實作
class CNameList:public INameList
{
P2Smart_Ptr<DataBase> DataBase_Ptr;
// 指示再生時到哪尋找 dll 元件檔
virtual UNICODE_String cxxlFASTCALL GetGroup()
{
return UNICODE_String(L"testGroup");
}
// 儲存容器藉此取得要永續存取的屬性資料
// 延伸類別須以 virtual 的形式覆寫
// 並且須呼叫上層類別的此函數
virtual bool cxxlFASTCALL Ref(Filter *F)
{
if(F != NULL && INameList::Ref(F))
return true;
else
return false;
}
public:
// Constructor 新建立時用的
CNameList(ISpirit *spirit)
:cxxlObject(spirit),
cxxlPreserve2(CNameList_ClassID), // 在建構時指定 ClassID
// 這裡其實是可以不須採用 Spirit_Urgent,會用 Spirit_Urgent 是為了下面的使用範例要求的即時性
DataBase_Ptr(
Preserve2_Cast<DataBase>( cxxlCM_GetElement(DataBase_ClassID,
L"testGroup", NULL, Spirit_Urgent) )
, this, L"DataBase")
{
}
// Constructor 再生時用的
CNameList()
:cxxlObject(Spirit_Easy), // 再生時 CentralizedMgr 會用永存資料中記錄的 Spirit 換掉
cxxlPreserve2(CNameList_ClassID), // 在建構時指定 ClassID
DataBase_Ptr(NULL, this, L"DataBase")//再生時會以永存資料中記錄的元件資訊產生一個物件填補上去
{
}
// Destructor
virtual ~CNameList()
{
}
virtual void Input(const UNICODE_String &Name_Arg, int Age_Arg) // 輸入
{
DataBase_Ptr->Add(new Data(Name_Arg, Age_Arg), Name_Arg);
}
virtual void Show(const UNICODE_String &Name_Arg) // 顯示所指名稱的資料
{
Smart_Ptr<Data> Data_Ptr = DataBase_Ptr->GerData(Name_Arg);
wcout << L"名稱:" << (const wchar_t*)Data_Ptr->Name << L" "
<< L"年紀:" << Data_Ptr->Age << endl;
}
virtual void ShowAll() // 顯示所有資料
{
Smart_Ptr<cxxlList<Data> > Data_List = DataBase_Ptr->GerAllData();
Data_List->ResetPT(toHead);
for(Smart_Ptr<Data> Data_Ptr = (*Data_List)++;
Data_Ptr.isNULL() == false;
Data_Ptr = (*Data_List)++)
{
wcout << L"名稱:" << (const wchar_t*)Data_Ptr->Name << L" "
<< L"年紀:" << Data_Ptr->Age << endl;
}
}
// 實作的 Preserve2 元件還要再加上這個
friend cxxlObject * cxxlCDECL CxxlMan_ObjectFactory(const wchar_t *ClassID,
void *Arg, ISpirit *spirit);
};
// 負責註冊沒對外公佈的元件識別碼,
class Init
{
static void Reg()
{
wstring RegTbl(
L"[testGroup]"
L"{"
L" [0C494B0B-D168-480c-97BD-6C6E8D4BD165] = \"SampleComponent.dll\""
L"}");
// 匯入註冊表
wistringstream Wins( RegTbl );
cxxlCM_ElementImport(Wins);
}
public:
Init()
{
Reg();
}
};
extern "C" CXXL_DLLEXPORT
cxxlObject * cxxlCDECL CxxlMan_ObjectFactory(const wchar_t *ClassID, void *Arg,
ISpirit *spirit)
{
static Init init;
if(wcscmp(INameList_ClassID, ClassID) == 0) // 只處理介面就好
return new CNameList(spirit);
/*
if(wcscmp(CNameList_ClassID, ClassID) == 0) // 不應處理這個,因 CNameList_ClassID 不
return new CNameList(spirit); // 是用要用於 cxxlCM_GetElement()
*/
if(wcscmp(DataBase_ClassID, ClassID) == 0)
return new DataBase;
return NULL;
}
extern "C" CXXL_DLLEXPORT
cxxlPreserve2 * cxxlCDECL CxxlMan_Preserve2Factory(const wchar_t *ClassID)
{
static Init init;
if(wcscmp(CNameList_ClassID, ClassID) == 0) // 只處理最終實作類別的識別碼就行了
return new CNameList();
if(wcscmp(DataBase_ClassID, ClassID) == 0)
return new DataBase;
return NULL;
}