隨筆-62  評論-29  文章-0  trackbacks-0

          用 Eclipse Modeling Framework 實(shí)現(xiàn)模型驅(qū)動開發(fā),第 1 部分

          創(chuàng)建 UML 模型并生成代碼

          developerWorks
          文檔選項(xiàng)
          將打印機(jī)的版面設(shè)置成橫向打印模式

          打印本頁

          將此頁作為電子郵件發(fā)送

          將此頁作為電子郵件發(fā)送

          未顯示需要 JavaScript 的文檔選項(xiàng)


          級別: 初級

          Adrian Powell, Advisory I/T Specialist, IBM

          2004 年 4 月 01 日

          Eclipse Modeling Framework(EMF)是一個開放源代碼的模型驅(qū)動應(yīng)用程序開發(fā)框架。它可以基于 XML Schema、UML 或經(jīng)過注釋的 Java 中指定的模型,創(chuàng)建 Java 代碼,實(shí)現(xiàn)圖形化的數(shù)據(jù)編輯、操縱、讀取和序列化。EMF 是 IBM WebSphere Studio 和 Eclipse 項(xiàng)目中很多工具的基礎(chǔ)。本文將幫助您逐步了解創(chuàng)建模型、生成代碼、使用生成的應(yīng)用程序和定制編輯器的整個過程。

          EMF 究竟是什么?


          Eclipse Modeling Framework(EMF)是一個開放源代碼的框架,它的目標(biāo)是實(shí)現(xiàn)模型驅(qū)動架構(gòu)(Model-Driven Architecture)的開發(fā)。如果我們當(dāng)中的少數(shù)人有幸得到了某個 UML 模型,那么這個框架就可以幫助我們將文檔變成代碼。至于其他人,這個工具也使您又有一次機(jī)會向老板證實(shí),把時間花在為解決方案建模上是值得的。除了可以生成令人贊嘆的 Java 代碼之外,EMF 還可以生成 Eclipse 插件,以及圖形化的可定制編輯器。當(dāng)您改變模型時(這種情況真的會出現(xiàn)),EMF 可以通過單擊一個按鈕,就使代碼和模型保持同步。

          EMF 生成的代碼也不是一種只配丟進(jìn)垃圾箱的解決方案。這種代碼支持標(biāo)準(zhǔn)的創(chuàng)建、獲取、更新和刪除操作,而且還支持元數(shù)約束、復(fù)雜關(guān)系和繼承結(jié)構(gòu)、屏蔽定義,以及一套屬性描述。生成的代碼還提供通知、參照完整性和可定制的 XMI 持久性。您所需要做的全部工作就是創(chuàng)建一個對象模型,就像您以前也想做的那樣。

          EMF 是比較新的事物,但前景廣闊,對它持續(xù)支持的力度也很強(qiáng)。它實(shí)現(xiàn)的是一項(xiàng)公共標(biāo)準(zhǔn),即對象管理組織(Object Management Group)的元對象工具(Meta-Object Facility,MOF)。現(xiàn)在 EMF 已經(jīng)對 MOF 的第二版進(jìn)行了增強(qiáng)。更進(jìn)一步看,EMF 還是 EMF:XSD 以及 Hyades 等 Eclipse 項(xiàng)目的基礎(chǔ),大多數(shù) IBM WebSphere Studio 產(chǎn)品也都使用它。EMF 第二版的開發(fā)已經(jīng)開始,開發(fā)構(gòu)建應(yīng)該很快就會出爐。第二版開發(fā)計(jì)劃中包括更好的 XML Schema 支持、更靈活的代碼生成方式以及模型之間的映射機(jī)制。





          回頁首


          讓工具自己說話


          商業(yè)宣傳已經(jīng)說得夠多了。現(xiàn)在讓我們直接進(jìn)入代碼中,看看 EMF 到底能做些什么。下面的例子都是用 Eclipse 3.0M7 和 EMF 2.0.0,再加上與之匹配的 XSD 工具箱實(shí)現(xiàn)的。現(xiàn)在有四種獨(dú)立的 EMF 開發(fā)流程,每一種都適用于不同版本的 Eclipse,所以一定要保證根據(jù)您的 Eclipse 版本選擇了正確的 EMF 版本(請參閱 參考資料中的鏈接,獲取這些插件)。

          我們將以一個簡單的 Web 論壇為例,向您展示最重要的特性。模型的根為 Forum ,下面包括一組 MemberTopic 。每一個 Topic 都具有一個 TopicCategory (枚舉類型), MemberTopic 通過 Post 類間接相關(guān)聯(lián),這兩者之間也存在直接關(guān)聯(lián),因?yàn)?Member 可以創(chuàng)建 Topic

          用 UML 和 Omondo 創(chuàng)建 EMF 模型


          Omondo 的 UML 插件是在 Eclipse 中創(chuàng)建 UML 文檔的方便可靠的工具。它看起來就像是 Rational Rose 受冷落的小兄弟,但除非是您需要特別強(qiáng)大的功能,否則用它就可以工作得很好了。不過,該工具尚不支持 Eclipse 3,所以我采用 Eclipse 2.1 來創(chuàng)建 UML 類圖。

          一開始,我們創(chuàng)建一個新的 Java 項(xiàng)目 UMLForum,以及一個新包 com.ibm.example.forum 。再創(chuàng)建一個新的 EMF 類圖, forum.ucd ,存放在 src/com/ibm/example/forum 下。目錄中創(chuàng)建了兩個文件,forum.ecd 和 forum.ecore。向類圖中增加一個新類,名為 Forum ,然后單擊 Finished。向 Forum 類中增加一條屬性描述,類型為 EString (對于所有的簡單 Java 類都有相應(yīng)的 Ecore 類),如圖 1 所示。對于屬性的特性,只選擇 changeable ,并將范圍設(shè)為從 0 到 1。

          如果您過一會改主意了,想使用其他的特性,可以打開 Properties 視圖,選擇其中的類或?qū)傩浴?/p>
          圖 1. 新建的 Forum 類及其屬性的性質(zhì)
          新建的 Forum 類及其屬性的性質(zhì)

          對于下列接口重復(fù)上述步驟:

          接口 屬性 類型
          Member nickname EString
          Topic title EString
          Post comment EString

          為定義關(guān)聯(lián),我們可以選中關(guān)聯(lián)按鈕,然后單擊關(guān)聯(lián)的源( Forum )和目標(biāo)( Member )。這樣將打開關(guān)聯(lián)屬性設(shè)置對話框。在其中將名字設(shè)置為 members ,確保僅僅選擇了 changeable 和 containment,然后將上限設(shè)為 -1。在第二個 Association End 選項(xiàng)卡中,取消選中的 Navigable,然后單擊 Ok。對 ForumTopic 也執(zhí)行相同的操作,屬性名稱從 members 改為 topics 。取消選中的 navigable,從而創(chuàng)建一個無方向的關(guān)聯(lián),但我們想讓其他屬性都保持為雙向。

          按照下表所示完成關(guān)聯(lián)設(shè)置:

          目標(biāo) 關(guān)聯(lián) 名稱 特性 范圍
          Member Topic 1st Association topicsCreated changeable 0 到 1
          2nd Association creator changeable 0 到 1
          Topic Post 1st Association posts Containment, changeable 0 到 -1
          2nd Association topic changeable 0 到 1
          Member Post 1st Association posts changeable 0 到 -1
          2nd Association author changeable 0 到 1

          最后,我們要定義一個枚舉類型,用于表示 topic 有多少不同的類型。創(chuàng)建一個新的枚舉類型,名字叫做 TopicCategory 。Literal 中加入以下的內(nèi)容:

          • ANNOUNCEMENT , value = 0
          • GUEST_BOOK , value = 1
          • DISCUSSION , value = 2

          然后,為 Topic 定義一個新屬性,叫做 category ,類型為 TopicCategory ,changeable,范圍 0-1。如果您愿意的話,可以在屬性標(biāo)簽上對默認(rèn)值進(jìn)行修改,但我們將接受 ANNOUNCEMENT 的默認(rèn)值。


          圖 2. 完成后的 UML 類模型
          完成后的 UML 類模型

          一旦您完成了圖 2 所示的 UML 類圖,下一步就是創(chuàng)建一個 EMF 模型。為此,需要先創(chuàng)建一個新的 EMF 項(xiàng)目( File > New > Project... > Eclipse Modeling Framework > EMF Project),并用 com.ibm.example.forum 作為該項(xiàng)目的名稱(這是插件名稱的基礎(chǔ),因此我們遵從 Eclipse 插件的命名規(guī)范)。在下一個頁面上,選擇 Load from an EMF core model,然后單擊 Next。從文件系統(tǒng)中加載 ecore 文件,它將自動填充 Generator 的模型名。在最后一個頁面上,單擊包旁邊的復(fù)選框,然后單擊 Finish。這樣就創(chuàng)建好了 EMF 模型,它的名字叫做 forum.genmodel。您可以從 使用生成的 EMF 模型一節(jié)中了解到這個模型是什么,以及如何使用它。

          用 XML Schema

          創(chuàng)建 EMF 模型
          XML Schema(XSD)的表現(xiàn)能力不如 UML 或帶注釋的 Java 代碼那么強(qiáng)大,例如,它不能表達(dá)出雙向引用的關(guān)聯(lián)。但是由于默認(rèn)的的序列化方法要使用到您的方案,因此 XSD 對定制序列化來說是最快的方法。如果您希望為模型生成非常詳細(xì)的 XML/XMI,那么 XSD 就是必然的選擇。

          清單 1. forum.xsd 的片段
          <xsd:simpleType name="TopicCategory">
                                  <xsd:restriction base="xsd:NCName">
                                  <xsd:enumeration value="Announcement"/>
                                  <xsd:enumeration value="GuestBook"/>
                                  <xsd:enumeration value="Discussion"/>
                                  </xsd:restriction>
                                  </xsd:simpleType>
                                  <xsd:complexType name="Post">
                                  <xsd:sequence>
                                  <xsd:element name="comment" type="xsd:string"/>
                                  <xsd:element name="author" type="xsd:anyURI" ecore:reference="forum:Member"/>
                                  <xsd:element name="topic" type="xsd:anyURI" ecore:reference="forum:Topic"/>
                                  </xsd:sequence>
                                  </xsd:complexType>
                                  

          在清單 1 中,您可以看到枚舉是如何表示的,也能從中了解到如何定義一個具有指向其他類型的元素和引用的類型。在 Forum 這個例子中,我們僅僅使用了字符串屬性 "xsd:string" ,但是其他簡單 Java 類型也是支持的。有關(guān) XML Schema 和 forum.xsd 文件的更多信息,請參閱 參考資料

          一旦完成了 XSD,下一步就是創(chuàng)建 EMF 模型。方法與 UML 模型中類似,先創(chuàng)建一個新的 EMF 項(xiàng)目( File > New > Project... > Eclipse Modeling Framework > EMF Project),項(xiàng)目名稱為 com.ibm.example.forum(這是插件名稱的基礎(chǔ),因此我們遵從 Eclipse 插件的命名規(guī)范)。在下一個頁面上選擇 Load from an XML Schema,然后單擊 Next。在文件系統(tǒng)中找出 XSD 文件并加載,然后 Generator 中的模型名就會自動填充。在最后一個頁面上,單擊包旁邊的復(fù)選框,然后單擊 Finish。這樣就創(chuàng)建了一個 EMF 模型,名字叫做 forum.genmodel。 您可以從 使用生成的 EMF 模型一節(jié)中了解到這個模型是什么,以及如何使用它。

          用帶注釋的 Java 代碼創(chuàng)建 EMF 模型


          如果通過 Java 代碼定義 EMF 模型,我們可以用 Interface 列出每一個類的屬性,以及類之間的關(guān)系。這樣得到的內(nèi)容并不充足,無法定義我們想要的全部信息,所以 EMF 使用了特殊的 JavaDoc 標(biāo)簽。每一個屬性或類,如果是 EMF 模型的一部分,就必須在其 JavaDoc 中包含一個 @model 標(biāo)簽,也可以包含一個附加屬性列表。比如說,如果要構(gòu)造如上面圖 2 所示的一個對象模型,我們對 Forum 的定義看起來應(yīng)該像清單 2 的樣子。

          清單 2. 帶注釋的 Forum.java
          package com.ibm.example.forum;
                                  import java.util.List;
                                  /**
                                  *
                                  @model
                                  */
                                  public interface Forum {
                                  /**
                                  *
                                  @model type="Topic" containment="true"
                                  */
                                  List getTopics();
                                  /**
                                  *
                                  @model type="Member" containment="true"
                                  */
                                  List getMembers();
                                  /**
                                  *
                                  @model
                                  */
                                  String getDescription();
                                  }
                                  

          清單 2 聲明了一個叫做 Forum 的對象,它具有一條 String 類型的描述信息和兩個孩子,一個是 Topic 列表,還有一個是 Member 列表。這兩個孩子都包含在 Forum 之內(nèi)。

          對于簡單的屬性,如 描述信息@model 標(biāo)簽就足夠了,但對于 list 而言,您也需要為其指明類型。 containment 屬性是可選的,但是如果某個對象是被包含的,那么它就和其容器一起被序列化。為了簡化序列化的過程,我們要保證所有的對象都是直接或者間接包含在 Forum 中的。其他一些有用的可選屬性如下:

          • opposite (用于雙向?qū)傩裕?
          • default (屬性的默認(rèn)值)。
          • transient (該屬性不能被序列化)。

          要獲得完整的屬性列表,請您參閱 參考資料中的 EMF user's guide。

          惟一需要當(dāng)心的是枚舉類型。它被定義成一個 Class,而不是其他模型類中的 Interface! 為了明確這一點(diǎn),清單 3 展示了 TopicCategory 枚舉類型是如何實(shí)現(xiàn)的。

          清單 3. 枚舉類型 TopicCategory.java
          package com.ibm.example.forum;
                                  /**
                                  * @model
                                  */
                                  public
                                  class TopicCategory{
                                  /**
                                  * @model name="Announcement"
                                  */
                                  public static final int ANNOUNCEMENT = 0;
                                  /**
                                  * @model name="GuestBook"
                                  */
                                  public static final int GUEST_BOOK = 1;
                                  /**
                                  * @model name="Discussion"
                                  */
                                  public static final int DISCUSSION = 2;
                                  }
                                  

          最后,生成如下所示的三個接口,模型就完成了:

          接口 方法 模型標(biāo)簽
          Member List getPosts() type="Post" opposite="author"
          List getTopicsCreated() type="Topic" opposite="creator"
          String getName()
          Topic List getPosts() type="Post" opposite="author"
          Member getCreator() opposite="topicsCreated"
          String getTitle()
          TopicCategory getCategory()
          Post Member getAuthor opposite="posts"
          Topic getTopic() opposite="posts"
          String getComment()

          模型定義完成之時,可以生成 EMF 模型( File > New > Other > Eclipse Modeling Framework > EMF Models)。將父目錄設(shè)為 com.ibm.example.forum/src/model, File name設(shè)為 forum.genmodel。在下一個頁面上,選擇 Load from annotated Java,然后選中包“forum”旁邊的復(fù)選框。然后單擊 Finish。這樣就創(chuàng)建了一個名為 forum.genmodel 的 EMF 模型。





          回頁首


          使用生成的 EMF 模型


          現(xiàn)在您的工作空間中應(yīng)該有一個生成好的 EMF 模型 forum.genmodel。這個模型中包含您輸入其中的所有信息。用默認(rèn)的編輯器打開這個模型(參見圖 3),再打開 Properties 視圖,然后檢查模型樹中每一個節(jié)點(diǎn)的屬性。前面輸入的所有屬性都可以定制,但是也有一些用于定制代碼生成的屬性。為了驗(yàn)證這一點(diǎn),讓我們試著修改“Copyright Text”或“Generate Schema”之類的屬性,看看會發(fā)生什么事情。


          圖 3. 在默認(rèn)的編輯器中打開生成的 EMF 模型
          帶有生成的 EMF 模型的 Eclipse 屏幕快照

          如果對模型描述(UML、XSD、帶注釋的 Java)進(jìn)行了修改,也可以在 Package Explorer 中用右鍵單擊該模型,然后選擇 Reload,這樣就能夠重新加載模型。這實(shí)現(xiàn)了用 EMF 生成的模型與模型描述之間的同步。重新加載后將會改變您在生成的模型中修改過的屬性。





          回頁首


          生成 Java 代碼

          如果您對模型描述感到滿意,或者如果您僅僅是想看看所有這一切到底是什么意思,那么現(xiàn)在就可以生成代碼了。在根節(jié)點(diǎn)上單擊鼠標(biāo)右鍵,選擇其中一個生成選項(xiàng):Model、Edit、或 Editor code。 Generate Model將在當(dāng)前項(xiàng)目中創(chuàng)建該 EMF 模型的 Java 實(shí)現(xiàn)代碼。其中會包含下列內(nèi)容:

          • com.ibm.example.forum -- 創(chuàng)建該 Java 類的接口和工廠。
          • com.ibm.example.forum.impl -- com.ibm.example.forum 中定義的接口的具體實(shí)現(xiàn)。
          • com.ibm.example.forum.util -- AdapterFactory。

          Generate Editor Code將創(chuàng)建 com.ibm.example.forum.edit 項(xiàng)目。其中僅僅包含一個包, com.ibm.example.forum.provider ,用于控制每一個模型對象出現(xiàn)在編輯器中的方式。 Generate Editor Code將在 com.ibm.example.forum.editor 項(xiàng)目中創(chuàng)建一個插件編輯器示例,其中包含了 com.ibm.example.forum.presentation。這些類提供了一系列簡單的 JFace 編輯器,可以與您的模型進(jìn)行交互。

          為了測試生成的插件,請依次進(jìn)入 Run > Run... > Run Time Workbench > New。輸入一個描述性的名稱,然后在 plug-ins 選項(xiàng)卡中,選擇 launch with all workspace and enabled external plug-ins。再在 Common 頁下,單擊 Display in favorites menu > RunLaunch in background。最后保存設(shè)置并運(yùn)行。

          這時將出現(xiàn)一個新的 Eclipse 工作臺,您可以在 Help > About Eclipse Platform > Plug-in Details下面驗(yàn)證您的插件是否可用,如圖 4 所示。


          圖 4. Forum 的插件詳細(xì)信息
          自定義插件列表的 Eclipse 屏幕快照

          為了測試生成的插件,您可以創(chuàng)建一個新的 Simple 項(xiàng)目,名為“Forum Demo”,然后依次進(jìn)入 New > Other... > Example EMF Model Creation Wizards > Forum Model。給文件取名叫做 sample.forum,然后選擇 Forum 作為 Model Object。這時會打開一個窗口,您可以在這里向根中增加新的模型元素。其中包含幾種視圖:Selection、Parent、List、Tree、Table 和 TreeTable。所有這些視圖都顯示相同的數(shù)據(jù),也和 Outline 視圖保持同步。雖然所有視圖都會在右鍵菜單選項(xiàng)中顯示 New Sibling/New Child,但是我發(fā)現(xiàn),有些視圖在加入兄弟節(jié)點(diǎn)或子節(jié)點(diǎn)時不能正確響應(yīng)。如果您也遇到這種情況,可以使用 TableTree 視圖,或是在 Outline 視圖中創(chuàng)建新的節(jié)點(diǎn)。圖 5 展示了所生成的插件編輯器。


          圖 5. 所生成的插件編輯器
          自定義插件列表的 Eclipse 屏幕快照




          回頁首


          定制生成的代碼


          生成的代碼都很不錯,但是這只是真正應(yīng)用程序的起點(diǎn)。為了滿足我們的需要,我們必須對其進(jìn)行調(diào)整和定制。我們可以改變所生成的模型類的實(shí)現(xiàn),也可以對編輯器進(jìn)行擴(kuò)展和定制。好在 EMF 沒有讓我們失望,我們可以按照自己的想法做任何定制,當(dāng)重新生成代碼時也不會丟掉這些內(nèi)容。我們需要做的全部工作就是刪除 @generated JavaDoc 標(biāo)簽,EMF 的 jmerge 將保證這些方法、屬性或類不被打擾。

          為著重說明您能對代碼進(jìn)行哪些修改,讓我們來看一個簡單的例子。在所生成編輯器的 Table 視圖中,兩個字段都顯示出相同的的值。這一點(diǎn)并不是完全沒有用處。為了改善一下,我們可以修改第二個字段,讓它在選中一個 Topic 的時候顯示 Author,然后增加第三個字段,給出該 Topic 中的帖子數(shù)。

          第一步,向 Table 視圖中額外增加一個字段。這一步在 com.ibm.example.forum.editor 項(xiàng)目中實(shí)現(xiàn),即 createPages() 方法中的 com.ibm.example.forum.presentation.ForumEditor 。把 @generated 標(biāo)簽刪除,這樣就能持久保存我們的修改,然后定位到表瀏覽窗口所在的位置。按照清單 4 的內(nèi)容對這段代碼進(jìn)行修改。

          清單 4. 修改后的 createPages()
          TableColumn selfColumn = new TableColumn(table, SWT.NONE);
                                  layout.addColumnData(new ColumnWeightData(2, 100, true));
                                  selfColumn.setText("Author");
                                  selfColumn.setResizable(true);
                                  TableColumn numberColumn = new TableColumn(table, SWT.NONE);
                                  layout.addColumnData(new ColumnWeightData(4, 100, true));
                                  numberColumn.setText("Number of Posts");
                                  numberColumn.setResizable(true);
                                  tableViewer.setColumnProperties(new String [] {"a", "b", "c"});
                                  

          這樣就額外增加了一個字段,但是現(xiàn)在所有的三個字段都顯示相同的數(shù)據(jù)。為了定制每一個字段中的數(shù)據(jù),我們需要提供一些 ITableItemLabelProvider 的實(shí)現(xiàn)。打開 com.ibm.example.forum.provider.TopicItemProvider ,在實(shí)現(xiàn)列表中加入 ITableItemLabelProvider 。我們需要增加兩個方法, getColumnText(Object, int)getColumnImage(Object, int) ,如清單 5 所示。

          清單 5. 加入 TopicItemProvider
          public String getColumnText(Object obj, int index) {
                                  if( index == 0 ){
                                  return getText(obj);
                                  }
                                  else if( index == 1 ) {
                                  return ((Topic)obj).getCreator().getNickname();
                                  } else if( index == 2 ) {
                                  return " + ((Topic)obj).getPosts().size();
                                  }
                                  return "unknown";
                                  }
                                  public Object getColumnImage(Object obj, int index) {
                                  return getImage( obj );
                                  }
                                  

          最后,我們需要注冊這個提供程序。實(shí)現(xiàn)方法是編輯 com.ibm.example.forum.provider.ForumItemProviderAdapterFactory 的構(gòu)造函數(shù),向支持的類型中增加 ITableItemLabelProvider ,如清單 6 所示。

          清單 6. ForumItemProviderFactory 構(gòu)造函數(shù)
          public ForumItemProviderAdapterFactory() {
                                  supportedTypes.add(ITableItemLabelProvider.class);
                                  supportedTypes.add(IStructuredItemContentProvider.class);
                                  supportedTypes.add(ITreeItemContentProvider.class);
                                  supportedTypes.add(IItemPropertySource.class);
                                  supportedTypes.add(IEditingDomainItemProvider.class);
                                  supportedTypes.add(IItemLabelProvider.class);
                                  }
                                  

          現(xiàn)在我們再運(yùn)行這個插件,打開表視圖,就能看到圖 6。請注意,沒有實(shí)現(xiàn)的 ITableItemLabelProvider 元素將在所有的字段中顯示相同的文本。


          圖 6. 修改后的 Table 編輯器
          修改后的 Table 編輯器




          回頁首


          在 Java 中操縱模型


          生成的模型代碼看起來就像是 Java 代碼中增加了一些有用的東西。系統(tǒng)還提供了一種靈活的定制反射 API,對工具很有用。您也許注意到了,這就是 eGet()eSet() 兩個方法。在大多數(shù)情況下,我們并不需要關(guān)心它,所以我們還是看看我們感興趣的東西:如何創(chuàng)建、保存和加載模型。讓我們從頭開始:加載 EMF 模型。

          清單 7. 加載 Forum
          // Register the XMI resource factory for the .forummodel extension
                                  Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
                                  Map m = reg.getExtensionToFactoryMap();
                                  m.put("forummodel", new XMIResourceFactoryImpl());
                                  ResourceSet resSet=new ResourceSetImpl();
                                  Resource res = resSet.getResource(URI.createURI("model/forum.forummodel"),true);
                                  Forum forum = (Forum)res.getContents().get(0);
                                  

          清單 7 展示了如何給文件關(guān)聯(lián)一個符合 XMI 格式的擴(kuò)展名“forummodel”,然后用 EMF 的 ResourceSet 解析并加載 forum 模型。我們知道,F(xiàn)orum 是惟一的根元素,所以可以想象, res.getContents().get(0) 將返回一個且僅有一個 Forum 對象。如果情況不是這樣,我們還可以從 getContents().iterator() 中取出一個 Iterator,然后分別檢查每一個元素。

          我們還可以換一種方法,創(chuàng)建一個新的 Forum,然后用程序組裝起來,如清單 8 所示。

          清單 8. 初始化 Forum
          // initialize model and dependencies
                                  ForumPackageImpl.init();
                                  // retrieve the default Forum factory singleton
                                  ForumFactory factory = ForumFactory.eINSTANCE;
                                  Forum forum = factory.createForum();
                                  forum.setDescription("programmatic forum example");
                                  Member adminMember = factory.createMember();
                                  adminMember.setNickname("Administrator");
                                  forum.getMembers().add( adminMember );
                                  Topic noticeTopic = factory.createTopic();
                                  noticeTopic.setTitle("Notices");
                                  noticeTopic.setCategory(TopicCategory.ANNOUNCEMENT_LITERAL);
                                  noticeTopic.setCreator(adminMember);
                                  forum.getTopic().add( noticeTopic );
                                  

          在這個例子中,我們首先初始化包,然后創(chuàng)建 ForumFactory,用它生成所有的子對象。創(chuàng)建完畢之后,就可以像標(biāo)準(zhǔn)的 JavaBean 那樣訪問這些對象。然而,由于我們把 TopicMemeber 之間的 creator/topicsCreated 關(guān)系聲明為雙向,當(dāng)我們調(diào)用 noticeTopic.setCreator(adminMember) 的時候, adminMembertopicsCreated 清單中就包括 noticeTopic

          一旦我們創(chuàng)建并操縱了 EMF 模型,就很容易將其保存為我們選定的格式(參見清單 9)。

          清單 9. 保存 Forum
          URI fileURI = URI.createFileURI("model/forum.ecore");
                                  Resource resource = new XMIResourceFactoryImpl().createResource(fileURI);
                                  resource.getContents().add( forum );
                                  try {
                                  resource.save(Collections.EMPTY_MAP);
                                  } catch (IOException e) {
                                  e.printStackTrace();
                                  }
                                  

          在本例中,我們給 URI.createFileURI() 提供了希望保存成的文件名與目標(biāo)格式。這個例子因?yàn)槭潜4鏋?XMI,所以使用了 XMIResourceFactoryImpl 。一旦創(chuàng)建完畢,所有的模型對象就如我們所愿的持久保存起來了。在這個例子中,除 Forum 之外的每一個對象都被另一個類包含,所以我們只需要對包含所有孩子的 root 增加這條命令即可。如果某些對象沒有 包含 關(guān)系,那么也必須通過 resource.getContents().add() 顯式地將它們加進(jìn)去。否則,當(dāng)您調(diào)用 resource.save() 時就會出現(xiàn)異常。



          posted on 2009-04-13 11:01 閱讀(500) 評論(0)  編輯  收藏

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 定陶县| 磐安县| 舒城县| 黎平县| 临城县| 长丰县| 贵州省| 汶川县| 蒙山县| 临安市| 甘泉县| 江源县| 西昌市| 盐山县| 宣化县| 泰来县| 瑞安市| 南乐县| 越西县| 宁乡县| 永善县| 息烽县| 望江县| 德惠市| 景谷| 苏州市| 龙岩市| 荆门市| 当涂县| 怀来县| 巴中市| 天长市| 独山县| 商丘市| 多伦县| 新化县| 兰州市| 那坡县| 深水埗区| 孟州市| 师宗县|