一段c++builder下的老代码。
用组合模式来实现组织结构,singleton的OrgTreeRepository来保存所有对象。
稍有问题的地方就是一部分构造界面的代码渗入到了实体对象中--MakeChildTreeView(),这个因为用它来初始化界面中的人员组织树简直是太干净了,实在没法抵挡这种诱惑。其它的业务方法差不多是相同的逻辑,去掉了。
//---------------------------------------------------------------------------
#ifndef OrganizationH
#define OrganizationH
#include <Classes.hpp>
#include <vector>
#include <list>
#include "Global/Global.h"
#include "mylib/mylib/Object_Manager.h"
#include "DataModule/PersistHome.h"
#include <memory>
#include "DataModule/Persist.h"
#include "mylib/mylog.h"
using namespace std;
using namespace mylib;
using namespace planmanage;
//---------------------------------------------------------------------------
class Party
{
public:
virtual void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode)=0;
void SetName(const String &arg)
{
this->m_name=arg;
}
const String GetName()
{
return m_name;
}
virtual bool IsLeaf()=0;
virtual Party* FindByName(const String & name)=0;
virtual Party* FindById(const String & id) =0;
virtual void AddChild(Party* party)=0;
virtual String GetParentId()=0;
virtual ~Party(){}
virtual void Dump()=0;
virtual void DumpChild()=0;
void SetParent(Party* arg)
{
m_parent = arg;
}
Party* GetParent()
{
return m_parent;
}
int GetLevel()
{
int ret=0;
Party * cursor = this->GetParent();
while(cursor)
{
cursor = cursor->GetParent();
ret++;
}
return ret;
}
protected:
TTreeNode* AddTreeViewNode(TTreeView *tree, TTreeNode* fnode)
{
TTreeNode* node = tree->Items->AddChildObject(fnode,m_name,this);
node->ImageIndex = IsLeaf() ? 1 : 0;
return node;
}
String m_name;
Party* m_parent;
};
class Organization : public Party, public Persist<>
{
public:
Organization()
{
}
void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode)
{
TTreeNode* node = AddTreeViewNode(tree,fnode);
for(size_t i=0; i<m_children.size(); i++)
{
m_children[i]->MakeChildTreeView(tree, node);
}
}
bool IsLeaf()
{
return false;
}
Party* FindByName(const String & name)
{
if(this->GetName()==name) return this;
else
{
for(size_t i=0;i<m_children.size();i++)
{
Party* ret = m_children[i]->FindByName(name);
if(ret) return ret;
}
}
return NULL;
}
Party* FindById(const String & id)
{
if(this->GetId()==id) return this;
else
{
for(size_t i=0;i<m_children.size();i++)
{
Party* ret = m_children[i]->FindById(id);
if(ret) return ret;
}
}
return NULL;
}
void AddChild(Party* party)
{
m_children.push_back(party);
}
String GetParentId()
{
return m_pid;
}
~Organization()
{
ClearContainer(&m_children);
}
void Dump()
{
log()<<"Dep: "+string(m_name.c_str())<<endl;
log()<<"-------------"<<endl;
for(size_t i=0; i<m_children.size();i++)
{
m_children[i]->Dump();
}
log()<<"-------------"<<endl;
}
void DumpChild()
{
log()<<"all children"<<endl;
for(size_t i=0; i<m_children.size();i++)
{
log()<<m_children[i]->GetName().c_str()<<endl;
}
}
protected:
void Bind()
{
BindTable("DOCMAN.DEPARTMENT","ID");
BindField<StringBinding>(m_name, "MANE");
BindField<StringBinding>(m_pid,"PARENT_ID");
}
private:
vector<Party *> m_children;
String m_pid;
};
class Employee : public Party, public Persist<false>
{
public:
void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode)
{
AddTreeViewNode(tree,fnode);
}
bool IsLeaf()
{
return true;
}
Party* FindByName(const String & name)
{
if(this->GetName()==name)
return this;
else
return NULL;
}
Party* FindById(const String & id)
{
if(this->GetId()==id)
return this;
else
return NULL;
}
void AddChild(Party* party)
{
//do nothing
}
String GetParentId()
{
return m_depId;
}
void Dump()
{
log()<<"Staff: "+string(m_name.c_str())<<endl;
}
void DumpChild()
{
log()<<"leaf node"<<endl;
}
protected:
void Bind()
{
BindTable("DOCMAN.STAFFINFO", "STAFFNO");
BindField < StringBinding > (m_name, "STAFFNAME");
BindField < StringBinding > (m_depId, "DEPARTNO");
}
private:
String m_depId;
};
//singlton
class OrgTreeRepository : public Cleanup
{
public:
static OrgTreeRepository * GetInstance()
{
if(!m_instance)
{
m_instance = new OrgTreeRepository();
mylib::Object_Manager::at_exit(m_instance);
}
return m_instance;
}
Party * GetTreeRoot()
{
return m_root;
}
Party * FindByName(const String &name)
{
return m_root->FindByName(name);
}
Party * FindById(const String &id)
{
return m_root->FindById(id);
}
Organization * GetJY()
{
return dynamic_cast<Organization*>(m_root->FindById(JY_DEP_ID));
}
Organization * GetZZ()
{
return dynamic_cast<Organization*>(m_root->FindById(ZZ_DEP_ID));
}
Organization * GetSB()
{
return dynamic_cast<Organization*>(m_root->FindById(SB_DEP_ID));
}
Organization * GetHZ()
{
return dynamic_cast<Organization*>(m_root->FindById(HZ_DEP_ID));
}
Organization * GetRootOrg()
{
return dynamic_cast<Organization*>(m_root);
}
private:
static OrgTreeRepository * m_instance;
OrgTreeRepository()
{
InitOrgTree();
}
~OrgTreeRepository()
{
delete m_root;
}
Party * m_root;
void InitRootNode()
{
Organization * org= new Organization();
org->SetId(0);
org->SetParent(NULL);
org->Load();
m_root = org;
}
void InitOrgTree()
{
InitRootNode();
auto_ptr< list<Organization*> > orgs(
PersistHome < Organization, list<Organization*> >::SelectByFilter("id <> 0")
);
AddKindNodes(orgs.get());
ClearContainer(orgs.get());
auto_ptr< list<Employee*> > emps(PersistHome < Employee, list<Employee*> >::SelectAll());
AddKindNodes(emps.get());
ClearContainer(emps.get());
}
template < typename CollectionType>
void AddKindNodes(CollectionType *collection)
{
typedef CollectionType::iterator Iterator;
if(!collection) return;
//循环取出,直至大小不再变化
size_t vane=0;
while(!collection->empty()&& collection->size()!=vane)
{
vane=collection->size();
for(Iterator i=collection->begin(); i!=collection->end(); i++)
{
Party* parent = m_root->FindById((*i)->GetParentId());
if(parent)
{
parent->AddChild(*i);
(*i)->SetParent(parent);
i=collection->erase(i);
}
}
}
}
};
#endif