<o:p> </o:p>
YAWL研究总结(之一)
<o:p> </o:p>
胡长城(银狐999)
<st1:chsdate month="10" islunardate="False" day="11" year="2004" w:st="on" isrocdate="False">2004-10-11</st1:chsdate>
<o:p> </o:p>
开始研究YAWL
<o:p> </o:p>
首先按按照其user manual,部署了yawl.war等。基本明白其实如何操作运行的<o:p></o:p>
<o:p> </o:p>
偶然间发现其有一个gui端的测试控制端,是<o:p></o:p>
au.edu.qut.yawl.engine.gui.YEngineGUI类。<o:p></o:p>
<o:p> </o:p>
List newSpecIDs = _engine.addSpecifications(selectedFile, _ignoreErrors, errorMessages);<o:p></o:p>
<o:p> </o:p>
但是,其在load specification的时候,会应为验证不通过而抛错误,需要修改一点程序。将 au.edu.qut.yawl.unmarshal.YMarshal 类中的 unmarshalSpecification 方法 中有关验证部分的代码屏蔽掉,即可:<o:p></o:p>
<o:p> </o:p>
// String errors = YSchemaChecker.getInstance().checkSchema(specificationSetFileID);<o:p></o:p>
// if (errors == null || errors.length() > 0) {<o:p></o:p>
// throw new YSyntaxException(<o:p></o:p>
// " The file failed to verify against YAWL's Schema:\n"<o:p></o:p>
// + errors);<o:p></o:p>
// }<o:p></o:p>
<o:p> </o:p>
其engine类 Yengine 提供了 加载 specification的方法:addSpecifications<o:p></o:p>
在这个方法中,会调用 Ymarshal类的来完成 xml到对象的转换:<o:p></o:p>
newSpecifications = YMarshal.unmarshalSpecifications(specificationFile.getAbsolutePath());<o:p></o:p>
<o:p> </o:p>
YAWL的元素
请首先参考http://www.citi.qut.edu.au/yawl/lexicon.jsp
<o:p> </o:p>
<o:p> </o:p> | <o:p> </o:p> | <o:p> </o:p> |
Input Condition<o:p></o:p> | 流程的起始节点<o:p></o:p> | YinputCondition<o:p></o:p> |
Output Condition<o:p></o:p> | 流程的结束节点<o:p></o:p> | YoutputCondition<o:p></o:p> |
Condition<o:p></o:p> | 流程的状态节点(相当于 place)<o:p></o:p> | Ycondition<o:p></o:p> |
Atomic Task<o:p></o:p> | 简单任务节点,可以被人处理,也可以被应用外界程序处理<o:p></o:p> | YExternalTask<o:p></o:p> |
YAtomicTask<o:p></o:p> (extends YExternalTask)<o:p></o:p> | ||
<st1:city w:st="on"><st1:place w:st="on">Split</st1:place></st1:city><o:p></o:p> | 支持三种:AND,OR,XOR<o:p></o:p> | <o:p> </o:p> |
Join<o:p></o:p> | 支持三种:And,OR,XOR<o:p></o:p> | <o:p> </o:p> |
Composite Task<o:p></o:p> | 调另外的yawl process<o:p></o:p> | YcompositeTask<o:p></o:p> |
Multiple Instance of an Atomic Task<o:p></o:p> | 表示Atomic任务(包含External)多实例<o:p></o:p> | <o:p> </o:p> YmultiInstanceAttributes |
Multiple instance of an Composite Task<o:p></o:p> | 表示Composite节点多实例<o:p></o:p> |
<o:p> </o:p>
<o:p> </o:p>
YAWL的Decomposition含义<o:p></o:p>
Decomposition代表了一个任务的真实定义,每一个Task元素都将指向一个Decomposition元素。The decomposition element can define the implementation of an atomic task or a composite task,并且,多个任务可以指向同一个Decompostion,从而完成同样的工作。<o:p></o:p>
每一个Task都会利用 decomposesTo 元素 来指向其 Decomposition。<o:p></o:p>
<o:p> </o:p>
<decomposition id="make record" xsi:type="NetFactsType"><o:p></o:p>
如果decomposition的type为“NetFactsType”,则代表是一个个Composite Task。<o:p></o:p>
<o:p> </o:p>
if ("NetFactsType".equals(decompositionType)) {<o:p></o:p>
task = new YCompositeTask(<o:p></o:p>
taskID,<o:p></o:p>
splitJoinTypes[1], splitJoinTypes[0],<o:p></o:p>
(YNet) _decomposition);<o:p></o:p>
} else if ("WebServiceGatewayFactsType".equals(decompositionType) || decomposesToID == null) {<o:p></o:p>
task = new YAtomicTask(<o:p></o:p>
taskID,<o:p></o:p>
splitJoinTypes[1], splitJoinTypes[0],<o:p></o:p>
(YNet) _decomposition);<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
当一个过程定义被引擎加载的时候,引擎会为这个Specifcation中的每一个Decomposition分配至少一个YAWL Service。而每一个Task Decompostion都必须指明其所需要注册的YAWL Servier(s)。<o:p></o:p>
<o:p> </o:p>
有必要说一下的是,YAWL的数据表示,采用了对Xpath和Xqueue的支持。
<expression query="/data/hotelDetails"/>
这个在Task的startingMappings, completedMappings;Decomposition中的outputExpression 元素中都有体现。<o:p></o:p>
<o:p> </o:p>
YAWL的YAWL Service
YAWL系统环境是由 YAWL Service提供的。最终用户、组织模型、应用程序都被抽象为一种服务。YAWL提供了四种服务:worklist handler,webservice broker,interop broker,custom YAWL service。
<o:p> </o:p>
YAWL引擎
YAWL的引擎类是 au.edu.qut.yawl.engine.YEngine
<o:p> </o:p>
YEngine提供了一个单态engine实例,在初始化的时候,需要注册web service的访问服务类<o:p></o:p>
<o:p> </o:p>
public static YEngine getInstance(boolean networked) {<o:p></o:p>
if (_myInstance == null) {<o:p></o:p>
_myInstance = new YEngine();<o:p></o:p>
YAWLService ys = new YAWLService("http://localhost:8080/yawlWSInvoker/", null);<o:p></o:p>
_myInstance.setRegisteredYawlService(ys);<o:p></o:p>
}<o:p></o:p>
return _myInstance;<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
Yengine提供了加载引擎定义文件,启动或取消Case实例(YAWL每一个流程实例叫一个Case),Check Out以及完成Workitem,开始和挂起Workitem, 完成Case。等等
<o:p> </o:p>
Yengine实例在初始化的,会注册 YAWLService。
<o:p> </o:p>
YAWL的YWorkItemRepository
YworkitemRepository 提供了对 Workitem的缓存。其本身是一个单态实例。
<o:p> </o:p>
private static Map _idStringToWorkItemsMap = new HashMap();//[case&taskIDStr=YWorkItem]<o:p></o:p>
protected static Map _caseToNetRunnerMap = new HashMap();<o:p></o:p>
<o:p> </o:p>
其将workitem对象缓存在一个map中。主键规则:case&taskIDStr 。通过这个主键,也说明其workitem的含义。
但是,也提供了一个对YnetRunner对象(流程实例对象的缓存)。—— 但是,在Engine对象中已经提供了对case实例的缓存,这地方又提供了一个接口。
<o:p> </o:p>
YAWL的流程实例(Case)的启动
启动一个流程,使调用Yengine的startCase方法。这个方法,最主要的是,构造一个Case实例对象:YNetRunner。
<o:p> </o:p>
这里就需要引入 au.edu.qut.yawl.engine.YNetRunner 类
其每一个Case就是一个YnetRunner实例。由于YNetRunner extends Thread ,其每一个Case其实就一个执行线程。<o:p></o:p>
<o:p> </o:p>
YNetRunner还有一个静态属性 YworkItemRepository的对象(其实是一个单态对象);并且提供了对engine对象的引用。<o:p></o:p>
同时YNetRunner对象,还包含一个流程定义的元素对象:protected YNet _net; <o:p></o:p>
初始化的时候,这个_net对象一个clone: _net = (YNet) netPrototype.clone();<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
YnetRunner初始化的时候,会调用自身的prepare 方法,进行一些初始化。<o:p></o:p>
private void prepare() {<o:p></o:p>
_workItemRepository.setNetRunnerToCaseIDBinding(this, _caseIDForNet);<o:p></o:p>
/* 获取流程的起始节点:inputCondition */<o:p></o:p>
YInputCondition inputCondition = _net.getInputCondition();<o:p></o:p>
inputCondition.add(_caseIDForNet);<o:p></o:p>