<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    sharky的點滴積累

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      56 隨筆 :: 104 文章 :: 10 評論 :: 0 Trackbacks

    GEF的設計沒有對模型部分做任何限制,也就是說,我們可以任意構造自己的模型,唯一須要保證的就是模型具有某種消息機制,以便在發生變化時能夠通知GEF(通過EditPart)。在以前的幾個例子里,我們都是利用java.beans包中的PropertyChangeSupport和PropertyChangeListener來實現消息機制的,這里將介紹一下如何讓GEF利用EMF構造的模型(下載例子,可編輯.emfsubject文件,請對比之前功能相同的非EMF例子),假設你對EMF是什么已經有所了解。

    EMF使用自己定義的Ecore作為元模型,在這個元模型里定義了EPackage、EClassifier、EFeature等等概念,我們要定義的模型都是使用這些概念來定義的。同時因為ecore中的所有概念都可以用本身的概念循環定義,所以ecore又是自己的元模型,也就是元元模型。關于ecore的詳細概念,請參考EMF網站上的有關資料。

    利用EMF為我們生成模型代碼可以有多種方式,例如通過XML Schema、帶有注釋的Java接口、Rose的mdl文件以及.ecore文件等,EMF的代碼生成器需要一個擴展名為.genmodel的文件提供信息,這個文件可以通過上面說的幾種方式生成,我推薦使用Omondo公司的EclipseUML插件來構造.ecore文件,該插件的免費版本可以從這里下載。

    subject_ecd.gif
    圖1 示例模型

    為了節約篇幅和時間,我就不詳細描述構造EMF項目的步驟了,這里主要把使用EMF與非EMF模型的區別做一個說明。圖1是例子中使用的模型,其中Dimension和Point是兩個外部java類型,由于EMF并不了解它們,所以定義為datatype類型。

    使用兩個Plugins

    為了讓模型與編輯器更好的分離,可以讓EMF模型單獨位于一個Plugin中(名為SubjectModel),而讓編輯器Plugin(SubjectEditor)依賴于它。這樣做的另一個好處是,當修改模型后,如果你愿意,可以很容易的刪除以前生成的代碼,然后全部重新生成。

    EditPart中的修改

    在以前我們的EditPart是實現java.beans.PropertyChangeListener接口的,當模型改用EMF實現后,EditPart應改為實現org.eclipse.emf.common.notify.Adapter接口,因為EMF的每個模型對象都是Notifier,它維護了一個Adapter列表,可以把Adapter作為監聽器加入到模型的這個列表中。

    實現Adapter接口時須要實現getTarget()和setTarget()方法,target代表發出消息的那個模型對象。我的實現方式是在EditPart里維護一個Notifier類型的target變量,這兩個方法分別返回和設置該變量即可。

    還要實現isAdapterForType()方法,該方法返回一個布爾值,表示這個Adapter是否應響應指定類型的消息,我的實現一律為"return type.equals(getModel().getClass());"。

    另外,propertyChanged()方法的名稱應改為notifyChanged()方法,其實現的功能和以前是一樣的,但代碼有所不同,下面是NodePart中的實現,看一下就應該明白了:

    public void notifyChanged(Notification notification) {
        
    int featureId = notification.getFeatureID(ModelPackage.class);
        
    switch (featureId) {
        
    case ModelPackage.NODE__LOCATION:
        
    case ModelPackage.NODE__SIZE:
            refreshVisuals();
            
    break;
        
    case ModelPackage.NODE__INCOMING_CONNECTIONS:
            refreshTargetConnections();
            
    break;
        
    case ModelPackage.NODE__OUTGOING_CONNECTIONS:
            refreshSourceConnections();
            
    break;
        }
    }

    還有active()/deactive()方法中的內容需要修改,作用還是把EditPart自己作為Adapter(不是PropertyChangeListener了)加入模型的監聽器列表,下面是SubjectPart的實現,其中eAdapters()得到監聽器列表:

    public void activate() {
        super.activate();
        ((Subject)getModel().eAdapters()).add(
    this);
    }

    可以看到,我們對EditPart所做的修改實際是在兩種消息機制之間的轉換,如果你對以前的那套機制很熟悉的話,這里理解起來不應該有任何困難。

    ElementFactory的修改

    這個類的作用是根據template創建新的模型對象實例,以前的實現都是"new XXX()"這樣,用了EMF以后應改為"ModelFactory.eINSTANCE.createXXX()",EMF里的每個模型對象實例都應該是使用工廠創建的。

    public Object getNewObject() {
        
    if (template.equals(Diagram.class))
            
    return ModelFactory.eINSTANCE.createDiagram();
        
    else if (template.equals(Subject.class))
            
    return ModelFactory.eINSTANCE.createSubject();
        
    else if (template.equals(Attribute.class))
            
    return ModelFactory.eINSTANCE.createAttribute();
        
    else if (template.equals(Connection.class))
            
    return ModelFactory.eINSTANCE.createConnection();
        
    return null;
    }

    使用自定義CreationFactory代替SimpleFactory

    在原先的PaletteFactory里定義CreationEntry時都是指定SimpleFactory作為工廠,這個類是使用Class.newInstance()創建新的對象實例,而用EMF作為模型后,創建實例的工作應該交給ModelFactory來完成,所以必須定義自己的CreationFactory。(注意,示例代碼里沒有包含這個修改。)

    處理自定義數據類型

    我們的Node類里有兩個非標準數據類型:Point和Dimension,要讓EMF能夠正確的將它們保存,必須提供序列化和反序列化它們的方法。在EMF為我們生成的代碼里,找到ModelFactoryImpl類,這里有形如convertXXXToString()和createXXXFromString()的幾個方法,分別用來序列化和反序列化這種外部數據類型。我們要把它的缺省實現改為自己的方式,下面是我對Point的實現方式:

    public String convertPointToString(EDataType eDataType, Object instanceValue) {
        Point p 
    = (Point) instanceValue;
        
    return p.x + "," + p.y;
    }
    public Point createPointFromString(EDataType eDataType, String initialValue) {
        Point p 
    = new Point();
        String[] values 
    = initialValue.split(",");
        p.x 
    = Integer.parseInt(values[0]);
        p.y 
    = Integer.parseInt(values[1]);
        
    return p;
    }

    注意,修改后要將方法前面的@generated注釋刪除,這樣在重新生成代碼時才不會被覆蓋掉。要設置使用這些類型的變量的缺省值會有點問題(例如設置Node類的location屬性的缺省值),在EMF自帶的Sample Ecore Model Editor里設置它的defaultValueLiteral為"100,100"(這是我們通過convertPointToString()方法定義的序列化形式)會報一個錯,但不管它就可以了,在生成的代碼里會得到這個缺省值。

    保存和載入模型

    EMF通過Resource管理模型數據,幾個Resource放在一起稱為ResourceSet。前面說過,要想正常保存模型,必須保證每個模型對象都被包含在Resource里,當然間接包含也是可以的。比如例子這個模型,Diagram是被包含在Resource里的(創建新Diagram時即被加入),而Diagram包含Subject,Subject包含Attribute,所以它們都在Resource里。在圖1中可以看到,Diagram和Connection之間存在一對多的包含關系,這個關系的主要作用就是確保在保存模型時不會出現DanglingHREFException,因為如果沒有這個包含關系,則Connection對象不會被包含在任何Resource里。

    在刪除一個對象的時候,一定要保證它不再包含在Resource里,否則保存后的文件中會出現很多空元素。比較容易犯錯的地方是對Connection的處理,在刪除連接的時候,只是從源節點和目標節點里刪除對這個連接的引用是不夠的,因為這樣只是在界面上消除了兩個節點間的連接線,而這個連接對象還是包含在Diagram里的,所以還要調用從Diagram對象里刪除它才對,DeleteConnectionCommand中的代碼如下:

    public void execute() {
        source.getOutgoingConnections().remove(connection);
        target.getIncomingConnections().remove(connection);
        connection.getDiagram().getConnections().remove(connection);
    }

    當然,新建連接時也不要忘記將連接添加在Diagram對象里(代碼見CreateConnectionCommand)。保存和載入模型的代碼請看SubjectEditor的init()方法和doSave()方法,都是很標準的EMF訪問資源的方法,以下是載入的代碼(如果是新創建的文件,則在Resource中新建Diagram對象):

    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        super.init(site, input);
        IFile file 
    = ((FileEditorInput) getEditorInput()).getFile();
        URI fileURI 
    = URI.createPlatformResourceURI(file.getFullPath().toString());
        resource 
    = new XMLResourceImpl(fileURI);
        
    try {
            resource.load(
    null);
            diagram 
    = (Diagram) resource.getContents().get(0);
        } 
    catch (IOException e) {
            diagram 
    = ModelFactory.eINSTANCE.createDiagram();
            resource.getContents().add(diagram);
        }
    }

    雖然到目前為止我還沒有機會體會EMF在模型交互引用方面的優勢,但經過進一步的了解和在這個例子的應用,我對EMF的印象已有所改觀。據我目前所知,使用EMF模型作為GEF的模型部分至少有以下幾個好處:

    1. 只需要定義一次模型,而不是類圖、設計文檔、Java代碼等等好幾處;
    2. EMF為模型提供了完整的消息機制,不用我們手動實現了;
    3. EMF提供了缺省的模型持久化功能(xmi),并且允許修改持久化方式;
    4. EMF的模型便于交叉引用,因為擁有足夠的元信息,等等。

    此外,EMF.Edit框架能夠為模型的編輯提供了很大的幫助,由于我現在對它還不熟悉,所以例子里也沒有用到,今后我會修改這個例子以利用EMF.Edit。

    posted on 2005-04-15 18:13 八進制 閱讀(2262) 評論(9)  編輯 收藏 收藏至365Key 所屬分類: Eclipse

    評論

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-04-18 16:49 tinachen
    請問:“EMF提供了缺省的模型持久化功能(xmi),并且允許修改持久化方式”持久化功能有什么用呀?
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-04-19 11:12 八進制
    就是把模型從內存保存到硬盤等持久化媒體上的功能,比如存為文件或者存到數據庫。如果沒有持久化功能,你編輯的模型在退出程序以后就丟失了。
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-05-18 12:57 blunwen
    例子中emf構造的模型一定要繼承一個包含位置和大小信息的Node類嗎?如果單純的用emf構造一個模型而不含有任何的除模型外的信息,但是又想使用gef來畫模型的圖,應該怎么入手好呢?
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-05-18 14:39 八進制
    目前我是通過繼承的方式把大小位置信息放在父類里。
    因為保存下來的本地文件里必須包含這些信息(否則不可能復原),所以嚴格來說它們也是模型的一部分。
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-05-22 14:32 blunwen
    有一個辦法可以使模型是模型。既模型不需要繼承具有大小位置信息的Node類,而是在Node類里面有一個指向模型的屬性。在save的時候,把Node類對應的模型保存在另外一個文件就ok了。這一點經過實現證明是可行的
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-06-06 21:12 whatisnew
    blunwen真是無所不在呀,哈哈哈
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-07-08 23:36 小小笨鳥
    我想從xsd出發,構造EMF模型。可是導入XML schema時,總是出這樣的錯:

    * a null pointer exception, or
    * the error message "Specify a valid XML Schema and try loading again".

    eclipse的站點上說,這是個bug,

    "To avoid this, use the following to control the JAXP implementation:

    <eclipse-install-dir>eclipse.exe -vmargs
    -Djava.endorsed.dirs=<path-to-your-xerces-jars-folder>"

    我不明白這樣的解釋。我下載了xerces 2.7.0,可是不明白怎樣用。有誰可以幫我嗎?還有有必要做xerces integrity verification嗎?md5,pgp又是怎樣用的呢?

    郁悶中。。。:(

    急切期待回音!謝過各位大俠了先。 :)
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-07-09 11:20 八進制
    可能是啟動eclipse時要用“eclipse.exe -vmargs -Djava.endorsed.dirs=<你下載的xerces所在目錄>”,也就是加一個參數讓eclipse使用你下載的新的xerces。
      

    # re: [Eclipse]GEF入門系列(八、使用EMF構造GEF的模型) 2005-07-11 17:08 小小笨鳥
    呵呵,bingle!找到了,原來只是引號的問題。我也一直在想它只是一條命令,可是怎樣試都不行,差點就絕望了。ouf!終于解決了,好開心!多謝八進制l了! :)
      
    posted on 2005-08-26 17:13 sharky的點滴積累 閱讀(1082) 評論(1)  編輯  收藏

    評論

    # re: GEF入門系列(八、使用EMF構造GEF的模型) 2016-05-02 19:19 正正糖糖
    如何設置point這種類型的默認值,在哪里設置  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产精品亚洲专区无码WEB| 亚洲精品无码少妇30P| 久久九九久精品国产免费直播| 久久国产精品免费| 国产免费牲交视频| 亚洲av日韩av不卡在线观看| 亚洲成av人片在线看片| 黄人成a动漫片免费网站| 亚在线观看免费视频入口| 国产亚洲成av人片在线观看| 免费高清国产视频| 国产精品色午夜免费视频| 亚洲视频免费在线看| 久久九九兔免费精品6| 亚洲成a人片在线观看播放| 国产成人无码免费看视频软件| va天堂va亚洲va影视中文字幕| 国产在线精品一区免费香蕉| 好爽又高潮了毛片免费下载| 亚洲精品宾馆在线精品酒店 | 久久亚洲精品高潮综合色a片| 日韩免费一区二区三区| 四虎影视永久在线精品免费| 久久天天躁狠狠躁夜夜免费观看| 亚洲依依成人亚洲社区| 小日子的在线观看免费| 亚洲制服丝袜精品久久| 97精品免费视频| 国产亚洲婷婷香蕉久久精品| 99久久99久久免费精品小说| 亚洲色偷偷色噜噜狠狠99网| 免费一级黄色毛片| 亚洲风情亚Aⅴ在线发布| 亚洲国产精品嫩草影院久久 | 亚洲av无码不卡| 我要看免费的毛片| 亚洲六月丁香六月婷婷色伊人| 麻豆国产入口在线观看免费 | 美女扒开屁股让男人桶爽免费| 在线日韩日本国产亚洲| 免费人妻精品一区二区三区|