微内核流程引擎(IVR导航)的设计与实现(三)——脚本的设计
我设计的流程引擎是脚步驱动的。脚本中定义了流程执行的环境,流程操作的对象,流程执行的步骤。下面是一个流程脚本的示例:
<?xml version="1.0" encoding="utf-8"?>
<process name="make_call">
<data type="user_tel">called_number</data>
<object type="user" id="global_data:called_number" operation="must">obj_user</object>
//用户对象描述中,号码是必须的,是流程引擎和业务的交互唯一标识,callid是可选的。
<object type="user" object_num="global_data:called_number" operation="must">obj_user</object>
<sequence name="make_call">
<invoke interface="make_call" node="make_call_001" object_user="obj_user" calling_number="6699" original_number="123456" call_type="local_call">
</invoke>
<invoke interface="play_voice" node="play_voice_001" object_user="obj_user" play_long="100" play_file="/home/welcome.au">
</invoke>
</sequence>
</process>
脚本的含义 :
1、process的name属性表示流程的名称,用于在程序中调用。
2、<data type="user_tel">called_number</data>表示定义了一个流程的全局外部变量。有程序在调用流程是作为流程数据传送给流程。这个数据要在后面的流程中使用。
3、<object>部分在流程中定义流程操作的对象。一般分为用户和会场。这里表示是用户。属性“id”表示对象的唯一标识。这里引用的是流程的全局数据:global_data:called_number,也就是在上面定义的数据。属性“operation”表示此对象是可选还是必选。如果是必须,这如果此对象被释放,这流程也要被被结束。否则,不结束。中间的内容表示对象在流程中的唯一标示,这里是obj_user,后面的节点可以通过使用它来操作对象。
4、<sequence>表示顺序调用下面的节点。
5、<invoke >表示调用节点。属性“interface="make_call"”表示此节点调用的接口是make_call。make_call是在代码中定义好的关键字,对应一个软交换系统的接口。属性“node”表示节点的唯一标识,在流程内部唯一,可以在流程跳转的时候使用。 “object_user="obj_user"“表示make_call 接口操作的对象。有<object>创建。 calling_number="6699" original_number="123456" call_type="local_call"表示的是make_call接口调用时的数据。
6、<invoke interface="play_voice"表示对此对象进行放音。
这个脚本的意思是,根据流程输入的号码,创建用户对象,并且发起呼叫,对用户进行放音。
复杂的脚步定义:
上面的是一个简单的示例。为了能够实现流程编辑,要考虑很多的情况,要能够进行分支处理,跳转执行,捕获事件等。
1、分支的实现
<recive event="user_key" ="" node="receive_key" object_user="obj_user" time_out="10"></recive>
<switch condition_type="user_key" object="obj_user">
<case condition="9092">
<sequence name="d">
</sequence>
</case>
<case condition="time_out">
<sequence name="d">
</sequence>
</case>
<otherwise>
<sequence name="">
<goto node="play_voice_001">goto_001</goto>
</sequence>
</otherwise>
</switch>
1)<recive event="user_key"表示接受指定用户的按键。如果超过10秒为收到按键则认为用户按键结束。
2)<switch condition_type="user_key"表示一用户的按键为分支条件,进行分支处理。
3)<case condition="9092">表示如果用户的按键式0092的话则进入此分支进行处理。
4)<case condition="time_out">如果超时为收到用户按键,这进入此分支处理
5)<otherwise>如果上面的条件都不满足,则进入此分支处理。
2、跳转的实现:
<goto node="goto_001" next_node="play_voice_001"></goto>
表示此节点是一个跳转节点,要跳转到的下一个节点是play_voice_001。
3、信号捕获的实现:
<pick name="pick_001" time_out="10">
<on_event event="on_ring_180" result="success" reason="normal">
<sequence name="008">
</sequence>
</on_event>
<time_out>
<sequence name="008">
</sequence>
</time_out>
<otherwise event="on_ring_180:on_ring_183">
<sequence name="009">
</sequence>
</otherwise>
</pick>
1)<pick name="pick_001" time_out="10"><pick>活动会等待一组相互排斥事件中的一个事件的发生,然后执行与发生的事件相关联的活动。它会阻塞业务流程执行,以等待某一特定的事件发生,比如接收到一个合适的消息或超时警报响起。当其中任何一个事件被触发后,业务流程就会继续执行,pick也随即完成了,不会再等待其他事件的发生。
2)<on_event event="on_ring_180" result="success" reason="normal">表示如果收到的on_ring_180,且结果是success,原因是normal。触发此流程的处理。
3)<time_out>表示超时为收到制定事件的处理。
4)<otherwise event="on_ring_180:on_ring_183">表示收到其他的事件,比如:on_ring_180或on_ring_183,都进入此分支处理。