級(jí)別: 中級(jí) 張 輝 ([email protected]), IBM 中國(guó) SOA 設(shè)計(jì)中心,軟件工程師, IBM 2007 年 11 月 08 日 本文在 GMF2.0 的基礎(chǔ)上,,用一個(gè)自上而下的流程分析建模工具為例,完整的描述了從如何建模,,如何修改模型,以及如何客戶化生成的代碼框架的整個(gè)過程,,主要涉及布局,,UI 外觀,,模型操作以及對(duì)多個(gè) Editor 的支持等等。 GMF(Graphical Modeling Framework)是Eclipse的一個(gè)開源項(xiàng)目,,它在結(jié)合了EMF和GEF的基礎(chǔ)上,,為基于模型的圖形化編輯器的開發(fā)提供了一個(gè)功能強(qiáng)大的框架,開發(fā)人員可以采用建模的方式很容易的生成高質(zhì)量的代碼框架,。 GMF主要由開發(fā)工具和運(yùn)行時(shí)兩部分組成,。開發(fā)工具負(fù)責(zé)基于GMF核心模型的設(shè)計(jì)和建模工作,,包括:描述具體領(lǐng)域模型的 Graph 模型的表示,Tool 模型的表示,,以及如何用 Mapping 模型對(duì)前面三個(gè)模型進(jìn)行映射組合,,從而根據(jù)定義好的 Mapping 模型生成 Gen 模型,并最終完成代碼框架的生成,。三個(gè)獨(dú)立的模型設(shè)計(jì)大大提高了模型的可重用性,,開發(fā)人員可以在各模型所關(guān)注的領(lǐng)域?qū)ζ溥M(jìn)行進(jìn)一步的定制,這個(gè)將在深入了解GMF建模工具中有詳細(xì)介紹,。GMF的運(yùn)行時(shí)環(huán)境提供了豐富的組件(如Command框架,,Services, Global Action, Layout等等)和強(qiáng)大的擴(kuò)展機(jī)制,如org.eclipse.gmf.runtime.emf.ui.modelingAssistantProviders, org.eclipse.gmf.runtime.common.ui.services.parserProviders,,org.eclipse.gmf.runtime.diagram.core.viewProviders等等,,這些將在深入了解GMF運(yùn)行時(shí)框架中詳細(xì)地介紹。 剛發(fā)布的GMF2.0 在 GMF1.0 的基礎(chǔ)上進(jìn)一步提高了其易用性,,同時(shí)也加入了相當(dāng)?shù)男鹿δ?。比如:Diagram 內(nèi)容導(dǎo)航的支持,對(duì) RCP 應(yīng)用的支持,,對(duì) Preference Pages 的支持,,支持模型的合并等等。 本文主要基于 GMF2.0 的運(yùn)行環(huán)境,,介紹如何實(shí)現(xiàn)一個(gè)自上而下的 Process 分析工具,。其主要功能是:自上而下的分解一個(gè)大的 Process 為一批子 Process,每個(gè) Process 可以由一個(gè)具體的 Flow 來描述,,對(duì)于同一個(gè)模型,,可以由多個(gè)Editor去編輯,如Process Editor, Flow Editor,。期望的結(jié)果如下圖,。 圖 1.Process Editor 圖 2.Flow Editor 本文將從定義領(lǐng)域模型入手,一步一步地介紹實(shí)現(xiàn)的細(xì)節(jié),。
GMF框架提供了對(duì)一個(gè)具體的Ecore模型進(jìn)行圖形化建模的支持,以模型驅(qū)動(dòng)的方式,,一步一步完成功能描述,,直至代碼的生成。參見(Graphical Model Framework進(jìn)階),。本文的環(huán)境如下:
ECore模型是GMF建模的起點(diǎn),,通常ECore模型是一個(gè)領(lǐng)域模型,描述了要建模的領(lǐng)域特征,。其后的GMF借鑒了MVC的思想,,Ecore模型就是MVC中的Model,,詳情可參見(深入了解GMF建模工具)。 用EMF向?qū)陆ㄒ粋€(gè)空的process.ecore文件,,右鍵單擊該Ecore文件,,選擇Initiallize ecore_diagram diagram file,將會(huì)打開一個(gè)Ecore Diagram編輯器,,創(chuàng)建Process的ECore模型如下: 圖 3.Process的ECore模型 當(dāng)然,,開發(fā)人員也可以直接用傳統(tǒng)的樹形EMF編輯器構(gòu)上面的Ecore模型,或用RSA(Rational Software Architect)對(duì)模型進(jìn)行UML圖的描述,,再轉(zhuǎn)換成Ecore模型,。 Graph模型是用來描述領(lǐng)域模型的顯示信息,在GMF的定義中,,Graph模型原則上是一個(gè)獨(dú)立的模型,,它描述了一個(gè)用于信息顯示的模型。從它的定義里面就可以看出,,它描述了Diagram, Node, Connection和Figure等圖形化信息,。將其關(guān)聯(lián)到具體的領(lǐng)域模型上,就表示了該領(lǐng)域模型前端的顯示圖元,。 選擇已經(jīng)定義的領(lǐng)域模型,,打開向?qū)?duì)話框, 圖 4.GMF模型向?qū)?/strong> 在圖4中,,GMF提供了一系列向?qū)磔o助創(chuàng)建不同的GMF模型,。值得一提的是,GMF2.0支持對(duì)已有的Graph模型和Tool模型的提供更新操作,。對(duì)于一個(gè)已存在的模型,,新的更新會(huì)被自動(dòng)添加到模型中,而原有的部分不會(huì)影響,,參見(GMF2.0新特性介紹),。在具體的實(shí)現(xiàn)上,GMF2.0添加了Reconcile Graphical Definition Model和Reconcile Tool Definition Model兩個(gè)向?qū)硗瓿纱斯δ?,和GMF1.0相比,,這個(gè)設(shè)計(jì)更人性化。 在具體的操作中,,以上面定義的 ECore 模型為基礎(chǔ),,利用 GMF 向?qū)б徊揭徊降纳蓪?duì)應(yīng)的Graph模型如下圖5,操作細(xì)節(jié)不再贅述,。當(dāng)然,,也可以不用ECore模型,直接編輯一個(gè)空的Graph模型來進(jìn)行定制,,因?yàn)樵瓌t上Graph模型是獨(dú)立的,,可以被多個(gè) Ecore 模型和Mapping 模型公用的,。GMF向?qū)б?ECore 模型為基礎(chǔ),方便了開發(fā)人員進(jìn)行更有效的開發(fā),。 圖 5.自定義Graph模型 在Graph模型中,,選擇Map元素為根元素,這里只是簡(jiǎn)單的為每個(gè)元素定義了圖元信息,。關(guān)于圖元外觀的定制會(huì)在下面介紹,。 圖形化建模工具里有一個(gè)很重要的部分,就是Palette部分,,它定義一系列的Tool Entry項(xiàng),,每個(gè)Tool Entry項(xiàng)對(duì)應(yīng)工具所支持的某一類型對(duì)象的創(chuàng)建,如RSA Class Diagram的Palette里的Package, Class, Interface 等Tool Entry項(xiàng),。 GMF提供了對(duì)Palette部分的功能建模,。Tool模型提供了對(duì)將要在Diagram里面出現(xiàn)的Tool Entry項(xiàng)的描述,包括名稱,,描述等,。同時(shí),GMF Tool模型提供了對(duì)常用Tool Entry的支持,,此外,,還有一些標(biāo)準(zhǔn)的Tool Entry項(xiàng),如放大/縮小,,選擇,,注釋等等。Tool模型也是一個(gè)獨(dú)立的模型,,可以被多個(gè)ECore模型和Mapping模型共享,。 圖 6.自定義GMF Tool模型 這里使用GMF Tool模型創(chuàng)建向?qū)镋Core模型生成了一個(gè)Tool模型??梢栽谙旅娴膶傩砸怖锩鎸?duì)Tool Entry做一些基本的配置,,不過,上面的Default Image是不允許配置的,,GMF自動(dòng)為每個(gè)Tool Entry生成了默認(rèn)的圖標(biāo),,如果要自己定義圖標(biāo),可以使用Bundle Image來指定特定的圖標(biāo),。 Mapping模型是一個(gè)組織者,,針對(duì)前面提到的三個(gè)獨(dú)立的模型,由Mapping模型把這三個(gè)模型合理的組織起來,。在Mapping模型里,孤立的模型間有了相互的聯(lián)系,,領(lǐng)域模型的對(duì)象將會(huì)由特定的Graph模型里的圖元來進(jìn)行展示,,同時(shí),,還在Tool模型里為其設(shè)定一個(gè)Tool Entry作為Palette上的元素創(chuàng)建選項(xiàng)。 此外,,GMF Mapping模型還提供了豐富靈活的配置選項(xiàng),,詳情參見(深入了解GMF建模工具)。 圖 7.Process的Mapping模型 上圖中,,只提供了在一個(gè)Diagram Editor里面創(chuàng)建一個(gè)Process節(jié)點(diǎn)的功能,,實(shí)際需要每個(gè)Process節(jié)點(diǎn)下可以創(chuàng)建多個(gè)子節(jié)點(diǎn)。通常這種情況下,,需要在Node Mapping下創(chuàng)建一個(gè)Child Reference和Compartment Mapping來定義節(jié)點(diǎn)所包含的子節(jié)點(diǎn)的信息,,但是這樣一來,在Diagram的顯示上將會(huì)是一個(gè)Process節(jié)點(diǎn)圖形內(nèi)部包含了其所有的子Process節(jié)點(diǎn),,它們?cè)谇岸藞D形顯示上是一個(gè)包含關(guān)系,,不能滿足我們所期望的層次關(guān)系的表示。所以這里只是在Diagram定義了Process的節(jié)點(diǎn)的信息,,其父子節(jié)點(diǎn)的層次關(guān)系將在代碼部分解決,。 在這個(gè)例子中,我們需要在雙擊一個(gè)Process節(jié)點(diǎn)時(shí),,打開一個(gè)Flow Editor來對(duì)應(yīng)Process的內(nèi)部流程的編輯,,因此,需要再定義一個(gè)Flow Editor,,對(duì)應(yīng)的Mapping模型如下圖8 圖 8.Flow Mapping模型 在這個(gè)Flow里面關(guān)注3個(gè)元素,,Task、Decision和表示它們間流程關(guān)系的Relationship,。Flow Mapping模型共享了Process的Ecore模型和Graph模型,。 Gen模型是用來生成Diagram框架的模型,Gen 原模型描述了生成Diagram代碼框架所需要的一些元素,。在GMF中,,Gen模型由Mapping模型生成,一個(gè)Mapping模型對(duì)應(yīng)一個(gè)Gen模型,,當(dāng)然也可以由一個(gè)Mapping模型生成多個(gè)自定義的Gen模型,,這樣就可以生成多個(gè)Diagram Editor了。 圖 9.Process Gen模型 圖 10.Flow Gen模型 Gen模型和Mapping模型相比,,有更多關(guān)于代碼生成的屬性信息,,開發(fā)人員可以自己定義生成代碼的一些細(xì)節(jié)信息。在GMF2.0里,,加入了內(nèi)容導(dǎo)航元模型,,在Gen模型里會(huì)生成一個(gè)Gen Navigator項(xiàng),其下的一系列子項(xiàng)詳細(xì)定義了導(dǎo)航欄和編輯器間作內(nèi)容同步時(shí)的配置信息,。其次,,在Gen Diagram下面,,還增加了對(duì)Preference Page的支持,開發(fā)人員可以自己配制和定制Diagram的Preference page頁面,,GMF提供了預(yù)定義的一組標(biāo)準(zhǔn)的Preference page,,如Appearance, Printing, Connections等,當(dāng)然,,開發(fā)人員也可以預(yù)定義自己的Preference Page的配置情況,。GMF將會(huì)生成相應(yīng)的代碼框架,開發(fā)人員只需把注意力集中在具體的應(yīng)用邏輯上,。值得一提的是,,GMF Gen模型提供了對(duì)RCP應(yīng)用在Gen模型的支持,通過對(duì)Gen Application項(xiàng)的定義和配置,,可以很容易實(shí)現(xiàn)對(duì)RCP應(yīng)用的設(shè)置,,比如菜單項(xiàng),工具條等等,。 在一個(gè)GMF工程下面可以有多個(gè)Tool/Graph模型,,同時(shí)也可以有多個(gè)Mapping模型和對(duì)應(yīng)的Gen模型。事實(shí)上,,本實(shí)例中就是創(chuàng)建了兩個(gè)Mapping模型和Gen模型,,分別用于Process Diagram和Flow Diagram的建模。
在生成的代碼框架中,,GMF Diagram的默認(rèn)布局管理器是FreeFormLayoutEx,,在此布局管理器中,圖元采用XY布局管理,。這個(gè)和Process預(yù)期的自上而下的樹形布局不相符,,因此需要對(duì)Process Diagram的圖元布局管理器進(jìn)行一定的修改。 Node的布局是由它的父元素對(duì)應(yīng)的圖元的布局管理器來控制的,,在Process Diagram里Node就是Process圖元,,它的父容器就是Diagram,這樣,,通過修改Diagram的布局管理器就規(guī)范了其子節(jié)點(diǎn)(Process節(jié)點(diǎn))的布局了,。可參見(GMF進(jìn)階-自定義布局管理器和背景色) 所不同的只是Layout()方法的實(shí)現(xiàn),,本示例中用樹形的布局來組織Process節(jié)點(diǎn)的顯示,。 Connection圖元是一個(gè)由至少兩個(gè)點(diǎn)組成的線/折線,并且有可能帶有一個(gè)箭頭指向目標(biāo)節(jié)點(diǎn),。折線上點(diǎn)的位置和數(shù)量決定了折線的形狀和布局,。默認(rèn)的兩個(gè)圖元之間的一個(gè)連接是一條帶箭頭的直線,要實(shí)現(xiàn)圖所示的Connection的折線型布局,這里需要修改Connection的布局管理器,。 首先自定一個(gè)布局管理器,,在這個(gè)布局管理器里會(huì)自動(dòng)計(jì)算出折線的形狀。 清單 1. 自定義Connection的布局
其次,,和Node的布局類似,把此布局管理器安裝到Connection的圖元上,,如下所示,。 清單 2. 安裝Connection的布局
這樣,在Connection進(jìn)行布局的時(shí)候就會(huì)把原來的直線通過計(jì)算變成折線形狀,,照此方法,,可以很容易的構(gòu)造出水平或垂直方向的樹形布局。 在GMF生成的Diagram Editor里,,在編輯模型的時(shí)候,,可以選中一些或全部模型,在選擇工具條上的按鈕或右鍵菜單里的Format->Arrange->All,,就可以對(duì)選中的模型元素進(jìn)行布局,。 事實(shí)上,GMF對(duì)此功能提供了一個(gè)擴(kuò)展點(diǎn) org.eclipse.gmf.runtime.diagram.ui.layoutProviders進(jìn)行支持,,由這個(gè)擴(kuò)展點(diǎn)可以輕松實(shí)現(xiàn)上述功能,。下面實(shí)現(xiàn)一個(gè)CustomerLayoutProvider類, 圖 11.自定義LayoutProvider 這里需要注意兩個(gè)方法
GMF和GEF一樣,都是用Draw2D來完成模型前端的顯示工作,,這里提到的對(duì)UI外觀的修改主要是對(duì)Draw2D功能的一些應(yīng)用,。 在GMF中,每一個(gè)EditPart都會(huì)有一個(gè)Figure或PolylineConnection對(duì)象來做其前端的顯示,,因此對(duì)UI的外觀的修改也就是對(duì)這些圖形屬性的修改,。 在圖2中,要實(shí)現(xiàn)圖形背景的漸變色,需要對(duì) 清單 3. 設(shè)置漸變的背景色
默認(rèn)情況下,,Process和Task節(jié)點(diǎn)的圖標(biāo)和文本是放在同一行的,,如何設(shè)置其為上下布局呢?修改它們對(duì)應(yīng)的XXXNameEditPart的兩個(gè)方法如下,,設(shè)置文本的在下,,圖標(biāo)在上: 清單 4. 設(shè)置文本和圖標(biāo)的布局
GMF工具生成了一個(gè)很好的代碼框架,但是為了使其更加符合具體的應(yīng)用,,需要對(duì)生成的代碼進(jìn)行一定的修改,,尤其是對(duì)UI上的一些操作常常伴隨著模型的修改。由于GMF是基于事務(wù)的機(jī)制對(duì)模型進(jìn)行管理,,所以,,對(duì)模型的修改或更新操作需要放在一個(gè)具體的事務(wù)中進(jìn)行。GMF豐富的EditPolicy和Command機(jī)制提供了對(duì)上述的支持,。 模型的創(chuàng)建是由 清單 5. 安裝自定義的CreationEditPolicy
其中,, 清單 6. 自定義CreationEditPolicy
在創(chuàng)建一個(gè)Create Process命令后,緊接著在生成一個(gè)創(chuàng)建Connection的命令,,這樣就會(huì)在創(chuàng)建子Process后自動(dòng)創(chuàng)建一條與其父節(jié)點(diǎn)的連接,。 這里需要說明的一點(diǎn)是,在創(chuàng)建一個(gè)Connection對(duì)應(yīng)的模型信息是在對(duì)應(yīng)EditPart的XXXItemSemanticEditPolicy 生成的Command里完成的,,GMF2.0里面這個(gè)Command是作為一個(gè)獨(dú)立的Command放在command package下面的,,和其他的CreateElementCommand 類似。如果使用之前的GMF版本的話,,這個(gè)Command是作為XXXItemSemanticEditPolicy 的一個(gè)內(nèi)部類存在的,。
生成一個(gè)Connection對(duì)應(yīng)的模型后,需要在Diagram里面創(chuàng)建一個(gè)其對(duì)應(yīng)的Notation View的信息,,也就是一個(gè)Edge對(duì)象,,由這個(gè)Edge對(duì)象維護(hù)Connection的顯示信息,包括連線形狀,起始點(diǎn)和目標(biāo)節(jié)點(diǎn)等,。這和創(chuàng)建一個(gè)Node的Notation View類似,,需要指定 清單 7. 創(chuàng)建Relation View
在EditPolicy中,有一個(gè)SemanticEditPolicy,,GMF生成的代碼框架中常會(huì)以此EditPolicy為基礎(chǔ),派生出 在本實(shí)例中,,要求在刪除一個(gè)Process節(jié)點(diǎn)時(shí)刪除它所關(guān)聯(lián)的子節(jié)點(diǎn),如果此Process節(jié)點(diǎn)有Flow的信息,,刪除其對(duì)應(yīng)的Flow的信息,,并關(guān)閉對(duì)應(yīng)的Flow Editor(如果打開的話)?;谏鲜鲆?,首先需要自定義一個(gè) 清單 8. 自定義DestroyElementCommand
其次需要把上面的Command安裝在正確的地方,,如下,修改ProcessEditPart的 清單 9. 應(yīng)用自定義的DestroyElementCommand
很明顯,這里需要處理多個(gè)編輯器同時(shí)打開一個(gè)模型的情況,,我們希望可以在編輯Process樹的時(shí)候,,同時(shí)可以打開它的Flow Editor來編輯其具體的流程細(xì)節(jié)。但是如果用默認(rèn)的方法給一個(gè)編輯器設(shè)置一個(gè)文件作為輸入的話,,這一點(diǎn)是絕對(duì)做不到的,。因?yàn)镋clipse本身在第二次打開同樣的文件時(shí),如果發(fā)現(xiàn)它已經(jīng)被一個(gè)Editor打開就不會(huì)再次打開它,。 針對(duì)這種情況,,一種比較直接的辦法就是把一個(gè)模型拆分成一些小的部分,分別用文件保存,每個(gè)Editor之打開其中的一個(gè)文件,,像WBM就采用了類似的做法,。 還有一種就是整個(gè)模型就是一個(gè)文件,而用非文件的方式去打開和編輯模型,,像RSA就是這種作法,,整個(gè)模型就是一個(gè)大的.emx文件。本文計(jì)劃采用一個(gè)模型文件的做法,。 首先,,需要一個(gè) 清單 10. EditingDomain Manager
其次,需要用 清單 11. 打開Flow Editor
為了從DiagramEditorInput打開一個(gè)Editor,F(xiàn)low Diagram Editor要修改它的 清單 12. 修改Flow Editor的方法
此外還需要對(duì) 清單 13. 修改DocumentProvider
這樣,,就可以同時(shí)打開多個(gè)Process文件,,并且編輯多個(gè)Flow Editor了,具體如圖1和圖2所示,。
GMF2.0在前一個(gè)版本的基礎(chǔ)上,,在可用性和功能上都有了很大的改進(jìn),本文用一個(gè)完整的例子介紹了GMF在從建模,、模型修改到生成代碼框架以及對(duì)代碼定制的過程,,對(duì)GMF的應(yīng)用和開發(fā)做了一個(gè)系統(tǒng)的介紹。當(dāng)然,,GMF本身還在不斷的完善中,,新的功能也會(huì)不斷的包含近來,希望能有越來越多的人學(xué)習(xí)和使用GMF,。
原文鏈接: http://www.ibm.com/developerworks/cn/opensource/os-cn-eclipse-gmf2/part2/index.html |
|