Các ví dụ chuyển đổi

Một phần của tài liệu Khảo sát khả năng sử dụng ngôn ngữ bpel để cài đặt các mô hình tiến trình phần mềm (Trang 86 - 118)

5.4.1 Fagan Code Inspection

Mô hình Fagan Code Inspection là mô hình tiến trình dùng cho việc kiểm duyệt mã nguồn. Việc kiểm duyệt bao gồm các hành động lên kế hoạch (Planning) với tham số đầu vào là mã nguồn (Source Code), xem xét tổng quan (Overview), chuẩn bị (Preparing) sau đó tiến hành thanh tra mã nguồn (Inspection Meeting), thay đổi mã nguồn (Rework) và kiểm tra (Follow Up). [Hình V-5] là mô hình Fagan Code Inspection đƣợc biểu diễn bằng UML- PP.

Hình V-5 Mô hình Fagan Code Inspection

Việc chuyển đổi mô hình Fagan Code Inpsection UML-PP sang mô hình BPEL đƣợc thực hiện lần lƣợt qua các bƣớc:

 Chuyển đổi đối tƣợng BehaviorModel sang đối tƣợng BPEL Process

 Khởi tạo phần đối tƣợng BPEL Import ( chứa các tham chiếu đến các file WSDL cần thiết)

 Khởi tạo các đối tƣợng BPEL PartnerLink

 Chuyển đổi các thành phần trong UML-PP sang BPEL Variable (nhƣ Product). Mỗi Task trong UML-PP sẽ đƣợc chuyển thành hai Variable, các tham số của Task sẽ đƣợc chuyển thành các nội dung của biến. Ví dụ, nội dung của biến PlanningIn có giá trị

’IN:Source Code’ có nghĩa tác vụ Planning nhận tham số đầu vào là Source Code

 Chuyển đổi tất cả các Task thành các đối tƣợng BPEL Invoke tƣơng ứng. Đồng thời chuyển đổi thứ tự thực thi các tác vụ thành các đối tƣợng BPEL, trong mô hình Fagan Code Inspection thứ tự thực thi là đối tƣợng BPEL Sequence.

Mô hình BPEL kết quả sẽ đƣợc chuyển sang dạng file BPEL XML sử dụng Acceleo. Kết quả file BPEL XML sẽ đƣợc kiểm tra trên nền tảng NetBeans 6.7.1 và thực thi trên GlassFish Server v2.1. Nhằm mục đích thực thi chúng tôi đã tạo sẵn dịch vụ web HumanTask giả lập để thực hiện tất cả các hoạt động mà qui trình phần mềm yêu cầu.

Hình V-7 Mô hình dịch vụ web HumanActivity

5.4.2 Refactor Code

Tiến trình Refactor Code mô tả các bƣớc cần thực hiện để tiến hành chỉnh sửa mã nguồn gồm các bƣớc: xác định các vấn đề trong mã nguồn (Identify Complexity In Code), tiến hành refactor (Apply Refactor Code) sau đó thực hiện unit test (Perform Unit Test). Ở mỗi bƣớc các hoạt động đều chấp nhận đầu vào mã nguồn, tình trạng của mã nguồn sẽ đƣợc thay đổi qua các bƣớc từ inspected đến inspected + unit tested. Việc chuyển đổi sang mô hình BPEL và file BPEL XML tƣơng tự mô hình Fagan Code Inspection. Các tham số đầu vào và đầu ra của hoạt động Apply Refactor Code sẽ đƣợc chuyển sang biến và giá trị của biến nhƣ sau: ‘IN:Source Code | OUT:Source Code (inspected)’.

Hình V-9 Mô hình BPEL Refactor Code sau khi kiểm tra

5.4.3 Modify Design

Tiến trình Modify Design mô tả quá trình thay đổi bản thiết kế. Các công việc sau khi bản thiết kế đƣợc thay đổi diễn ra song song nhƣ Review

Hình V-11 Mô hình BPEL của Modify Design sau khi kiểm tra

5.4.4 Mô hình sử dụng Process Pattern Binding

[Hình V-12] mô tả một tiến trình trong đó tác vụ Code Review sử dụng lại mẫu tiến trình Fagan Code Inspection theo kiểu Process Pattern Binding. Để có thể chuyển sang đƣợc mô hình BPEL, quan hệ Process Pattern Binding sẽ đƣợc mở ra. Kết quả ta có mô hình [Hình V-13].

Hình V-14 Mô hình BPEL sau khi kiểm tra

5.5 Kiểm chứng tiến trình kết quả BPEL

Các tiến trình kết quả sẽ đƣợc thực thi trên môi trƣờng Netbeans 6.7.1 sử dụng Glassfish Server v2.1

Chƣơng VI – KẾT LUẬN

6.1 Kết quả đạt đƣợc

Trong luận văn, để khảo sát việc tận dụng các môi trƣờng vận hành tiến trình nghiệp vụ, cụ thể là các hệ thống hỗ trợ BPEL, để thực thi các tiến trình phần mềm, chúng tôi đã sử dụng hƣớng tiếp cận kết hợp chuyển đổi từ mô hình UML-PP sang BPEL.

Giải pháp chuyển đổi đƣợc thực hiện trên hai mức: chuyển đổi mô hình sang mô hình và từ mô hình sang văn bản. Sau khi xây dựng các metamodel mô tả ngôn ngữ nguồn UML-PP và ngôn ngữ đích BPEL cũng nhƣ xây dựng bộ luật chuyển đổi UML-PP sqng BPEL, chúng tôi đã sử dụng ATL để cài đặt chuyển đổi mô hình UML-PP sang mô hình BPEL, sau đó sử dụng Acceleo để hiện thực chuyển đổi mô hình BPEL sang dạng XML theo bản đặc tả của BPEL.

Chúng tôi đã tiến hành thử nghiệm việc chuyển đổi với bốn mô hình tiến trình phần mềm là Fagan Code Inspection, Code Refactor, Modify Design và mô hình dùng Process Pattern Binding. Kết quả đƣợc kiểm tra và thực thi thành công trên GlassFish Server.

Nhƣ vậy, BPEL hỗ trợ tốt các tình huống tiến trình cơ bản, bất kể nghiệp vụ hay phần mềm.

Các kết quả chính của luận văn:

Lý thuyết:

 Cung cấp hƣớng tiếp cận để chuyển đổi ngôn ngữ mô hình hóa phần mềm UML-PP sang ngôn ngữ tiến trình nghiệp vụ BPEL (Mục 4.1)

 Khắc phục một số sai sót, dƣ thừa của bản metamodel UML-PP gốc của tác giả Tran.HN (13 luật – Phụ lục A)

 Cung cấp các luật cơ bản để chuyển đổi một số thành phần trong ngôn ngữ mô hình UML-PP sang BPEL (10 luật – Mục 4.4).

Thực nghiệm:

 Xây dựng đƣợc metamodel của ngôn ngữ BPEL 2.0

 Xây dựng đƣợc metamodel của ngôn ngữ UML-PP

 Xây dựng đƣợc công cụ mô hình hóa UML-PP dựa vào metamodel

 Thực hiện chuyển đổi và thực thi thành công một số mô hình tiến trình phần mềm đƣợc biểu diễn bởi UML-PP.

6.2 Nhận xét

Ngôn ngữ BPEL cung cấp nhiều khái niệm để phối hợp và thực thi tiến trình tuy nhiên BPEL có tính trừu tƣợng và trực quan không cao. Sử dụng BPEL ta khó có thể mô tả các tiến trình tổng quát hay các mẫu tiến trình dùng để sử dụng lại mặt khác việc lƣu trữ bằng XML sẽ gây khó khăn trong việc đọc hiểu và giao tiếp các tiến trình. Hơn thế nữa, BPEL thiếu hỗ trợ một số mẫu tiến trình, không có bộ ký hiệu, không hỗ trợ giao tiếp với ngƣời. Điều này khiến BPEL trở nên không phù hợp cho việc mô hình hóa, giao tiếp và hiểu các tiến trình phần mềm vốn dĩ dựa vào sự giao tiếp giữa ngƣời với ngƣời. Trong khi đó, UML-PP cung cấp bộ ký hiệu trực quan và đầy đủ với nhiều mức độ trừu tƣợng khác nhau nhƣng lại thiếu hỗ trợ thực thi. Trong đề tài này, chúng tôi đã thực hiện việc kết hợp cả hai ngôn ngữ trên để khắc phục các khuyết điểm của cả hai phía nhằm hỗ trợ việc mô hình hóa và thực thi tiến trình phần mềm.

Ƣu điểm hƣớng tiếp cận của đề tài là đã tận dụng đƣợc các bộ máy thực thi BPEL sẵn có để hỗ trợ thực thi các tiến trình phần mềm UML-PP. Tuy nhiên hƣớng tiếp cận này có các các khuyết điểm:

 Trong quá trình chuyển đổi, các khái niệm trong tiến trình phần mềm nhƣ Product, Role bị mất ngữ nghĩa khi đƣợc chuyển sang biến bên BPEL. Chỉ duy nhất các khái niệm hoạt động nhƣ Task, Step cùng với thứ tự các hoạt động là không bị ảnh hƣởng do bản thân các khái niệm này đã chứa ngữ nghĩa thực thi. Nhƣ vậy, điều

này dẫn đến hậu quả một số dữ liệu cần thiết cho quá trình đo lƣờng và cải tiến qui trình bị mất.

 Một vấn đề khác là trong khi một số khái niệm trong UML-PP có chuyển đổi 1-1 sang BPEL (nhƣ Task, ForkNode …) thì một số khác lại có nhiều tùy chọn nhƣ LoopNode có thể đƣợc chuyển sang

<while> hoặc <repeatUntil>, các hoạt động tuần tự đều có thể đƣợc chuyển sang <sequence> hoặc <flow>. Đồng thời một số khái niệm trong UML-PP không có khái niệm tƣơng ứng nhƣ ProcessPatternBinding, ProcessPatternApplying, cách tốt nhất để chuyển đổi khác khái niệm này sang BPEL là phải tiến hành unfold tất cả các tiến trình phần mềm này. Khi đó ngữ nghĩa sử dụng lại mẫu tiến trình trong UML-PP sẽ không còn trong BPEL.

 Vấn đề cuối cùng, BPEL đƣợc tạo ra sau quá trình chuyển đổi không thể thực thi ngay đƣợc mà phải tiến hành cấu hình để gắn các mô tả và dịch vụ web (nhƣ thẻ <partnerLinkType>). Trong quá trình khảo sát, chúng tôi đã đặt các cấu hình này vào sẵn trong file template của Acceleo.

6.3 Hƣớng phát triển

Nhƣ đã trình bày, luận văn đã thực hiện kết hợp sử dụng các bộ máy thực thi BPEL để thực thi các tiến trình phần mềm UML-PP. Tuy nhiên luận văn chỉ dừng lại ở mức khảo sát và tiến hành chuyển đổi thử nghiệm trên bốn qui trình phần mềm, cần phải thử nghiệm trên nhiều qui trình phần mềm hơn nữa mới có thể đánh giá đầy đủ đƣợc hƣớng tiếp cận này. Một hƣớng phát triển là thử nghiệm việc chuyển đổi thực thi trên tất cả các mô hình ISPW-6. Hơn nữa, cần phải định nghĩa đầy đủ và hình thức tất cả các luật chuyển đổi từ mô hình UML-PP sang mô hình BPEL phục vụ cho việc cài đặt chuyển đổi tự động một mô hình UML-PP bất kỳ sang BPEL. Chuyển đổi tự động sẽ thực hiện cả hai bƣớc unfold tiến trình UML-PP và tạo file BPEL dạng

XML. Một hƣớng phát triển khác là hoàn thiện metamodel của UML-PP với đầy đủ các ràng buộc đƣợc tác giả mô tả trong [6] để tiến tới xây dựng công cụ hỗ trợ đầy đủ bộ ký hiệu và các thành tố trong UML-PP trên nền eclipse. Trong luận văn, chúng tôi đã tiến hành kiểm tra cú pháp file BPEL XML tạo ra trên NetBeans 6.7.1 nhƣng chƣa kiểm tra tự động đƣợc việc ánh xạ các thành phần từ UML-PP. Một hƣớng phát triển khác là xây dựng công cụ kiểm tra và đánh giá việc chuyển đổi.

B. PHỤ LỤC - MÃ NGUỒN ATL

File Umlpp2Bpel – chuyển đổi mô hình UML-PP sang mô hình BPEL

-- @path MMUmlpp=/vn.edu.tdt.atl.umlpp2bpel/metamodel/umlppcomplete.ecore -- @path MMBpel=/vn.edu.tdt.atl.umlpp2bpel/metamodel/bpelcomplete.ecore

module Umlpp2Bpel;

create OUT : MMBpel from IN : MMUmlpp;

-- Helper

-- Get all general tasks

helper context MMUmlpp!BehaviorModel def : getAllGeneralTasks() :

OrderedSet(MMUmlpp!GeneralTask) =

self.behaviorNodes->select( e | e.oclIsTypeOf(MMUmlpp!GeneralTask))

;

-- Get all tasks in process with order

helper context MMUmlpp!BehaviorModel def : getSequenceTasks() :

OrderedSet(MMUmlpp!GeneralTask) = self.behaviorNodes->select( e | e.oclIsTypeOf(MMUmlpp!InitialNode))->first() .outgoing->first().target- >getNextTasks() ;

-- Get all tasks after a task

helper context MMUmlpp!GeneralTask def : getNextTasks() : OrderedSet

(MMUmlpp!GeneralTask) = self.outgoing->select( e | e.oclIsTypeOf(MMUmlpp!ControlFlow)) ->collect( c | c.target) ->select (n | n.oclIsTypeOf(MMUmlpp!GeneralTask)) ->iterate(c ; tasks :

OrderedSet(MMUmlpp!GeneralTask) = OrderedSet{self} |

tasks->union(c- >getNextTasks())

) ;

-- Remove all space

helper context String def : wtrim() : String = self.replace(' ',''); -- Get task parameters

helper context MMUmlpp!GeneralTask def : getTaskParameters() : String = MMUmlpp!ObjectFlow->allInstances()->iterate(f;res : String =

'' |

if f.target = self and

f.source.oclIsTypeOf(MMUmlpp!GeneralProduct)

then res + 'IN:' + f.source.name + '|'

else if f.source = self and f.target.oclIsTypeOf(MMUmlpp!GeneralProduct)

then res + 'OUT:' + f.target.name + '|' else res endif endif ) ;

helper context MMUmlpp!BehaviorModel def : getForkNodes() :

OrderedSet(MMUmlpp!ForkNode) =

self.behaviorNodes->select( e | e.oclIsTypeOf(MMUmlpp!ForkNode))

;

helper context MMUmlpp!ForkNode def : getBranchTasks() :

OrderedSet(MMUmlpp!GeneralTask) =

MMUmlpp!ControlFlow->allInstances()->select(c | c.source =

self)->collect(c | c.target) ;

helper context MMUmlpp!ActivityNode def : isNextJoinNode() : Boolean =

self.outgoing->select(c |

c.oclIsTypeOf(MMUmlpp!ControlFlow))->exists( c | c.target.oclIsTypeOf(MMUmlpp!JoinNode))

;

helper context MMUmlpp!ActivityNode def : isPreviousForkNode() : Boolean

=

self.incoming->select(c |

c.oclIsTypeOf(MMUmlpp!ControlFlow))->exists( c | c.source.oclIsTypeOf(MMUmlpp!ForkNode))

;

helper context MMUmlpp!ActivityNode def : nextNode() :

MMUmlpp!ActivityNode =

self.outgoing->select(c |

c.oclIsTypeOf(MMUmlpp!ControlFlow))->first().target ;

helper context MMUmlpp!ActivityNode def : isFinalNode() : Boolean =

self.oclIsTypeOf(MMUmlpp!FinalNode) ;

helper context MMUmlpp!ActivityNode def : isForkNode() : Boolean =

self.oclIsTypeOf(MMUmlpp!ForkNode) ;

helper context MMUmlpp!ActivityNode def : isJoinNode() : Boolean =

self.oclIsTypeOf(MMUmlpp!JoinNode) ;

helper context MMUmlpp!ActivityNode def : isGeneralTask() : Boolean =

self.oclIsTypeOf(MMUmlpp!GeneralTask) ;

helper context MMUmlpp!BehaviorModel def : getSequenceNodes() :

OrderedSet(MMUmlpp!ActivityNode) =

self.behaviorNodes->select(c |

c.oclIsTypeOf(MMUmlpp!GeneralTask) or c.oclIsTypeOf(MMUmlpp!ForkNode)) ->select(c | not c.isNextJoinNode()

or not c.isPreviousForkNode() or c.oclIsTypeOf(MMUmlpp!ForkNode))

;

rule Behavior2Process {

from b : MMUmlpp!BehaviorModel to p : MMBpel!Process(

name <- b.name

,suppressJoinFailure <- true

,partnerLinks <- thisModule.Model2PartnerLinks(b) ,variables <- thisModule.Model2Variables(b)

,activity <- thisModule.Model2MainSequence(b) )

}

-- Create partner links

unique lazy rule Model2PartnerLinks{ from b : MMUmlpp!BehaviorModel to ps : MMBpel!PartnerLinks(

children <-

OrderedSet{thisModule.Model2PartnerLink(b),b.getAllGeneralTasks()- >collect(t | thisModule.Task2PartnerLink(t) )}

) }

-- Create partner link to call BPEL process

unique lazy rule Model2PartnerLink{ from b : MMUmlpp!BehaviorModel to ps : MMBpel!PartnerLink(

name <- b.name.wtrim().toLower() + '_client'

,partnerLinkType <- thisModule.Model2PartnerLinkType(b) ,myRole <- thisModule.Model2MyRole(b)

) }

unique lazy rule Model2PartnerLinkType{ from b : MMUmlpp!BehaviorModel to t : MMBpel!PartnerLinkType(

name <- b.name.wtrim() + 'PL' )

}

unique lazy rule Model2MyRole{

from b : MMUmlpp!BehaviorModel to r : MMBpel!Role(

name <- b.name.wtrim() + 'Provider'

) }

-- Create partner link for each task

unique lazy rule Task2PartnerLink{ from t : MMUmlpp!GeneralTask to p : MMBpel!PartnerLink(

name <- t.name.wtrim().toLower() + '_service'

,partnerRole <- thisModule.Task2PartnerRole(t)

,partnerLinkType <- thisModule.Task2PartnerLinkType(t) )

}

unique lazy rule Task2PartnerLinkType{ from t : MMUmlpp!GeneralTask to l : MMBpel!PartnerLinkType(

name <- t.name.wtrim() + 'PL' )

}

unique lazy rule Task2PartnerRole{ from t : MMUmlpp!GeneralTask

to r : MMBpel!Role(

name <- t.name.wtrim() + 'Provider' )

}

-- Create variables

unique lazy rule Model2Variables{ from b : MMUmlpp!BehaviorModel to v : MMBpel!Variables(

children <- OrderedSet{thisModule.Model2InVariable(b) ,thisModule.Model2OutVariable(b)

,b.getAllGeneralTasks()- >collect(task | thisModule.Task2InVariable(task))

,b.getAllGeneralTasks()- >collect(task | thisModule.Task2OutVariable(task))

} )

}

unique lazy rule Model2InVariable{ from b : MMUmlpp!BehaviorModel to v : MMBpel!Variable(

name <- b.name.wtrim() + 'InputVariable'

,messageType <- thisModule.Model2RequestMessageType(b) )

}

unique lazy rule Model2OutVariable{ from b : MMUmlpp!BehaviorModel to v : MMBpel!Variable(

name <- b.name.wtrim() + 'OutputVariable'

,messageType <- thisModule.Model2ResponseMessageType(b) )

}

unique lazy rule Model2RequestMessageType{ from b : MMUmlpp!BehaviorModel

to t : MMBpel!Message(

qName <- b.name.wtrim()+'RequestMessage' )

}

unique lazy rule Model2ResponseMessageType{ from b : MMUmlpp!BehaviorModel

to t : MMBpel!Message(

qName <- b.name.wtrim()+'ResponseMessage' )

}

unique lazy rule Task2InVariable{ from t : MMUmlpp!GeneralTask to v : MMBpel!Variable(

name <- t.name.wtrim() + 'In'

,messageType <- thisModule.Task2RequestMessageType(t) )

}

unique lazy rule Task2RequestMessageType{ from t : MMUmlpp!GeneralTask

to m : MMBpel!Message(

qName <- t.name.wtrim() + 'RequestMessage'

) }

unique lazy rule Task2OutVariable{ from t : MMUmlpp!GeneralTask to v : MMBpel!Variable(

name <- t.name.wtrim() + 'Out'

,messageType <- thisModule.Task2ResponseMessageType(t) )

}

unique lazy rule Task2ResponseMessageType{ from t : MMUmlpp!GeneralTask

to m : MMBpel!Message(

qName <- t.name.wtrim() + 'ResponseMessage'

) }

-- Create sequence

unique lazy rule Model2MainSequence{ from b : MMUmlpp!BehaviorModel to s : MMBpel!"Sequence"(

name <- 'main'

,activities <- Sequence{thisModule.Model2Receive(b)

,b.getSequenceNodes()- >iterate(n ; activities : Sequence(MMBpel!Activity) = Sequence{} |

if

(n.oclIsTypeOf(MMUmlpp!GeneralTask)) then

activities- >append(Sequence{thisModule.Task2Assign(n),thisModule.Task2Invoke(n)})

else if

(n.oclIsTypeOf(MMUmlpp!ForkNode)) then

activities- >append(thisModule.Fork2Flow(n))

else activities endif endif ) ,thisModule.Model2ReplyAssign(b) ,thisModule.Model2Reply(b) } ) }

unique lazy rule Fork2Flow{ from f : MMUmlpp!ForkNode to l : MMBpel!Flow( activities <- f->getBranchTasks()->collect(t | thisModule.Task2FlowSeq(t)) ) }

unique lazy rule Task2FlowSeq{ from t : MMUmlpp!GeneralTask to s : MMBpel!"Sequence"(

activities <- t->getNextTasks()->collect( g |

Sequence{thisModule.Task2Assign(g),thisModule.Task2Invoke(g)})->flatten() )

}

unique lazy rule Task2Assign{ from t : MMUmlpp!GeneralTask

to a : MMBpel!Assign(

name <- 'Assign_' + t.name.wtrim() ,copy <- thisModule.Task2Copy(t) )

}

unique lazy rule Task2Invoke{ from t : MMUmlpp!GeneralTask to i : MMBpel!Invoke(

name <- 'Invoke_' + t.name.wtrim()

,partnerLink <- thisModule.Task2PartnerLink(t) ,operation <- thisModule.Task2Operation(t) ,inputVariable <- thisModule.Task2InVariable(t) ,outputVariable <- thisModule.Task2OutVariable(t) ,portType <- thisModule.Task2PortType(t)

) }

unique lazy rule Task2Copy{

from t : MMUmlpp!GeneralTask to c : MMBpel!Copy(

"from" <- thisModule.Task2From(t) ,"to" <- thisModule.Task2To(t) )

}

unique lazy rule Task2From{

from t : MMUmlpp!GeneralTask to f : MMBpel!From(

expression <- thisModule.Task2FromExpression(t) )

}

unique lazy rule Task2FromExpression{ from t : MMUmlpp!GeneralTask to f : MMBpel!Expression(

body <- t.getTaskParameters() )

}

unique lazy rule Task2To{

from t : MMUmlpp!GeneralTask to f : MMBpel!To(

variable <- thisModule.Task2InVariable(t) ,part <- thisModule.Task2Part(t)

) }

unique lazy rule Task2Part{

from t : MMUmlpp!GeneralTask to p : MMBpel!Part(

name <- 'input'

) }

unique lazy rule Task2PortType{ from t : Umlpp!GeneralTask to p : MMBpel!PortType(

qName <- t.name.wtrim() + 'PT' )

}

unique lazy rule Task2Operation{ from t : Umlpp!GeneralTask to o : MMBpel!Operation(

name <- t.name.wtrim() )

}

unique lazy rule Model2Receive{ from b : MMUmlpp!BehaviorModel to r : MMBpel!Receive(

name <- 'Start' + b.name.wtrim()

,operation <- thisModule.Model2ReceiveOp(b) ,createInstance <- true

,partnerLink <- thisModule.Model2PartnerLink(b) ,portType <- thisModule.Model2ReceivePortType(b) ,variable <- thisModule.Model2InVariable(b) )

}

unique lazy rule Model2ReceiveOp{ from b : MMUmlpp!BehaviorModel to o : MMBpel!Operation(

name <- b.name.wtrim() )

}

unique lazy rule Model2ReceivePortType{ from b : MMUmlpp!BehaviorModel to r : MMBpel!PortType(

qName <- b.name.wtrim() + 'PT'

) }

unique lazy rule Model2ReplyAssign{ from b : MMUmlpp!BehaviorModel to a: MMBpel!Assign(

name <- 'Assign_Exit '

,copy <- thisModule.Model2ReplyCopy(b) )

}

unique lazy rule Model2Reply{

from b : MMUmlpp!BehaviorModel to r : MMBpel!Reply(

name <- 'Exit' + b.name.wtrim()

,operation <- thisModule.Model2ReceiveOp(b) ,partnerLink <- thisModule.Model2PartnerLink(b) ,portType <- thisModule.Model2ReceivePortType(b) ,variable <- thisModule.Model2OutVariable(b)

Một phần của tài liệu Khảo sát khả năng sử dụng ngôn ngữ bpel để cài đặt các mô hình tiến trình phần mềm (Trang 86 - 118)