小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

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

 guoery 2010-07-15

級別: 中級

張 輝 (cdlhuiz@cn.ibm.com), IBM 中國 SOA 設(shè)計中心,軟件工程師, IBM
陳 雷 (cdlchenl@cn.ibm.com), IBM 中國 SOA 設(shè)計中心,高級軟件工程師, IBM
任 志宏 (renzhih@cn.ibm.com), IBM 中國 SOA 設(shè)計中心,高級軟件工程師, IBM
劉 偉 (liuwcdl@cn.ibm.com), IBM 中國 SOA 設(shè)計中心,軟件工程師, IBM

2007 年 11 月 08 日

本文在 GMF2.0 的基礎(chǔ)上,用一個自上而下的流程分析建模工具為例,完整的描述了從如何建模,如何修改模型,以及如何客戶化生成的代碼框架的整個過程,主要涉及布局,UI 外觀,模型操作以及對多個 Editor 的支持等等。

前言

GMF(Graphical Modeling Framework)是Eclipse的一個開源項目,它在結(jié)合了EMF和GEF的基礎(chǔ)上,為基于模型的圖形化編輯器的開發(fā)提供了一個功能強大的框架,開發(fā)人員可以采用建模的方式很容易的生成高質(zhì)量的代碼框架。

GMF主要由開發(fā)工具和運行時兩部分組成。開發(fā)工具負責基于GMF核心模型的設(shè)計和建模工作,包括:描述具體領(lǐng)域模型的 Graph 模型的表示,Tool 模型的表示,以及如何用 Mapping 模型對前面三個模型進行映射組合,從而根據(jù)定義好的 Mapping 模型生成 Gen 模型,并最終完成代碼框架的生成。三個獨立的模型設(shè)計大大提高了模型的可重用性,開發(fā)人員可以在各模型所關(guān)注的領(lǐng)域?qū)ζ溥M行進一步的定制,這個將在深入了解GMF建模工具中有詳細介紹。GMF的運行時環(huán)境提供了豐富的組件(如Command框架,Services, Global Action, Layout等等)和強大的擴展機制,如org.eclipse.gmf.runtime.emf.ui.modelingAssistantProviders, org.eclipse.gmf.runtime.common.ui.services.parserProviders,org.eclipse.gmf.runtime.diagram.core.viewProviders等等,這些將在深入了解GMF運行時框架中詳細地介紹。

剛發(fā)布的GMF2.0 在 GMF1.0 的基礎(chǔ)上進一步提高了其易用性,同時也加入了相當?shù)男鹿δ?。比如:Diagram 內(nèi)容導航的支持,對 RCP 應用的支持,對 Preference Pages 的支持,支持模型的合并等等。

本文主要基于 GMF2.0 的運行環(huán)境,介紹如何實現(xiàn)一個自上而下的 Process 分析工具。其主要功能是:自上而下的分解一個大的 Process 為一批子 Process,每個 Process 可以由一個具體的 Flow 來描述,對于同一個模型,可以由多個Editor去編輯,如Process Editor, Flow Editor。期望的結(jié)果如下圖。


圖 1.Process Editor
Process Editor

圖 2.Flow Editor
Flow Editor

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





回頁首


GMF建模

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

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

 

ECore模型

ECore模型是GMF建模的起點,通常ECore模型是一個領(lǐng)域模型,描述了要建模的領(lǐng)域特征。其后的GMF借鑒了MVC的思想,Ecore模型就是MVC中的Model,詳情可參見(深入了解GMF建模工具)。

用EMF向?qū)陆ㄒ粋€空的process.ecore文件,右鍵單擊該Ecore文件,選擇Initiallize ecore_diagram diagram file,將會打開一個Ecore Diagram編輯器,創(chuàng)建Process的ECore模型如下:


圖 3.Process的ECore模型
Process的ECore模型

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

Graph模型

Graph模型是用來描述領(lǐng)域模型的顯示信息,在GMF的定義中,Graph模型原則上是一個獨立的模型,它描述了一個用于信息顯示的模型。從它的定義里面就可以看出,它描述了Diagram, Node, Connection和Figure等圖形化信息。將其關(guān)聯(lián)到具體的領(lǐng)域模型上,就表示了該領(lǐng)域模型前端的顯示圖元。

選擇已經(jīng)定義的領(lǐng)域模型,打開向?qū)υ捒颍?


圖 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支持對已有的Graph模型和Tool模型的提供更新操作。對于一個已存在的模型,新的更新會被自動添加到模型中,而原有的部分不會影響,參見(GMF2.0新特性介紹)。在具體的實現(xiàn)上,GMF2.0添加了Reconcile Graphical Definition Model和Reconcile Tool Definition Model兩個向?qū)硗瓿纱斯δ?,和GMF1.0相比,這個設(shè)計更人性化。

在具體的操作中,以上面定義的 ECore 模型為基礎(chǔ),利用 GMF 向?qū)б徊揭徊降纳蓪腉raph模型如下圖5,操作細節(jié)不再贅述。當然,也可以不用ECore模型,直接編輯一個空的Graph模型來進行定制,因為原則上Graph模型是獨立的,可以被多個 Ecore 模型和Mapping 模型公用的。GMF向?qū)б?ECore 模型為基礎(chǔ),方便了開發(fā)人員進行更有效的開發(fā)。


圖 5.自定義Graph模型
自定義Graph模型

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

Tool模型

圖形化建模工具里有一個很重要的部分,就是Palette部分,它定義一系列的Tool Entry項,每個Tool Entry項對應工具所支持的某一類型對象的創(chuàng)建,如RSA Class Diagram的Palette里的Package, Class, Interface 等Tool Entry項。

GMF提供了對Palette部分的功能建模。Tool模型提供了對將要在Diagram里面出現(xiàn)的Tool Entry項的描述,包括名稱,描述等。同時,GMF Tool模型提供了對常用Tool Entry的支持,此外,還有一些標準的Tool Entry項,如放大/縮小,選擇,注釋等等。Tool模型也是一個獨立的模型,可以被多個ECore模型和Mapping模型共享。


圖 6.自定義GMF Tool模型
自定義GMF Tool模型

這里使用GMF Tool模型創(chuàng)建向?qū)镋Core模型生成了一個Tool模型??梢栽谙旅娴膶傩砸怖锩鎸ool Entry做一些基本的配置,不過,上面的Default Image是不允許配置的,GMF自動為每個Tool Entry生成了默認的圖標,如果要自己定義圖標,可以使用Bundle Image來指定特定的圖標。

Mapping模型

Mapping模型是一個組織者,針對前面提到的三個獨立的模型,由Mapping模型把這三個模型合理的組織起來。在Mapping模型里,孤立的模型間有了相互的聯(lián)系,領(lǐng)域模型的對象將會由特定的Graph模型里的圖元來進行展示,同時,還在Tool模型里為其設(shè)定一個Tool Entry作為Palette上的元素創(chuàng)建選項。

此外,GMF Mapping模型還提供了豐富靈活的配置選項,詳情參見(深入了解GMF建模工具)。


圖 7.Process的Mapping模型
Process的Mapping模型

上圖中,只提供了在一個Diagram Editor里面創(chuàng)建一個Process節(jié)點的功能,實際需要每個Process節(jié)點下可以創(chuàng)建多個子節(jié)點。通常這種情況下,需要在Node Mapping下創(chuàng)建一個Child Reference和Compartment Mapping來定義節(jié)點所包含的子節(jié)點的信息,但是這樣一來,在Diagram的顯示上將會是一個Process節(jié)點圖形內(nèi)部包含了其所有的子Process節(jié)點,它們在前端圖形顯示上是一個包含關(guān)系,不能滿足我們所期望的層次關(guān)系的表示。所以這里只是在Diagram定義了Process的節(jié)點的信息,其父子節(jié)點的層次關(guān)系將在代碼部分解決。

在這個例子中,我們需要在雙擊一個Process節(jié)點時,打開一個Flow Editor來對應Process的內(nèi)部流程的編輯,因此,需要再定義一個Flow Editor,對應的Mapping模型如下圖8


圖 8.Flow Mapping模型
圖片示例

在這個Flow里面關(guān)注3個元素,Task、Decision和表示它們間流程關(guān)系的Relationship。Flow Mapping模型共享了Process的Ecore模型和Graph模型。

Gen 模型

Gen模型是用來生成Diagram框架的模型,Gen 原模型描述了生成Diagram代碼框架所需要的一些元素。在GMF中,Gen模型由Mapping模型生成,一個Mapping模型對應一個Gen模型,當然也可以由一個Mapping模型生成多個自定義的Gen模型,這樣就可以生成多個Diagram Editor了。


圖 9.Process Gen模型
Process Gen模型

圖 10.Flow Gen模型
Flow Gen模型

Gen模型和Mapping模型相比,有更多關(guān)于代碼生成的屬性信息,開發(fā)人員可以自己定義生成代碼的一些細節(jié)信息。在GMF2.0里,加入了內(nèi)容導航元模型,在Gen模型里會生成一個Gen Navigator項,其下的一系列子項詳細定義了導航欄和編輯器間作內(nèi)容同步時的配置信息。其次,在Gen Diagram下面,還增加了對Preference Page的支持,開發(fā)人員可以自己配制和定制Diagram的Preference page頁面,GMF提供了預定義的一組標準的Preference page,如Appearance, Printing, Connections等,當然,開發(fā)人員也可以預定義自己的Preference Page的配置情況。GMF將會生成相應的代碼框架,開發(fā)人員只需把注意力集中在具體的應用邏輯上。值得一提的是,GMF Gen模型提供了對RCP應用在Gen模型的支持,通過對Gen Application項的定義和配置,可以很容易實現(xiàn)對RCP應用的設(shè)置,比如菜單項,工具條等等。

在一個GMF工程下面可以有多個Tool/Graph模型,同時也可以有多個Mapping模型和對應的Gen模型。事實上,本實例中就是創(chuàng)建了兩個Mapping模型和Gen模型,分別用于Process Diagram和Flow Diagram的建模。





回頁首


自定義編輯器的布局

在生成的代碼框架中,GMF Diagram的默認布局管理器是FreeFormLayoutEx,在此布局管理器中,圖元采用XY布局管理。這個和Process預期的自上而下的樹形布局不相符,因此需要對Process Diagram的圖元布局管理器進行一定的修改。

Node的布局

Node的布局是由它的父元素對應的圖元的布局管理器來控制的,在Process Diagram里Node就是Process圖元,它的父容器就是Diagram,這樣,通過修改Diagram的布局管理器就規(guī)范了其子節(jié)點(Process節(jié)點)的布局了。可參見(GMF進階-自定義布局管理器和背景色

所不同的只是Layout()方法的實現(xiàn),本示例中用樹形的布局來組織Process節(jié)點的顯示。

Connection的布局

Connection圖元是一個由至少兩個點組成的線/折線,并且有可能帶有一個箭頭指向目標節(jié)點。折線上點的位置和數(shù)量決定了折線的形狀和布局。默認的兩個圖元之間的一個連接是一條帶箭頭的直線,要實現(xiàn)圖所示的Connection的折線型布局,這里需要修改Connection的布局管理器。

首先自定一個布局管理器,在這個布局管理器里會自動計算出折線的形狀。


清單 1. 自定義Connection的布局
            public class ConnectionLayout extends DelegatingLayout {
            public void layout(IFigure parent) {
            ...
            Connection conn = (Connection)parent;
            points = new PointList();
            while(條件成立){
            Point p[i] = //計算第i個節(jié)點坐標
            Points.add(p[i]);
            }
            ...
            conn.setPoints(points);
            }
            }
            

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


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

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

自定義Layout provider

在GMF生成的Diagram Editor里,在編輯模型的時候,可以選中一些或全部模型,在選擇工具條上的link icon按鈕或右鍵菜單里的Format->Arrange->All,就可以對選中的模型元素進行布局。

事實上,GMF對此功能提供了一個擴展點 org.eclipse.gmf.runtime.diagram.ui.layoutProviders進行支持,由這個擴展點可以輕松實現(xiàn)上述功能。下面實現(xiàn)一個CustomerLayoutProvider類,


圖 11.自定義LayoutProvider
自定義LayoutProvider

這里需要注意兩個方法

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

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





回頁首


UI外觀的修改

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

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

設(shè)置漸變背景色

圖2中,要實現(xiàn)圖形背景的漸變色,需要對TaskEditPart對應的TaskFigure進行修改,在圖形進行重新繪制時設(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è)置子圖形位置

默認情況下,Process和Task節(jié)點的圖標和文本是放在同一行的,如何設(shè)置其為上下布局呢?修改它們對應的XXXNameEditPart的兩個方法如下,設(shè)置文本的在下,圖標在上:


清單 4. 設(shè)置文本和圖標的布局
            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工具生成了一個很好的代碼框架,但是為了使其更加符合具體的應用,需要對生成的代碼進行一定的修改,尤其是對UI上的一些操作常常伴隨著模型的修改。由于GMF是基于事務(wù)的機制對模型進行管理,所以,對模型的修改或更新操作需要放在一個具體的事務(wù)中進行。GMF豐富的EditPolicy和Command機制提供了對上述的支持。

創(chuàng)建

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


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

其中,XXXCreationEditPolicy是對CreationEditPolicy的一個擴展,本實例中有個限制,需要在創(chuàng)建一個Process節(jié)點的同時,創(chuàng)建一條和它的父節(jié)點的連線,也就是一個帶箭頭Connection連接,實現(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)建一個Create Process命令后,緊接著在生成一個創(chuàng)建Connection的命令,這樣就會在創(chuàng)建子Process后自動創(chuàng)建一條與其父節(jié)點的連接。

這里需要說明的一點是,在創(chuàng)建一個Connection對應的模型信息是在對應EditPart的XXXItemSemanticEditPolicy生成的Command里完成的,GMF2.0里面這個Command是作為一個獨立的Command放在command package下面的,和其他的CreateElementCommand類似。如果使用之前的GMF版本的話,這個Command是作為XXXItemSemanticEditPolicy的一個內(nèi)部類存在的。

生成一個Connection對應的模型后,需要在Diagram里面創(chuàng)建一個其對應的Notation View的信息,也就是一個Edge對象,由這個Edge對象維護Connection的顯示信息,包括連線形狀,起始點和目標節(jié)點等。這和創(chuàng)建一個Node的Notation View類似,需要指定CreateElementRequestAdapter, SemanticHint,然后由RelationshipViewFactoryCreateView()方法來生成一個Edge對象。所有的這些操作都是在CreateChildrenRelation4PorcessCommand類的doExecuteWithResult()方法里面進行,具體操作由CreateRelationView()方法完成,其中containerView為Diagram View,因為所有的Process View都是Diagram View的子節(jié)點。


清單 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中,有一個SemanticEditPolicy,GMF生成的代碼框架中常會以此EditPolicy為基礎(chǔ),派生出XXXBaseItemSemanticEditPolicy,進而派生出其他EditPart所需的具體的XXXItemSemanticEditPolicy。正是這個EditPolicy控制著元素的刪除操作。安裝在EditPart上的SemanticEditPolicy控制此EditPart被刪除時所進行的操作。

在本實例中,要求在刪除一個Process節(jié)點時刪除它所關(guān)聯(lián)的子節(jié)點,如果此Process節(jié)點有Flow的信息,刪除其對應的Flow的信息,并關(guān)閉對應的Flow Editor(如果打開的話)?;谏鲜鲆螅紫刃枰远x一個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. 應用自定義的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();
            }
            





回頁首


多編輯器的支持

很明顯,這里需要處理多個編輯器同時打開一個模型的情況,我們希望可以在編輯Process樹的時候,同時可以打開它的Flow Editor來編輯其具體的流程細節(jié)。但是如果用默認的方法給一個編輯器設(shè)置一個文件作為輸入的話,這一點是絕對做不到的。因為Eclipse本身在第二次打開同樣的文件時,如果發(fā)現(xiàn)它已經(jīng)被一個Editor打開就不會再次打開它。

針對這種情況,一種比較直接的辦法就是把一個模型拆分成一些小的部分,分別用文件保存,每個Editor之打開其中的一個文件,像WBM就采用了類似的做法。

還有一種就是整個模型就是一個文件,而用非文件的方式去打開和編輯模型,像RSA就是這種作法,整個模型就是一個大的.emx文件。本文計劃采用一個模型文件的做法。

首先,需要一個EditingDomainManager來管理EditingDomain和文件所對應Resource。由這個Manager維護當前處于活躍狀態(tài)的EditingDomain和Resource,F(xiàn)low Editor共享其對應的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來替換默認的以文件為輸入的FileEditorInput。雙擊一個Process圖標的時,如果當前節(jié)點沒有對應的Diagram,則由initialFlowDiagram()方法生成一個空的Diagram對象,然后構(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打開一個Editor,F(xiàn)low Diagram Editor要修改它的getDiagram()方法,默認的getDiagram()方法沒有提供對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();
            }
            

此外還需要對FlowDocumentProvider進行相應的修改,重載三個函數(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);
            }
            

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





回頁首


結(jié)束語

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



參考資料



作者簡介

 

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


 

陳雷:IBM 中國 SOA 設(shè)計中心,高級軟件工程師,從事 SOA 和企業(yè)整合相關(guān)的工作,對 J2EE,SOA 和相關(guān)的領(lǐng)域有著濃厚的興趣,聯(lián)系方式: cdlchenl@cn.ibm.com。


 

任志宏:IBM 中國 SOA 設(shè)計中心,高級軟件工程師,從事 SOA 及 WebSphere 相關(guān)的工作,對 J2EE,SOA 和業(yè)務(wù)流程管理有著濃厚的興趣,聯(lián)系方式: renzhih@cn.ibm.com。


 

劉偉:IBM 中國 SOA 設(shè)計中心,軟件工程師,主要從事 SOAIF Tooling 的設(shè)計和開發(fā)工作。深入理解和應用SOA、SOMA、Web Services 等技術(shù)。個人興趣:書法,繪畫。聯(lián)系方式:liuwcdl@cn.ibm.com




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

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多