八进制

少年壮志无烟抽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  230 随笔 :: 0 文章 :: 2943 评论 :: 11 Trackbacks

一旦熟练使用EMF后,有新项目我总是习惯于先使用工具构造出数据模型,然后让EMF帮我生成java代码。当模型需要修改时,也是用工具修改模型本身,然后让EMF把改动更新到java代码,从而保证模型与代码的同步。最近的一个基于struts的Web项目里我试验了脱离Eclipse运行环境使用EMF,发现比想象中的要更容易,以下是一些经验总结。

1. EMF可以脱离Eclipse环境使用,所以不论你要做的项目是纯swt应用程序、swing应用程序、基于web的应用程序甚至没有GUI的应用程序,这些非Eclipse插件的项目也都可以利用EMF生成的模型代码。不过EMF生成的.edit和.editor部分就难以利用了,因为.edit主要为jface的各种viewer提供支持,.editor则是基于Eclipse的一个编辑器。

2. 要脱离Eclipse独立使用EMF生成的代码,需要在项目里包含EMF的运行库,可以在EMF下载页面找到这个名为Standalone的下载项,下载以后要让里面的.jar文件都包含在项目classpath里。

3. 除添加这些库文件以外,还有少量初始化工作需要在你的应用程序启动时执行。在EMF-FAQ页面专门介绍了初始化的方法,基本上要做的就是在程序启动时执行下面两条命令:

XXXPackage xxxPackage = XXXPackage.eINSTANCE;
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
"xxx"new XMIResourceFactoryImpl());

4. 用EMF生成模型代码的步骤和平时基本没有区别,仍然是".ecore->.genmodel->java代码"。一般来说,直接在这个EMF项目里以EMF生成的java代码为基础继续开发就可以了,如果你用其他IDE则可以把这些java代码复制过去使用,只是注意一下每次修改ecore后要重复这个生成和复制代码的过程。

5. 关于多个模型和跨模型引用的处理。EMF的一个好处是可以把整个项目的模型保存为多个文件,并且允许文件之间的相互依赖。例如一个在线商店系统里,在设计的时候可以把模型分为用户信息、商品信息和订单信息三大部分,显然订单信息依赖用户和商品信息,所以对用户和商品的管理可以独立进行开发,一方面提高了模块化程度,也增加了重用的可能性,例如在另外一个项目里可以只做很小的修改甚至不做修改的重用用户管理部分或是商品管理部分。

EMF是通过ResourceSet处理多个模型之间的引用的,以上面的在线商店为例,当从一个文件(一般是xmi格式)里载入一个订单实例时,EMF并不会去实际读取存储用户或商品信息的文件,而是使用代理(Proxy)的方式生成一个替代品,当程序里需要得到订单对应的用户的详细信息时(例如执行了theOrder.getCustomer().getAddress()方法),才会实际读取用户信息文件,并根据订单的用户id找到对应的用户信息。

因此,当你的项目里有多个模型并且存在相互引用的这种情况时,建议维护一个全局的ResourceSet实例,可以在程序启动时创建:

ResourceSet resourceSet = new ResourceSetImpl();

对于普通应用程序,可以用单例模式(Singleton)维护ResourceSet实例;若在web应用程序里,也可以利用application维护它。在程序里,每载入一个模型都要把它加到这个ResourceSet实例上。具体方法如下:

//get global ResourceSet instance
ResourceSet resourceSet = ;
//file to load
String filename = ;//e.g. "c:\\work\\test.xxx"
URI fileURI = URI.createFileURI(filename);
//create resource
XMIResource resource = resourceSet.createResource(fileURI);
//load from file
resource.load(null);
//add resource to global ResourceSet instance
resourceSet.getResources().add(resource);
//get your model
XXXModel xxxModel = (XXXModel) resource.getContents().get(0);

6. 其他常用方法,以下仍以在线商店里的模型(见此帖)为例:

创建一个新产品(Product),通过ShopFacotory的createProduct()方法而不要直接new ProductImpl():

Product p = ShopFactory.eINSTANCE.createProduct();
//
Product p = (Product)ShopFactory.eINSTANCE.create(ShopPackage.Literals.Product);

把新创建的产品添加到商店(Shop):

Shop model = …;
Product p 
= …;
model.getProducts().add(p);

通过EMF反射机制得到Product类型的所有属性(非引用类型),任何一个EObject都可以通过这种方式得到其所有属性:

Product p = …;
EClass eclass 
= p.eClass(); 
for (Iterator iterator = eclass.getEAllAttributes().iterator(); iterator.hasNext();) {
  EAttribute attr 
= (EAttribute)iterator.next(); //属性,如Product#name
  Object value = p.eGet(attr); //属性值,如“walkman”
  … //do whatever with the value
}

通过EMF反射机制得到Category类型的所有引用,任何一个EObject都可以通过这种方式得到其所有引用:

Category category = …;
EClass eclass 
= category.eClass();
for (Iterator iterator = eclass.getEAllReferences().iterator(); iterator.hasNext();) {
  EReference ref 
= (EReference)iterator.next(); //引用,如Category#products
  Object value = category.eGet(ref); //引用值,如EList<Product>(一对多的情况)
  … //do whatever with the value
}

posted on 2007-05-07 14:16 八进制 阅读(3646) 评论(8)  编辑 收藏 所属分类: EclipseEMF

评论

正在学习这个,谢谢
  回复  引用    

十分感谢八进制兄给出这么多好文章。好不容易哦,呵呵
在emf 的 2.2 中好像没有了 《EMF介绍系列(五、定制应用程序界面)》所说的问题了。
但是,就是奇怪,为什么你选择一个对象的时候都是获取到的都是这个选取对象的子对象的信息?也就是说你选取"Category电子"对象时,tableviewer 出现的却是它对应的两子对象(Category相机和Category随身听)的信息?而不是"Category电子"自己的信息?
  回复  引用    

不知八进制兄有没有关于emf的query和ocl项目的文章可以分享一些呢?
  回复  引用    

#4楼 [楼主] 2007-06-07 16:52 八进制      
这篇和ocl有一点点相关,http://www.cnblogs.com/bjzhanghao/archive/2006/08/09/472607.html,query的部分没实际用过,query部分的eclipse帮助可以看看。
  回复  引用  查看    

#5楼 [楼主] 2007-06-07 16:54 八进制      
因为adapterfactorycontentprovider是这样实现的。
  回复  引用  查看    

最近学习EMF-Query和EMF-OCL,在学习过程中用博客记录,使用了八进制兄的模型,作为八兄EMF系列的扩展吧。希望八兄不要介意。希望多交流 :)
八兄能建个链接不?
  回复  引用    

还是没明白用EMF有什么好处,这个web应用不用数据库吗,怎么和hibernate集成呢?
  回复  引用    

#8楼 [楼主] 2007-12-04 16:47 八进制      
如果数据量不大是可以不用数据库,省去部署时很多麻烦。
如果需要用数据库,TENEO可以把EMF对象保存到数据库(通过JDO或Hibernate),连Mapping文件都不需要写,TENEO会自动生成。
EMF的最大好处是时刻保持类图与Java代码同步,同时提供了额外的好处如XMI序列化,监听机制(MVC必须),多Resource关联等等。
  回复  引用  查看