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

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

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

    Thinking in XiaoQiang
    世人皆有悲哀,只有你不明白
    posts - 56,comments - 150,trackbacks - 0
    如果給定一個(gè)模型,那么EMF能夠自動(dòng)生成Java源代碼-該源碼允許你創(chuàng)建、查詢、更新、串行化、反串行化、檢驗(yàn)和追蹤你的模型實(shí)例的變化。EMF提供了一組有效的反射API并且允許你用動(dòng)態(tài)的(非生成的)模型進(jìn)行工作。

      一、 引言

      Eclipse建模框架(EMF)是一個(gè)Java開源框架與代碼生成工具-用于基于結(jié)構(gòu)化的模型來(lái)構(gòu)建工具和其它應(yīng)用程序。在Eclipse平臺(tái)在用戶界面和文件級(jí)上提供一個(gè)強(qiáng)有力的集成框架的同時(shí),EMF加強(qiáng)了這種能力來(lái)實(shí)現(xiàn)工具和應(yīng)用程序之間良好粒度的數(shù)據(jù)分享。

      類似于其它的Java綁定框架,例如JAXB或XMLBeans,給定一個(gè)模型后,EMF就能夠生成Java源代碼-它允許你創(chuàng)建、查詢、更新、反串行化以及串行化你的模型的實(shí)例。盡管多數(shù)Java綁定框架僅支持一個(gè)模型類,例如XML模式,而EMF支持從XML模式,UML類圖(Rational Rose或UML2)以及被注解的Java接口中生成代碼。除了模型代碼,EMF還能生成一個(gè)完整的應(yīng)用程序-它包括一個(gè)可定制的編輯器。

      EMF生成的代碼有一個(gè)內(nèi)建的改變通知機(jī)制并且支持跨文檔參考。EMF提供一個(gè)反射API以存取你的模型實(shí)例并且允許你動(dòng)態(tài)地創(chuàng)建模型。EMF支持模型約束校驗(yàn)。EMF提供強(qiáng)有力的代碼生成工具來(lái)支持模型的重新生成和使用用戶書寫的代碼進(jìn)行合并。

      在本文中,我們將解釋什么是EMF,并分析其基本框架。

      EMF最開始是一個(gè)對(duì)象管理組的(OMG)元對(duì)象設(shè)備(MOF)說(shuō)明書的實(shí)現(xiàn)-它為面向?qū)ο蟮姆治龊驮O(shè)計(jì)提供一個(gè)標(biāo)準(zhǔn)化的元模型。在很長(zhǎng)一段時(shí)間以來(lái),EMF被用于實(shí)現(xiàn)大量的工具并且因此演變?yōu)橐粋€(gè)有效的MOF API的一個(gè)核心子集的Java實(shí)現(xiàn)。

      在EMF中的類MOF核心元模型(一個(gè)模型的模型)被稱作Ecore。在對(duì)當(dāng)前的MOF 2.0的實(shí)現(xiàn)中,有一個(gè)類似的MOF模型的子集,稱作Essential MOF(EMOF),它現(xiàn)在已經(jīng)被獨(dú)立出來(lái)。在Ecore和EMOF之間主要存在上些小的特別是命名上的區(qū)別,因此EMF能透明地讀和寫串行化的EMOF,從而允許工具間數(shù)據(jù)的標(biāo)準(zhǔn)交換。

      今天EMF已被廣泛應(yīng)用。例如,EMF被用于實(shí)現(xiàn)開源XML模式Infoset模型(XSD),服務(wù)數(shù)據(jù)對(duì)象(SDO),UML2以及Eclipse上的Web工具平臺(tái)(WTP)工程。另外,EMF也被使用在商業(yè)化的產(chǎn)品中,例如Omondo EclipseUML以及IBM Rational和WebSphere產(chǎn)品等。

      二、 Ecore和反射API

      EMF中的一個(gè)關(guān)鍵接口是Eobject,它在概念上等價(jià)于java.lang.Object。所有的建模對(duì)象,無(wú)論是生成的與否,為了提供以下幾個(gè)重要特征,都要實(shí)現(xiàn)這個(gè)接口:

      ·類似Java的Object.getClass(),通過(guò)使用eClass()方法,你能檢索實(shí)例的元數(shù)據(jù),也就是它的Eclass。

      ·在任何EMF建模的對(duì)象上,你都能使用反射API(eGet(),eSet())來(lái)存取它的數(shù)據(jù)。這在概念上等同于Java的java.lang.reflect.Method.invoke()方法,盡管效率更高些。

      ·從任何實(shí)例對(duì)象,你都可以通過(guò)使用eContainer()方法得到它的容器(parent)。

      ·EObject也擴(kuò)展了Notifier,這允許你監(jiān)視對(duì)象的數(shù)據(jù)的所有變化。

      如前面所提及,EMF有它自己的簡(jiǎn)單的元數(shù)據(jù)-稱作Ecore。圖1顯示出Ecore元數(shù)據(jù)的完整的類層次結(jié)構(gòu)圖。在圖1中,你可以看到EPackage包含關(guān)于模型類(EClass)和數(shù)據(jù)類型(EDataType)的信息。EClass描述一個(gè)建模的類,并且指定屬性和參考以描述實(shí)例的數(shù)據(jù)。EAttribute描述簡(jiǎn)單數(shù)據(jù),它由一個(gè)EDataType來(lái)指定。EReference描述一個(gè)類之間的關(guān)聯(lián);它的類型是一個(gè)Eclass。EFactory包含創(chuàng)建模型元素的方法。


    圖1.Ecore類層次結(jié)構(gòu):這個(gè)圖像顯示出Ecore元數(shù)據(jù)完整的類層次。

      為找到更多關(guān)于EMF和Ecore,請(qǐng)讀在線概述或購(gòu)買Eclipse建模框架(EMF)。EMF網(wǎng)站提供了若干文件來(lái)描述怎么使用EMF來(lái)從一個(gè)XML模式或UML圖表生成Java代碼。

      下面我將描述一個(gè)示例,它使用Ecore來(lái)創(chuàng)建一個(gè)簡(jiǎn)單公司模型,然后使用動(dòng)態(tài)的EMF來(lái)創(chuàng)建,串行化和反串行化這個(gè)模型的實(shí)例。如果你想繼續(xù)讀下去并且你已經(jīng)是一個(gè)Eclipse用戶,請(qǐng)下載和安裝EMF 2.1 SDK或任何可用的更新的版本,在EMF下載站點(diǎn)。如果不那樣,你還可以下載獨(dú)立包,它包括EMF jar文件,它沒(méi)有任何對(duì)Eclipse的依賴性并且能被使用于一個(gè)獨(dú)立的應(yīng)用程序。

    三、 使用動(dòng)態(tài)EMF能力

      一般地,如果你在開發(fā)期間創(chuàng)建了模型,那么典型情況下,你最好生成Java代碼,因?yàn)樵谶@種情況中你的應(yīng)用程序會(huì)使用較少的內(nèi)存并且提供更快的數(shù)據(jù)存取(或是使用生成的API或是使用反射API)。盡管生成Java代碼滿足了大多數(shù)應(yīng)用程序的需要,但是情況并不總是如此。你可能需要處理數(shù)據(jù),而不需要使用生成的實(shí)現(xiàn)類。例如,你可能不知道在開發(fā)時(shí)間你將要處理的數(shù)據(jù)的模型,這就使得生成的Java代碼成為一個(gè)可憐的選項(xiàng)。

      動(dòng)態(tài)的(也就是非生成的)類可以在運(yùn)行時(shí)刻用幾種方法來(lái)創(chuàng)建。讓我們先開始使用Ecore API以編程地方式來(lái)創(chuàng)建一個(gè)公司模型。公司模型用于描述一個(gè)公司,它有一個(gè)名稱和部門。每個(gè)部門由一個(gè)數(shù)字來(lái)唯一標(biāo)志出并且它還有雇員,每個(gè)雇員有一個(gè)名稱。在下面的代碼顯示出一個(gè)相應(yīng)于該模型的Ecore元模型。

    EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
    EcorePackage ecorePackage = EcorePackage.eINSTANCE;
    //創(chuàng)建一Company類
    EClass companyClass = ecoreFactory.createEClass();
    companyClass.setName("Company");
    //創(chuàng)建公司名
    EAttribute companyName = ecoreFactory.createEAttribute();
    companyName.setName("name");
    companyName.setEType(ecorePackage.getEString());
    companyClass.getEStructuralFeatures().add(companyName);
    //創(chuàng)建一Employee類
    EClass employeeClass = ecoreFactory.createEClass();
    employeeClass.setName("Employee");
    //在Employee類上添加一個(gè)名字屬性
    EAttribute employeeName = ecoreFactory.createEAttribute();
    employeeName.setName("name");
    employeeName.setEType(ecorePackage.getEString());
    employeeClass.getEStructuralFeatures().add(employeeName);
    //創(chuàng)建一Department類
    EClass departmentClass = ecoreFactory.createEClass();
    departmentClass.setName("Department");
    //添加department標(biāo)志數(shù)字
    EAttribute departmentNumber = ecoreFactory.createEAttribute();
    departmentNumber.setName("number");
    departmentNumber.setEType(ecorePackage.getEInt());
    departmentClass.getEStructuralFeatures().add(departmentNumber);
    //department類能夠包含到一個(gè)或多個(gè)employee的參考
    EReference departmentEmployees = ecoreFactory.createEReference();
    departmentEmployees.setName("employees");
    departmentEmployees.setEType(employeeClass);
    //指定它可能是一個(gè)或多個(gè)employee
    departmentEmployees.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
    departmentEmployees.setContainment(true);
    departmentClass.getEStructuralFeatures().add(departmentEmployees);
    //company能夠包含到一個(gè)或多個(gè)departments的參考
    EReference companyDepartments = ecoreFactory.createEReference();
    companyDepartments.setName("department");
    companyDepartments.setEType(departmentClass);
    companyDepartments.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
    companyDepartments.setContainment(true);
    companyClass.getEStructuralFeatures().add(companyDepartments);
    //創(chuàng)建一個(gè)包-描述company
    EPackage companyPackage = ecoreFactory.createEPackage();
    companyPackage.setName("company");
    companyPackage.setNsPrefix("company");
    companyPackage.setNsURI("http:///com.example.company.ecore");
    companyPackage.getEClassifiers().add(employeeClass);
    companyPackage.getEClassifiers().add(departmentClass);
    companyPackage.getEClassifiers().add(companyClass);
    通過(guò)使用反射API,你能創(chuàng)建并且初始化一個(gè)你的模型的實(shí)例:
    //得到company工廠
    EFactory companyFactory = companyPackage.getEFactoryInstance();
    //使用工廠來(lái)創(chuàng)建company類的實(shí)例并且
    //設(shè)置company名字
    EObject company = companyFactory.create(companyClass);
    company.eSet(companyName, "MyCompany");
    //創(chuàng)建一個(gè)employee類的實(shí)例
    EObject employee = companyFactory.create(employeeClass);
    //使用反射API初始化employee的名字
    employee.eSet(employeeName, "John");
    //創(chuàng)建一個(gè)department類的實(shí)例
    EObject department = companyFactory.create(departmentClass);
    department.eSet(departmentNumber, new Integer(123));
    //添加"John"到department
    ((List)department.eGet(departmentEmployees)).add(employee);
    //添加department到company
    ((List)company.eGet(companyDepartments)).add(department);

    四、 數(shù)據(jù)的串行化和反串行化

      為了串行化你的模型實(shí)例,你需要把一個(gè)你的實(shí)例模型的根對(duì)象放置到一個(gè)資源中。EMForg.eclipse.emf.ecore.resource.Resource接口描述了一個(gè)物理的存儲(chǔ)位置(例如文件或URL)并且提供方法以串行化和裝載數(shù)據(jù)。每一種資源都被存儲(chǔ)在一個(gè)ResourceSet中-它代表了一個(gè)資源集合-這些資源被一起創(chuàng)建和加載并允許在它們當(dāng)中進(jìn)行參考引用。特別地,一個(gè)ResourceSet負(fù)責(zé)跟蹤哪些資源已被裝載并且保證這個(gè)ResourceSet中的資源不會(huì)被重復(fù)裝載。

      因?yàn)镋MF能夠處理多重模型源,例如XML模式,所以指定使用哪些資源來(lái)實(shí)現(xiàn)(反)串行化你的數(shù)據(jù)也是很重要的。通常,當(dāng)你調(diào)用ResourceSet.createResource(URI)方法時(shí),它查詢Resource.Factory.Registry來(lái)查找一個(gè)工廠-該工廠是為該URI而注冊(cè)的并且使用它來(lái)創(chuàng)建一個(gè)適當(dāng)?shù)馁Y源實(shí)現(xiàn)。因此,在你(反)串行化你的數(shù)據(jù)以前,請(qǐng)確保你已注冊(cè)了適當(dāng)?shù)馁Y源工廠實(shí)現(xiàn)。EMF提供若干Resource.Factory實(shí)現(xiàn):

      ·對(duì)于XML數(shù)據(jù),使用org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl。

      ·對(duì)于XMI數(shù)據(jù),使用org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl。

      ·對(duì)于Ecore模型,使用org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl。

      你的工具箱中有了這些EMF資源后,你就能使用下面的代碼來(lái)串行化你的數(shù)據(jù):

    //創(chuàng)建資源集和資源
    ResourceSet resourceSet = new ResourceSetImpl();
    //注冊(cè)XML資源工廠
    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi",
    new XMIResourceFactoryImpl());
    Resource resource = resourceSet.createResource(URI.createFileURI("c:/temp/company.xmi"));
    //添加根對(duì)象到資源
    resource.getContents().add(company);
    //串行化資源-你還能指定串行化
    //選項(xiàng),它定義在org.eclipse.emf.ecore.xmi.XMIResource中
    resource.save(null);
    company.xmi被串行化后的形式如下:
    <?xml version="1.0" encoding="ASCII"?>
    <company:Company xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
    xmlns:company="http:///com.example.company.ecore" name="MyCompany">
    <department number="123">
    <employees name="John"/>
    </department>
    </company:Company>

      在反串行化過(guò)程中,XML數(shù)據(jù)的命名空間URI被用于定位所需要的Ecore包(它用于描述你的實(shí)例文檔的模型)。因此,在你嘗試裝載任何模型以前,請(qǐng)確保你已經(jīng)為你的文檔將要使用的每個(gè)Ecore包注冊(cè)了命名空間URI:

    //在本地資源注冊(cè)表中注冊(cè)包
    resourceSet.getPackageRegistry().put(companyPackage.getNsURI(), companyPackage);
    //加載資源
    resource.load(null);

      注意到局部的和全局的包(EPackage.Registry.INSTANCE)以及資源工廠(Resource.Factory.Registry.INSTANCE)的注冊(cè)差別也是很重要的。全局注冊(cè)是靜態(tài)的,因此任何應(yīng)用程序在JVM生存期都能存取全局注冊(cè)并且可能覆蓋它。為確保你的注冊(cè)不會(huì)覆蓋全局注冊(cè)并且反過(guò)來(lái)也如此,典型地,你最好使用局部資源集合注冊(cè)。

      五、 由XML模式生成動(dòng)態(tài)的Ecore

      如前所提及,如果你的模型是一個(gè)XML模式但是你沒(méi)有選擇生成Java類,那么,你可以通過(guò)使用XSDEcoreBuilder來(lái)動(dòng)態(tài)地創(chuàng)建一個(gè)Ecore模型。這個(gè)示例使用了ipo.xsd:

    XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder();
    ResourceSet resourceSet = new ResourceSetImpl();
    Collection eCorePackages =xsdEcoreBuilder.generate(URI.createFileURI("c:/temp/ipo.xsd"));

      這個(gè)generate方法返回為這個(gè)模式中的每個(gè)URI生成的Ecore包。如果該模式導(dǎo)入了其它命名空間,那么將有多個(gè)Ecore包被返回。每個(gè)包是被注冊(cè)到本地的資源集中-用于實(shí)現(xiàn)模式轉(zhuǎn)換。因此,如果你使用同樣的資源集來(lái)裝載你的實(shí)例XML文檔的話,你就不需要自己注冊(cè)包。

      因?yàn)閄ML模式包括更多概念而不僅僅是Ecore,例如通配符等,所以EMF使用Ecore EAnnotations來(lái)記錄到XML模式的映射。在數(shù)據(jù)(反)串行化期間,EMF需要處理這些注解。為了確保這些注解在(反)串行化期間被加以考慮,你必須使用XMLResource.ExtendedMetaData選項(xiàng):

    HashMap options = new HashMap();
    options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
    //請(qǐng)參考http://www.w3.org/TR/2004/PER-xmlschema-0-20040318/#ipo.xml
    Resource resource = resourceSet.createResource(URI.createFileURI("c:/temp/ipo.xml"));
    resource.load(options);

      EMF 2.1還增加了一項(xiàng)新功能-它允許你在加載一個(gè)包含一個(gè)xsi:schemaLocation或xsi:noNamespaceSchemaLocation屬性的XML文檔時(shí),不斷地把模式轉(zhuǎn)換成Ecore。同時(shí),它也允許你加載一個(gè)沒(méi)有與之相關(guān)聯(lián)的模式的XML文檔。為了使用這一功能,你需要注冊(cè) org.eclipse.emf.ecore.xmi.impl.GenericXMLResourceFactoryImpl:

    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml",new GenericXMLResourceFactoryImpl());

      六、 小結(jié)

      本文向你簡(jiǎn)短介紹了EMF,并解釋了幾個(gè)核心的EMF概念。同時(shí),對(duì)于如何利用模式EMF的動(dòng)態(tài)能力提供了相關(guān)示例。
    posted on 2005-10-19 00:10 小強(qiáng) 閱讀(587) 評(píng)論(0)  編輯  收藏 所屬分類: eclipse plugin

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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产福利视精品永久免费| 免费jjzz在在线播放国产| 亚洲第一成年免费网站| 亚洲偷自拍拍综合网| 亚洲免费视频观看| 美女视频黄频a免费观看| 亚洲av午夜成人片精品网站| 最近中文字幕mv免费高清视频7| 新最免费影视大全在线播放| 亚洲另类春色国产精品| 亚洲国产成人精品久久久国产成人一区二区三区综 | 美女裸身网站免费看免费网站| 色欲色欲天天天www亚洲伊| 九月丁香婷婷亚洲综合色| 毛片a级毛片免费观看品善网| 中文字幕在线视频免费观看| xxx毛茸茸的亚洲| 国产成人精品日本亚洲网站| 尤物永久免费AV无码网站| 久久午夜羞羞影院免费观看| 精品一区二区三区无码免费直播 | 亚洲精品制服丝袜四区| 岛国片在线免费观看| 精品国产一区二区三区免费| 亚洲AV成人一区二区三区观看| 亚洲精选在线观看| 亚洲国产黄在线观看| 成人无遮挡裸免费视频在线观看| AAAAA级少妇高潮大片免费看| 亚洲国产成人无码AV在线影院| 亚洲综合自拍成人| 亚洲美女又黄又爽在线观看| 国产成人精品123区免费视频| 四虎成年永久免费网站| 13小箩利洗澡无码视频网站免费| 最好2018中文免费视频| 亚洲成a人无码亚洲成www牛牛| 亚洲AV无码一区二区三区在线| 亚洲成色999久久网站| 中文字幕亚洲综合久久男男| 国产成人涩涩涩视频在线观看免费|