久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

基于 GMF 的流程分析工具的設(shè)計(jì)與實(shí)現(xiàn)

 guoery 2010-07-15

級(jí)別: 中級(jí)

張 輝 ([email protected]), IBM 中國(guó) SOA 設(shè)計(jì)中心,軟件工程師, IBM
陳 雷 ([email protected]), IBM 中國(guó) SOA 設(shè)計(jì)中心,高級(jí)軟件工程師, IBM
任 志宏 ([email protected]), IBM 中國(guó) SOA 設(shè)計(jì)中心,高級(jí)軟件工程師, IBM
劉 偉 ([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
Process Editor

圖 2.Flow Editor
Flow Editor

本文將從定義領(lǐng)域模型入手,一步一步地介紹實(shí)現(xiàn)的細(xì)節(jié),。





回頁首


GMF建模

GMF框架提供了對(duì)一個(gè)具體的Ecore模型進(jìn)行圖形化建模的支持,以模型驅(qū)動(dòng)的方式,,一步一步完成功能描述,,直至代碼的生成。參見(Graphical Model Framework進(jìn)階),。本文的環(huán)境如下:

  • Eclipse3.3.0
  • EMF2.3.0
  • GEF3.3.0
  • GMF2.0

 

ECore模型

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模型
Process的ECore模型

當(dāng)然,,開發(fā)人員也可以直接用傳統(tǒng)的樹形EMF編輯器構(gòu)上面的Ecore模型,或用RSA(Rational Software Architect)對(duì)模型進(jìn)行UML圖的描述,,再轉(zhuǎn)換成Ecore模型,。

Graph模型

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>
GMF模型向?qū)?src="http://image12.360doc.com/DownloadImg/2010/07/1512/4057252_7.gif"

圖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模型

在Graph模型中,,選擇Map元素為根元素,這里只是簡(jiǎn)單的為每個(gè)元素定義了圖元信息,。關(guān)于圖元外觀的定制會(huì)在下面介紹,。

Tool模型

圖形化建模工具里有一個(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模型

這里使用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模型

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模型
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 模型

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模型
Process Gen模型

圖 10.Flow Gen模型
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的布局

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的布局

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的布局
            public class ConnectionLayout extends DelegatingLayout {
            public void layout(IFigure parent) {
            ...
            Connection conn = (Connection)parent;
            points = new PointList();
            while(條件成立){
            Point p[i] = //計(jì)算第i個(gè)節(jié)點(diǎn)坐標(biāo)
            Points.add(p[i]);
            }
            ...
            conn.setPoints(points);
            }
            }
            

其次,,和Node的布局類似,把此布局管理器安裝到Connection的圖元上,,如下所示,。


清單 2. 安裝Connection的布局
            public class RelationshipConnection extends PolylineConnectionEx {
            public RelationshipConnection() {
            setLayoutManager(new ConnectionLayout());
            }
            }
            

這樣,在Connection進(jìn)行布局的時(shí)候就會(huì)把原來的直線通過計(jì)算變成折線形狀,,照此方法,,可以很容易的構(gòu)造出水平或垂直方向的樹形布局。

自定義Layout provider

在GMF生成的Diagram Editor里,,在編輯模型的時(shí)候,,可以選中一些或全部模型,在選擇工具條上的link icon按鈕或右鍵菜單里的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
自定義LayoutProvider

這里需要注意兩個(gè)方法

provides()方法,,該方法檢查當(dāng)前的Provider是否提供具體的方法,,檢查選中的節(jié)點(diǎn)是否可以被布局,并且驗(yàn)證被傳遞的布局類型是否是有效的,。

layoutLayoutNodes()方法,,該方法是真正計(jì)算所要布局的節(jié)點(diǎn)的坐標(biāo)從而進(jìn)行布局的更新,和上面提到的做Node的布局是類似的,。所不同的是此方法返回一個(gè)Runnable對(duì)象,,由這個(gè)Runnable對(duì)象的執(zhí)行,完成真正的布局功能的執(zhí)行,。具體的功能實(shí)現(xiàn)可參見GMF默認(rèn)的LayoutProvider: org.eclipse.gmf.runtime.diagram.ui.providers.internal.DefaultProvider,。





回頁首


UI外觀的修改

GMF和GEF一樣,都是用Draw2D來完成模型前端的顯示工作,,這里提到的對(duì)UI外觀的修改主要是對(duì)Draw2D功能的一些應(yīng)用,。

在GMF中,每一個(gè)EditPart都會(huì)有一個(gè)Figure或PolylineConnection對(duì)象來做其前端的顯示,,因此對(duì)UI的外觀的修改也就是對(duì)這些圖形屬性的修改,。

設(shè)置漸變背景色

圖2中,要實(shí)現(xiàn)圖形背景的漸變色,需要對(duì)TaskEditPart對(duì)應(yīng)的TaskFigure進(jìn)行修改,,在圖形進(jìn)行重新繪制時(shí)設(shè)置其背景色,。這里Draw2D提供了fillGradient()方法來繪制漸變色。如下:


清單 3. 設(shè)置漸變的背景色
            public void paintFigure(Graphics g) {
            super.paintFigure(g);
            Color oldForeground = g.getForegroundColor();
            Color oldBackground = g.getBackgroundColor();
            g.setForegroundColor(FlowUtil.FORE_COLOR);
            g.setBackgroundColor(FlowUtil.TASK_BG_COLOR);
            g.fillGradient(bounds, true);
            g.setForegroundColor(oldForeground);
            g.setBackgroundColor(oldBackground);
            }
            

設(shè)置子圖形位置

默認(rèn)情況下,,Process和Task節(jié)點(diǎn)的圖標(biāo)和文本是放在同一行的,,如何設(shè)置其為上下布局呢?修改它們對(duì)應(yīng)的XXXNameEditPart的兩個(gè)方法如下,,設(shè)置文本的在下,,圖標(biāo)在上:


清單 4. 設(shè)置文本和圖標(biāo)的布局
            protected void setLabelTextHelper(IFigure figure, String text) {
            if (figure instanceof WrapLabel) {
            WrapLabel l = (WrapLabel)figure;
            l.setText(text);
            l.setTextPlacement(PositionConstants.SOUTH);
            l.setTextWrap(true);
            } else {
            ((Label) figure).setText(text);
            }
            }
            protected void setLabelIconHelper(IFigure figure, Image icon) {
            if (figure instanceof WrapLabel) {
            WrapLabel l = (WrapLabel)figure;
            l.setIcon(icon);
            l.setIconAlignment(PositionConstants.TOP);
            } else {
            ((Label) figure).setIcon(icon);
            }
            }
            





回頁首


自定義UI操作

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)建

模型的創(chuàng)建是由CreationEditPolicy來處理的,,如果一個(gè)EditPart需要?jiǎng)?chuàng)建其子元素,則需為其安裝一個(gè)CreationEditPolicy來控制子元素的生成,。通常為


清單 5. 安裝自定義的CreationEditPolicy
            installEditPolicy(EditPolicyRoles.CREATION_ROLE,	new XXXCreationEditPolicy());
            

其中,,XXXCreationEditPolicy是對(duì)CreationEditPolicy的一個(gè)擴(kuò)展,本實(shí)例中有個(gè)限制,,需要在創(chuàng)建一個(gè)Process節(jié)點(diǎn)的同時(shí),,創(chuàng)建一條和它的父節(jié)點(diǎn)的連線,也就是一個(gè)帶箭頭Connection連接,,實(shí)現(xiàn)getCreateCommand()如下,。


清單 6. 自定義CreationEditPolicy
            protected Command getCreateCommand(CreateViewRequest request) {
            TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
            .getEditingDomain();
            CompositeTransactionalCommand cc = //Create Process command
            ...
            Command cmd = new ICommandProxy(cc.reduce());
            CompoundCommand cm = new CompoundCommand();
            cm.add(cmd);
            // add Create Connection command
            if(request instanceof CreateViewAndElementRequest){
            CreateElementRequestAdapter requestAdapter =
            ((CreateViewAndElementRequest)request)
            .getViewAndElementDescriptor().getCreateElementRequestAdapter();
            if(CBSDiagramUtil.getInstance().getSourceEP() instanceof DANode2EditPart){
            CreateChildrenRelation4ProcessCommand cmd1 = createRalationCommand(
            editingDomain,
            (CreateViewAndElementRequest)request,
            requestAdapter);
            Command cmd2 = new ICommandProxy(cmd1);
            cm.add(cmd2);
            }
            }
            return new ICommandProxy(new CommandProxy(cm.unwrap()));
            }
            private CreateChildrenRelation4ProcessCommand createRelationCommand(
            TransactionalEditingDomain editingDomain, CreateViewAndElementRequest request,
            CreateElementRequestAdapter requestAdapter) {
            Diagram diagramView = (View)getHost().getModel()).getDiagram();
            IElementType type = ProcessElementTypes.Relation_3001;
            CreateConnectionViewAndElementRequest req =
            New CreateConnectionViewAndElementRequest(type,
            ((IHintedType) type).getSemanticHint(),
            request.getViewAndElementDescriptor().getPreferencesHint());
            CreateChildrenRelation4ProcessCommand cmd =
            new CreateChildrenRelation4ProcessCommand(editingDomain,requestAdapter,req,
            diagramView.getDiagram());
            return cmd ;
            }
            

在創(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類似,,需要指定CreateElementRequestAdapter, SemanticHint,然后由RelationshipViewFactoryCreateView()方法來生成一個(gè)Edge對(duì)象,。所有的這些操作都是在CreateChildrenRelation4PorcessCommand類的doExecuteWithResult()方法里面進(jìn)行,,具體操作由CreateRelationView()方法完成,其中containerView為Diagram View,,因?yàn)樗械腜rocess View都是Diagram View的子節(jié)點(diǎn),。


清單 7. 創(chuàng)建Relation View
            private void createRelationView() {
            DARelationViewFactory drvf = new DARelationViewFactory();
            final int index = -1 ;
            boolean persisted = true ;
            final String semanticHint = connReq.getConnectionViewAndElementDescriptor()
            .getSemanticHint();
            ConnectionViewAndElementDescriptor ccd =
            connReq.getConnectionViewAndElementDescriptor();
            final CreateElementRequestAdapter rAdapter = ccd.getCreateElementRequestAdapter();
            PreferencesHint preferencesHint = ccd.getPreferencesHint();
            Node srcNode = getSrcView();
            Node tgtNode = getTgtView();
            if(srcNode == null || tgtNode == null){
            return ;
            }
            View view = drvf.createView(rAdapter, containerView, semanticHint,
            index, persisted, preferencesHint);
            Edge edge = (Edge)view;
            edge.setSource(srcNode);
            edge.setTarget(tgtNode);
            }
            

刪除

在EditPolicy中,有一個(gè)SemanticEditPolicy,,GMF生成的代碼框架中常會(huì)以此EditPolicy為基礎(chǔ),派生出XXXBaseItemSemanticEditPolicy,,進(jìn)而派生出其他EditPart所需的具體的XXXItemSemanticEditPolicy,。正是這個(gè)EditPolicy控制著元素的刪除操作。安裝在EditPart上的SemanticEditPolicy控制此EditPart被刪除時(shí)所進(jìn)行的操作,。

在本實(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è)CustomizeDestroyElementCommand,由它來完成具體的刪除操作,。


清單 8. 自定義DestroyElementCommand
            public class CustomizeDestroyElementCommand extends DestroyElementCommand {
            …
            @Override
            protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
            ProcessEditPart editpart = (ProcessEditPart)getHost();
            if(root == null) {
            root = (ProcessEditPart)editpart.getParent();
            }
            // delete all descents and their relative process flow
            List children = editpart.getSourceConnections();
            int size = children.size();
            for(int i=0; i<size; i++) {
            delete((ProcessEditPart)((RelationshipsEditPart)children.get(i)).getTarget());
            }
            // update parent's process flow
            List targetConns = editpart.getTargetConnections();
            if(targetConns.size() != 0) {
            ProcessEditPart parent =
            (ProcessEditPart)((RelationshipsEditPart)targetConns.get(0)).getSource();
            Diagram flowDiagram = getOrDeleteProcessFlowDiagram(parent, false);
            if(flowDiagram != null) {
            deleteFlow(flowDiagram, ((Node)editpart.getModel()).getElement());
            }
            }
            // delete self process flow and close flow editor if acitved
            Diagram flowDiagram  = getOrDeleteProcessFlowDiagram(editpart, true);
            if(flowDiagram != null) {
            closeEditor(flowDiagram);
            }
            return super.doExecuteWithResult(monitor, info);
            }
            }
            

其次需要把上面的Command安裝在正確的地方,,如下,修改ProcessEditPart的XXXItemSemanticEditPolicy的方法如下,,用CustomizeDestroryElementCommand替換掉原有的Command,。


清單 9. 應(yīng)用自定義的DestroyElementCommand
            protected Command getDestroyElementCommand(DestroyElementRequest req) {
            CompoundCommand cc = getDestroyEdgesCommand();
            addDestroyShortcutsCommand(cc);
            View view = (View) getHost().getModel();
            if (view.getEAnnotation("Shortcut") != null) { //$NON-NLS-1$
            req.setElementToDestroy(view);
            }
            cc.add(getGEFWrapper(new CustomizeDestroyElementCommand(req)));
            return cc.unwrap();
            }
            





回頁首


多編輯器的支持

很明顯,這里需要處理多個(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è)EditingDomainManager來管理EditingDomain和文件所對(duì)應(yīng)Resource。由這個(gè)Manager維護(hù)當(dāng)前處于活躍狀態(tài)的EditingDomain和Resource,,F(xiàn)low Editor共享其對(duì)應(yīng)的Process Editor的EditingDomain,。


清單 10. EditingDomain Manager
            public class EditingDomainManager {
            public TransactionalEditingDomain getCurrentEditingDomain(final String id){
            ...
            return editingDomain ;
            }
            public Diagram getDiagramOfElement(Resource gmfRes, String editorID, Process element) {
            ...
            return  getDiagram(gmfRes, kind,element);
            }
            }
            

其次,需要用DiagramEditorInput來替換默認(rèn)的以文件為輸入的FileEditorInput,。雙擊一個(gè)Process圖標(biāo)的時(shí),,如果當(dāng)前節(jié)點(diǎn)沒有對(duì)應(yīng)的Diagram,則由initialFlowDiagram()方法生成一個(gè)空的Diagram對(duì)象,,然后構(gòu)造DiagramEditorInput來打開Flow Editor,。


清單 11. 打開Flow Editor
            private void openFlowEditor() {
            ...
            IWorkbenchPage page = PlatformUI.getWorkbench()
            .getActiveWorkbenchWindow().getActivePage();
            if(!isFlowDiagramExisted(node)){
            initialFlowDiagram(node);
            }
            Diagram diagram = getProcessNodeDiagram(node);
            DiagramEditorInput input = new DiagramEditorInput(diagram);
            try {
            IEditorPart ep = page.openEditor(input, editorId, true);
            } catch (PartInitException e) {
            e.printStackTrace();
            }
            }
            

為了從DiagramEditorInput打開一個(gè)Editor,F(xiàn)low Diagram Editor要修改它的getDiagram()方法,,默認(rèn)的getDiagram()方法沒有提供對(duì)DiagramEditorInput的處理,。


清單 12. 修改Flow Editor的方法
            @Override
            public Diagram getDiagram() {
            IEditorInput input = getEditorInput();
            if(input instanceof DiagramEditorInput){
            DiagramEditorInput dinput = (DiagramEditorInput)input;
            return dinput.getDiagram();
            }
            return super.getDiagram();
            }
            

此外還需要對(duì)FlowDocumentProvider進(jìn)行相應(yīng)的修改,重載三個(gè)函數(shù)如下


清單 13. 修改DocumentProvider
            @Override
            public IEditorInput createInputWithEditingDomain(IEditorInput editorInput,
            TransactionalEditingDomain domain) {
            return editorInput;
            }
            @Override
            public IStatus getStatus(Object element) {
            return STATUS_OK;
            }
            @Override
            public boolean isModifiable(Object element) {
            if(element instanceof DiagramEditorInput){
            return true;
            }
            return super.isModifiable(element);
            }
            

這樣,,就可以同時(shí)打開多個(gè)Process文件,,并且編輯多個(gè)Flow Editor了,具體如圖1圖2所示,。





回頁首


結(jié)束語

GMF2.0在前一個(gè)版本的基礎(chǔ)上,,在可用性和功能上都有了很大的改進(jìn),本文用一個(gè)完整的例子介紹了GMF在從建模,、模型修改到生成代碼框架以及對(duì)代碼定制的過程,,對(duì)GMF的應(yīng)用和開發(fā)做了一個(gè)系統(tǒng)的介紹。當(dāng)然,,GMF本身還在不斷的完善中,,新的功能也會(huì)不斷的包含近來,希望能有越來越多的人學(xué)習(xí)和使用GMF,。



參考資料



作者簡(jiǎn)介

 

張輝,,IBM中國(guó) SOA 設(shè)計(jì)中心,主要從事 SOA Domain Analyse 和 Legacy Transformation 的研發(fā),,目前在做 SOA Insdustry Model 相關(guān)的工作,,對(duì) SOA 應(yīng)用和業(yè)務(wù)流程的整合有濃厚的興趣,。聯(lián)系方式: [email protected]


 

陳雷:IBM 中國(guó) SOA 設(shè)計(jì)中心,高級(jí)軟件工程師,,從事 SOA 和企業(yè)整合相關(guān)的工作,,對(duì) J2EE,SOA 和相關(guān)的領(lǐng)域有著濃厚的興趣,,聯(lián)系方式: [email protected],。


 

任志宏:IBM 中國(guó) SOA 設(shè)計(jì)中心,高級(jí)軟件工程師,,從事 SOA 及 WebSphere 相關(guān)的工作,,對(duì) J2EE,SOA 和業(yè)務(wù)流程管理有著濃厚的興趣,,聯(lián)系方式: [email protected],。


 

劉偉:IBM 中國(guó) SOA 設(shè)計(jì)中心,軟件工程師,,主要從事 SOAIF Tooling 的設(shè)計(jì)和開發(fā)工作,。深入理解和應(yīng)用SOA、SOMA,、Web Services 等技術(shù)。個(gè)人興趣:書法,,繪畫,。聯(lián)系方式:[email protected]




原文鏈接: http://www.ibm.com/developerworks/cn/opensource/os-cn-eclipse-gmf2/part2/index.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多