设计模式应用之使用COMPOSITE模式实现流程(四)

                     设计模式应用之使用COMPOSITE模式实现流程(四)

   最近在工作的过程中,完成了一个实现动态流程的任务。因此将我的demo程序共享出来,给大家参考如何使用COMPOSITE实现流程的编写。在前面序列文章,我本来计划利用MEMENTO 解耦COMPOSITE 对象,使COMPOSITE 对象得到共用,但是在实际开发过程中,我发现这样在开发上有一定的难度,因此我没有采用这样的思路去开发。

  语音流程抽象起来包括:播放语音、播放菜单、还有其他叶子操作。因此语音流程的每个用户的每一选择,就构成了一棵状态子树。而这样的状态子树,如果采用常规的子树的遍历,这样的指针指向会指向很多层。因此我在实际开发过程中,抽象出一个TRootComposit 对象。具体的就不详细介绍了,我把不涉及到机密的东东,当作一个demo拿出来给大家参考。

   以下是头文件:


  
  
   
   
    
    
     
     
      
      
#ifndef __COMPOMENT__H__
#define __COMPOMENT__H__
//-------------------------------------------------------------------------------------------------------------
#include <string>
#include <map>
#include <vector>
using namespace Unify;
//-------------------------------------------------------------------------------------------------------------
#define HANDLE_NEXT 	1  //获取下一个节点(主要是composite对象)
#define HANDLE_PRE  	2  //获取上一个节点(主要是composite对象)
#define HANDLE_END  	3  //某一个流程分支都处理完
#define HANDLE_ERROR	4  //节点执行的操作有误
#define HANDLE_ERROR_NOTIFY 5 //节点执行错误,有提示
#define HANDLE_SELF   6  //驻留在节点执行
#define HANDLE_DEF    7  //默认的错误
//-------------------------------------------------------------------------------------------------------------
class IvrCompoment
{
public:
	IvrCompoment();
	virtual ~IvrCompoment();
	//节点处理事件
	virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e);
	//获取孩子节点
	virtual IvrCompoment* getChild(const std::string& cond);
	//这个接口是判断是否是composit对象
	virtual IvrCompoment* getComposite();
	//用于返回上一级目录
	virtual IvrCompoment* getPreCompoment();
	//判断是否本compoment对象
	virtual bool equal(const std::string& cond);
	//添加孩子节点,只要是composit对象
	virtual void addChild(IvrCompoment* child);	
	//递归构建树,可能要传入孩子信息
	virtual void buildChild(DbServer::TRecordSetSeq& sRec);
	//设置本节点信息
	virtual void set(DbServer::TRecordSet& rec);
	virtual void reset();
};
//-------------------------------------------------------------------------------------------------------------
class IvrVoiceLeaf:public IvrCompoment
{
public:
	IvrVoiceLeaf();
	~IvrVoiceLeaf();
	virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e);
	virtual bool equal(const std::string& cond);
	virtual void set(DbServer::TRecordSet& rec);
private:
	std::string	_actid;
	std::string	_preid;
	std::string _condtion;
	std::string _actname;
	std::string	_record;
	std::string _ttstext;
	std::string _recordfile;
	int			_step;
};
//-------------------------------------------------------------------------------------------------------------
class IvrComposite:public IvrCompoment
{
public:
	IvrComposite(IvrCompoment* ivr);
	virtual ~IvrComposite();
	virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e);
	//获取孩子节点
	virtual IvrCompoment* getChild(const std::string& cond);
	//这个接口是判断是否是composit对象
	virtual IvrCompoment* getComposite();
	//用于返回上一级目录
	virtual IvrCompoment* getPreCompoment();
	//判断是否本compoment对象
	virtual bool equal(const std::string& cond);
	//添加孩子节点,只要是composit对象
	virtual void addChild(IvrCompoment* child);	
	//递归构建树,可能要传入孩子信息
	virtual void buildChild(DbServer::TRecordSetSeq& sRec);
	//设置本节点信息
	virtual void set(DbServer::TRecordSet& rec);
private:
	// 0 go to child,1 not
	bool CheckCond(const std::string& cond);
	std::string	_actid;
	std::string	_preid;
	std::string _condtion;
	std::string _actname;
	std::string	_record;
	std::string _ttstext;
	std::string _recordfile;
	int			_step;
	std::vector<IvrCompoment*> _childs;
	IvrCompoment* _preIvr;
};
//-------------------------------------------------------------------------------------------------------------
class TRootComposit:public IvrCompoment
{
public:
	TRootComposit();
	~TRootComposit();
	virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e);
	virtual void buildChild(DbServer::TRecordSetSeq& sRec);	
	virtual void reset();
	//这个接口是判断是否是composit对象
	virtual IvrCompoment* getComposite(){return this;}
private:
	IvrCompoment* _root;
	IvrCompoment* _subRoot;//由于composit对象可能是一棵树
						   //_subRoot 指向下一个子树	
};
//-------------------------------------------------------------------------------------------------------------
class IvrMannage
{
public:
	~IvrMannage();
	int ReSetRoot(const std::string& key);
	int BuilderSessIvr(TIvrCallSessionInfo& s);
	int Handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e);
	int DeleteSessIvr(TIvrCallSessionInfo& s);
	static IvrMannage* instance();
private:
	IceUtil::RecMutex  _mutex;
	IvrMannage();
	static IvrMannage* _instance;
	std::map<std::string,IvrCompoment*> _ivrMap;
};
//-------------------------------------------------------------------------------------------------------------
#endif



#include "Compoment.h"
const int ErrorPlayLast = 90000;
const int TopFlow       = 1000;
const int InToFlow      = 2202;
const int SelfFlow      = 2101;
const int QUITFlow      = 94000;

//---------------------------------------------------------------
//IvrMannage
//---------------------------------------------------------------
IvrMannage* IvrMannage::_instance = NULL;
IvrMannage* IvrMannage::instance()
{
	if(_instance == NULL)
	{
		_instance = new IvrMannage();
	}
	return _instance;
}
//---------------------------------------------------------------
IvrMannage::IvrMannage()
{
	;
}
//---------------------------------------------------------------
IvrMannage::~IvrMannage()
{
}
//---------------------------------------------------------------
int IvrMannage::BuilderSessIvr(TIvrCallSessionInfo& s)
{
	if(_ivrMap.find(s.SessionId) != _ivrMap.end())
		return -1;
	DbServer::TRecordSetSeq selfInfo;
	int res = getAct(s,selfInfo);//获取某一个id的动态流程信心。
	if(res <= 0)
	{
		return -1;
	}
	//find for root act
	unsigned int idx = 0;
	for(idx; idx < selfInfo.size();idx++)
	{
		disp_msg(2,"preid = [%s]",selfInfo[idx][2].c_str());
		if(selfInfo[idx][2] == "-1")
		{
			break;
		}
	}

	if(idx >= selfInfo.size() || selfInfo.empty())
	{
		disp_msg(2,"Enid =[%d] does not have Root Act",s.entid);
		return -1;
	}
	IvrCompoment* root;
	if(selfInfo.size() != 1)
	{
		root = new TRootComposit();
	}
	else
	{
		root = new IvrVoiceLeaf();
	}

	if(root == NULL)
	{
		disp_msg(2,"Enid =[%d] does new Act Error",s.entid);
		return -1;
	}
	root->buildChild(selfInfo);
	RecMutex::Lock lock(_mutex);
	_ivrMap.insert(std::make_pair(s.SessionId,root));
	return 0;
}
//---------------------------------------------------------------
int IvrMannage::ReSetRoot(const std::string &key)
{
	IceUtil::RecMutex::Lock lock(_mutex);
	std::map<std::string,IvrCompoment*>::iterator it;
	it = _ivrMap.find(key);
	if(it != _ivrMap.end())
	{
		it->second->reset();
		return 0;
	}
	return -1;
}
//---------------------------------------------------------------
int IvrMannage::DeleteSessIvr(TIvrCallSessionInfo& s)
{
	RecMutex::Lock lock(_mutex);
	std::map<std::string,IvrCompoment*>::iterator it;
	it = _ivrMap.find(s.SessionId);
	if(it != _ivrMap.end())
	{
		delete it->second;
		it->second = NULL;
		_ivrMap.erase(it);
	}
	return 0;
}
//---------------------------------------------------------------
//class IvrCompoment
//---------------------------------------------------------------
IvrCompoment::IvrCompoment()
{
}
//---------------------------------------------------------------
IvrCompoment::~IvrCompoment()
{
}
//---------------------------------------------------------------
void IvrCompoment::addChild(IvrCompoment*)
{
}
//---------------------------------------------------------------
int IvrCompoment::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e)
{
	return 0;
}
//---------------------------------------------------------------
IvrCompoment* IvrCompoment::getChild(const std::string& cond)
{
	return 0;
}
//---------------------------------------------------------------
IvrCompoment* IvrCompoment::getComposite()
{
	return 0;
}
//---------------------------------------------------------------
IvrCompoment* IvrCompoment::getPreCompoment()
{
	return 0;
}
//---------------------------------------------------------------
bool IvrCompoment::equal(const std::string& cond)
{
	return true;
}
//---------------------------------------------------------------
void IvrCompoment::buildChild(DbServer::TRecordSetSeq& sRec)
{
}
//---------------------------------------------------------------
void IvrCompoment::set(DbServer::TRecordSet& rec)
{
}
//---------------------------------------------------------------
void IvrCompoment::reset()
{
}
//---------------------------------------------------------------
//class IvrVoiceLeaf
//---------------------------------------------------------------
IvrVoiceLeaf::IvrVoiceLeaf()
{
	_step = 0;
}
//---------------------------------------------------------------
IvrVoiceLeaf::~IvrVoiceLeaf()
{
	;
}
//---------------------------------------------------------------
bool IvrVoiceLeaf::equal(const std::string& cond)
{
	return (_condtion == cond);
}
//---------------------------------------------------------------
void IvrVoiceLeaf::set(DbServer::TRecordSet& rec)
{
/*
	os<<"select actid,acttype,preid,"
	  <<"condtion,actname,record,ttstext,recordfile from amrx_act"
	  <<" where state = 0 and entid="<<sInfo.entid
	  <<" order by preid";
*/
	_actid = rec[0];
	_preid = rec[2];
	_condtion = rec[3];
	_actname = rec[4];
	_record = rec[5];
	_ttstext = rec[6];
	_recordfile = rec[7];
}
//---------------------------------------------------------------
int IvrVoiceLeaf::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e)
{
	int v;
	bool b = false;
	while(!b)
	{
		disp_msg(3,"IvrVoiceLeaf:name = [%s],cond = [%s],step = [%d]",
		     _actname.c_str(),_condtion.c_str(),_step);
		switch(_step)
		{
		case 0:
			if(_record == "1" && !_recordfile.empty())
			{
				s.VoiceFile = _recordfile;
				setCallSession(s);//保存当前的信息
				_step = 3;
			}
			else
			{//alloc tts
				allocTts(s.SessionId,1);
				b = true;
				_step = 1;
			}
			v = HANDLE_SELF;
			break;
		case 1:
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
			}
			else
			{//tts change
				v = HANDLE_SELF;
				_step = 2;
				if(ttsChange(s.SessionId,_ttstext))
				{
					v = HANDLE_ERROR;
				}
			}
			b = true;
			break;
		case 2:
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
				b = true;
			}
			else
			{
				s.VoiceFile = e.UCEventInfo.TtsFileName;
				setCallSession(s);
				_step = 3;
			}
			break;
		case 3:
			v = HANDLE_SELF;
			b = true;
			_step = 4;
			if(playFileDtmf(s.SessionId,s.VoiceFile,1,0,5000))
			{
				v = HANDLE_ERROR;
			}
			break;
		case 4:
			b = true;
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
			}
			else
			{
				setSessionErrorCounts(s.SessionId,0);
				s.smstxt = _ttstext;
				setCallSession(s);
				v = HANDLE_END;
			}
			break;
		default:
			b = true;
			break;
			v = HANDLE_ERROR;
		}
	}
	if(v != HANDLE_SELF)
		_step = 0;
	return v;
}
//---------------------------------------------------------------
//IvrComposite
//---------------------------------------------------------------
IvrComposite::IvrComposite(IvrCompoment* ivr):
_preIvr(ivr),
_step(0)
{
}
//---------------------------------------------------------------
IvrComposite::~IvrComposite()
{
	for(unsigned int i = 0; i < _childs.size();i++)
		delete _childs[i];
}
//---------------------------------------------------------------
IvrCompoment* IvrComposite::getChild(const std::string& cond)
{
	IvrCompoment* ivr = 0;
	for(unsigned int i = 0; i < _childs.size();i++)
	{
		if(_childs[i] !=0 && _childs[i]->equal(cond))
		{
			ivr = _childs[i];
			break;
		}
	}
	return ivr;
}
//---------------------------------------------------------------
IvrCompoment* IvrComposite::getComposite()
{
	return this;
}
//---------------------------------------------------------------
IvrCompoment* IvrComposite::getPreCompoment()
{
	return _preIvr;
}
//---------------------------------------------------------------
bool IvrComposite::equal(const std::string& cond)
{
	return (_condtion == cond);
}
//---------------------------------------------------------------
void IvrComposite::addChild(IvrCompoment* child)
{
	if(child != 0)
		_childs.push_back(child);
}
//---------------------------------------------------------------
void IvrComposite::set(DbServer::TRecordSet& rec)
{
	_actid = rec[0];
	_preid = rec[2];
	_condtion = rec[3];
	_actname = rec[4];
	_record = rec[5];
	_ttstext = rec[6];
	_recordfile = rec[7];
}
//---------------------------------------------------------------
void IvrComposite::buildChild(DbServer::TRecordSetSeq& sRec)
{//递归构建该节点的子树
	IvrCompoment* ivr;
	for(unsigned int i = 0; i < sRec.size();i++)
	{
		unsigned int j = 0;
		if(_actid == sRec[i][2])
		{//找到该节点的子节点
			for(j = 0; j < sRec.size();j++)
			{//判断是否是复合动作
				if(sRec[i][0] == sRec[j][2])
					break;
			}
			if(j < sRec.size())
			{//是composite对象
				ivr = new IvrComposite(this);
			}
			else
			{//Leaf object
				ivr = new IvrVoiceLeaf();
			}
			if(ivr != 0)
			{
				ivr->set(sRec[i]);
				ivr->buildChild(sRec);
				addChild(ivr);
			}
		}//end if
	}//end for
}
//---------------------------------------------------------------
bool IvrComposite::CheckCond(const std::string& cond)
{
	bool b = false;
	for(unsigned int i = 0; i < _childs.size(); i++)
	{
		if(_childs[i] != 0 && _childs[i]->equal(cond))
		{
			b = true;
			break;
		}
	}
	return b;
}
//---------------------------------------------------------------
int IvrComposite::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e)
{
	int v;
	bool b = false;
	std::string file;
	while(!b)
	{
		disp_msg(3,"IvrComposite:name = [%s],cond = [%s],step = [%d]",
				 _actname.c_str(),_condtion.c_str(),_step);
		switch(_step)
		{//0 tts 1 file
		case 0:
			if(_record == "1" && !_recordfile.empty())
			{
				s.VoiceFile = _recordfile;
				file = s.VoiceFile;
				gReSourcePool->setCallSession(s);
				_step = 3;
			}
			else
			{//alloc tts
				allocTts(s.SessionId,1);
				b = true;
				_step = 1;
			}
			v = HANDLE_SELF;
			break;
		case 1:
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
			}
			else
			{//tts change
				v = HANDLE_SELF;
				_step = 2;
				if(ttsChange(s.SessionId,_ttstext))
				{
					v = HANDLE_ERROR;
				}
			}
			b = true;
			break;
		case 2:
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
				b = true;
			}
			else
			{
				s.VoiceFile = e.UCEventInfo.TtsFileName;
				file        = s.VoiceFile;
				gReSourcePool->setCallSession(s);
				_step = 3;
			}
			break;
		case 3:
			v = HANDLE_SELF;
			b = true;
			if(playFileDtmf(s.SessionId,file,1,0,5000))
			{
				v = HANDLE_ERROR;
			}
			_step = 4;
			break;
		case 4:
			if(e.UCEventInfo.EventType == UCEventEndCall ||
				e.UCEventInfo.ResCode != 0)
			{
				v = HANDLE_ERROR;
				b = true;
			}
			else
			{
				if(e.UCEventInfo.Dtmf[0] =='*')
				{
					v = HANDLE_PRE;
					b = true;
				}
				else
				{
					if(CheckCond(e.UCEventInfo.Dtmf))
					{
						v = HANDLE_NEXT;
						b = true;
						setSessionErrorCounts(s.SessionId,0);
					}
					else
					{//出错
						if(addSessionErrorCounts(s.SessionId)<= gMaxErrCounts)
						{
							file = "amrx//errin;"+s.VoiceFile;
							_step = 3;
						}
						else
						{
							b = true;
							v = HANDLE_ERROR_NOTIFY;
							s.VoiceFile = "amrx//maxerr";
							setCallSession(s);
						}
					}
				}
			}
			break;
		default:
			_step = 5;
			b = true;
			v = HANDLE_ERROR;
			break;
		}//end switch
	}
	if(v != HANDLE_SELF)
		_step = 0;
	return v;
}
//---------------------------------------------------------------
//TRootComposit
//---------------------------------------------------------------
TRootComposit::TRootComposit():
_root(0),
_subRoot(0)
{
}
//---------------------------------------------------------------
TRootComposit::~TRootComposit()
{
	delete _root;
}
//---------------------------------------------------------------
void TRootComposit::reset()
{
	_subRoot = _root;
}
//---------------------------------------------------------------
void TRootComposit::buildChild(DbServer::TRecordSetSeq& sRec)
{
	unsigned int idx = 0;
	for(idx; idx < sRec.size();idx++)
	{
		disp_msg(2,"preid = [%s]",sRec[idx][2].c_str());
		if(sRec[idx][2] == "-1")
		{
			break;
		}
	}

	if(idx >= sRec.size())
	{
		disp_msg(2,"TRootComposit build child Error = [no root act]");
		return;
	}
	_root = new IvrComposite(0);
	if(_root != 0)
	{
		_root->set(sRec[idx]);
		_root->buildChild(sRec);
		_subRoot = _root;
	}
}
//---------------------------------------------------------------
int TRootComposit::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e)
{
/*
#define HANDLE_NEXT 	1  //获取下一个节点(主要是composite对象)
#define HANDLE_PRE  	2  //获取上一个节点(主要是composite对象)
#define HANDLE_END  	3  //某一个流程分支都处理完
#define HANDLE_ERROR	4  //节点执行的操作有误
#define HANDLE_ERROR_NOTIFY 5 //节点执行错误,有提示
#define HANDLE_SELF   6  //驻留在节点执行
*/
	int v = HANDLE_ERROR;
	bool top = false;
	while(true)
	{
		v = HANDLE_DEF;
		if(_subRoot != 0)
			v = _subRoot->handle(s,e);
		switch(v)
		{
		case HANDLE_NEXT:
			 _subRoot = _subRoot->getChild(e.UCEventInfo.Dtmf);
			 break;
		case HANDLE_PRE:
			top = (_subRoot == _root);
			_subRoot  = _subRoot->getPreCompoment();
			if( top && _subRoot == 0)
			{
				_subRoot = _root;
				return TopFlow;
			}
			break;
		case HANDLE_END:
			//该流程的某个子树已经处理完了,返回到汇聚点
			disp_msg(3,"TRootComposit 3 InToFlow=[%d]",InToFlow);
			return InToFlow;
		case HANDLE_ERROR:
			disp_msg(3,"TRootComposit 4 QUITFlow=[%d]",QUITFlow);
			return QUITFlow;
		case HANDLE_ERROR_NOTIFY:
			disp_msg(3,"TRootComposit 5 ErrorPlayLast=[%d]",ErrorPlayLast);
			return ErrorPlayLast;
		case HANDLE_SELF:
			disp_msg(3,"TRootComposit 6 SelfFlow=[%d]",SelfFlow);
			return SelfFlow;
		default:
			disp_msg(3,"TRootComposit 7 QUITFlow=[%d]",QUITFlow);
			return QUITFlow;
		}//end switch
	}
}
//---------------------------------------------------------------
int IvrMannage::Handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e)
{
	std::map<std::string,IvrCompoment*>::iterator it;
	IvrCompoment* root = 0;
	{
		IceUtil::RecMutex::Lock lock(_mutex);
		it = _ivrMap.find(s.SessionId);
		if(it != _ivrMap.end())
			root = it->second;
		if(root == 0)
			return QUITFlow;
	}
	int v = QUITFlow;
	if(root->getComposite() == 0)
	{
		int v = root->handle(s,e);
		switch(v)
		{
		case HANDLE_END:
			v = InToFlow;
			break;
		case HANDLE_SELF:
			v = SelfFlow;
			break;
		default:
			v = QUITFlow;
			break;
		}//end if
		disp_msg(3,"IvrMannage::Handle Leaf return v =[%d]",v);
		return v;
	}
	else
	{
		v = root->handle(s,e);
		disp_msg(3,"IvrMannage::Handle RootComposit return v =[%d]",v);
		return v;
	}
}
//---------------------------------------------------------------


      
      


     
     
    
    
   
   
  
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值