Bossa研究总结(之一)

<o:p> </o:p>

Bossa研究总结<o:p></o:p>

<o:p> </o:p>

胡长城(银狐999)

<st1:chsdate month="10" islunardate="False" day="10" year="2004" w:st="on" isrocdate="False">2004-10-10</st1:chsdate>

<o:p> </o:p>

Bossa主站点:http://www.bigbross.com/bossa/

      

       Bossa与其说是一个workflow engine,不如说是一个Petri Net Engine。其完全采用Petri NetNotation,定义语言也是采用WFNet PNMLWFNet是其的Net Type)。

       其可以采用PNK进行模型定义,但是需要使用WFNetPNK支持配置文件,这个Bossa提供了,但是很遗憾的是,总是造成PNK的错误,可能与文件格式和编码有关系,这个后来因为时间问题,没有继续查找具体原因<o:p></o:p>

<o:p> </o:p>

       Bossa的帮助文档非常匮乏,即使其网站上提供的how toapi文档,也仅仅只是泛泛介绍。甚至没有一个如何正确运行其所提供了example的说明。<o:p></o:p>

<o:p> </o:p>

       Bossa支持的是Color Petri Net。这一点是由Case对象的attribute属性体现<o:p></o:p>

<o:p> </o:p>

Bossa的基本对象元素:

       这些主要对象元素,放在 com.bigbross.bossa.wfnet 包中。

       包括:CaseTypeCasePlaceTransitionEdgeActivityWorkitem

<o:p> </o:p>

<o:p> </o:p>

<o:p> </o:p>

CaseType

流程定义对象

Case

流程的实例

Place

对应于Petri Net中的元素 place

Transition

对应于Petri Net中的元素 transition

Edge

对应于Petri NetArc(有向弧)

Workitem

代表了一个Transtionfiring

This class represents a transition of a specific case instancea work item is a likely fireable transition

Activity

当打开一个workitem的时候就获取一个Activiy对象

This class represents an open (firing) work item<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

Bossatoken解决

       Petri Net允许从一个placetransition有几个arc,来表示允许几个token

       Bossa为了解决这个问题,引入了weight这个方式。而且允许这个weight是一个javascripte计算表达式(运行期间,解析表达式,返回的值就是token的个数)。

       但注意,weight本身并不是以属性存在于这些对象中,而是以方法。

<o:p> </o:p>

        List edges = activity.getTransition().getOutputEdges();<o:p></o:p>

        for (Iterator i = edges.iterator(); i.hasNext(); ) {<o:p></o:p>

            Edge e = (Edge) i.next();<o:p></o:p>

            /* An EvaluationException can be inconsistently thrown here. */<o:p></o:p>

            int tokenNumber = e.output(this);<o:p></o:p>

            this.marking[e.getPlace().getIndex()] += tokenNumber;<o:p></o:p>

            eventQueue.newPlaceEvent(getBossa(), WFNetEvents.ID_ADD_TOKENS,<o:p></o:p>

                                     this, e.getPlace(), tokenNumber);<o:p></o:p>

        }<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

BossaResouce

       Bossa中,ResouceTaskTransition)的执行者,但是其不是简单的实user的集合,在定义的时候,其表示的是一个“表达式”,而运行中,才会转换为相应得user list

       比如“sales - $a”,代表的就是,这个Task的执行者是“sales用户组中的用户 减去 a任务(Task,Transition)的执行者”。<o:p></o:p>

       注意,这个“表达式”,不是script的了,而是bossa自己的规则表达式。

<o:p> </o:p>

       但是,具体这个Resouce如何解析、运行。并没有深入

<o:p> </o:p>

Bossa的引擎

       Bossa的引擎类是 com.bigbross.bossa.Bossa.

       其是通过BossaFactory创建的

<o:p> </o:p>

BossaWorkitem

       注意,我们通常所理解的workitem概念,在Bossa中是不一样的。

       在一个CaseType,如果存在多少个Transition,则在一个Case实例中,则存在多少个Workitem。其workitem表示的代表一个transitionfirable状态。

<o:p> </o:p>

Collection ts = caseType.getTransitions();<o:p></o:p>

workItems = new HashMap(ts.size());<o:p></o:p>

for (i = ts.iterator(); i.hasNext(); ) {<o:p></o:p>

Transition t = (Transition) i.next();<o:p></o:p>

workItems.put(t.getId(), new WorkItem(this, t, isFireable(t)));<o:p></o:p>

}<o:p></o:p>

<o:p> </o:p>

       这个是在Case实例初始化的时候构造workitems列表,只是其中一些workitemfireable的,一些不是。

       每一次close activity之后,会更改workitemfirable状态(主要是调用其update方法)。    

<o:p> </o:p>

BossaEventQueqe

       com.bigbross.bossa.notify 包提供了一种事件监听、通知的机制。

      

       Listener

       Event

       NotificationBus 就是一个support类。

       NotificationQueue 表示的是一个“处理队列”类,提供记录了一些需要处理的Event可能。

<o:p> </o:p>

WFNetEvents extends NotificationQueue)则记录了所有有关 WFNetevent事件ID,以及调用这些事件的方法。每调用一个时间处理方法,如下所示

<o:p> </o:p>

    void newCaseEvent(Bossa bossa, String notificationId, Case caze) {<o:p></o:p>

        if (bossa != null) {<o:p></o:p>

            Map attrib = new HashMap();<o:p></o:p>

            attrib.put(ATTRIB_CASE_ID, Integer.toString(caze.getId()));<o:p></o:p>

            attrib.put(ATTRIB_CASE_TYPE_ID, caze.getCaseType().getId());<o:p></o:p>

            addEvent(new Event(notificationId, Event.WFNET_EVENT, attrib,<o:p></o:p>

                               bossa.getTimeSource().getTime()));<o:p></o:p>

        }<o:p></o:p>

    }<o:p></o:p>

<o:p> </o:p>

可以看出来,其是将一个event注入到NotificationQueue 所提供的queue列表中。

<o:p> </o:p>

那么是如何执行的呢?

        WFNetEvents queue = new WFNetEvents();<o:p></o:p>

        queue.newCaseEvent(getBossa(), WFNetEvents.ID_OPEN_CASE, caze);<o:p></o:p>

        queue.notifyAll(getBossa());<o:p></o:p>

<o:p> </o:p>

其最后调用notifyAll方法,来进行处理。

    public void notifyAll(Bossa bossa) {<o:p></o:p>

        if (bossa != null) {<o:p></o:p>

            NotificationBus bus = bossa.getNotificationBus();<o:p></o:p>

            for (Iterator i = queue.iterator(); i.hasNext(); ){<o:p></o:p>

                Event e = (Event) i.next();<o:p></o:p>

                bus.notifyEvent(e);<o:p></o:p>

                i.remove();         }        }    }<o:p></o:p>

<o:p> </o:p>

到这一步,就可以很清晰的明白了吧:

       整个内部还是一个“事件监听”,但是在这个事件监听外围,封装了一层“事件处理队列”。

<o:p> </o:p>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值