关于EMF
EMF(全称Eclipse Modeling Framework),是Eclipse组织推出的建模框架。它能够帮助软件开发人员将模型(UML, XSD等)转换成为健壮且功能丰富的Java代码。通过使用EMF,程序员编写的程序能免费的获得一个健壮的模型层,它通常比程序员自己手工编写的模型层更为健壮。事实上,有很多商业产品都使用了 EMF 来作为其模型层。由于 EMF 的广泛使用,Eclipse 组织为其推出了众多的周边模块。
Fixflow中的EMF
Fixflow引擎读写BPMN2.0模型文件都是通过EMF来实现,扩展的"fixflow:"的元素也是通过EMF提供的注入技术实现,Eclipse的流程设计器上也使用EMF去读写模型文件,
除此之外,系统里的各种.xml配置文件都是EMF完成读写,同时还涉及到了脱离Eclipse环境在web中使用EMF。
设计模型
假设我们需要通过EMF读写一个这样格式的XML文件:
1 <bookRepository> 2 <book id="1" name="我的奋斗" author="阿道夫·希特勒"></book> 3 <book id="2" name="闪击英雄" author="海因茨·古德里安"></book> 4 <book id="3" name="失去的胜利" author="冯·埃里希·曼施泰因"></book> 5 </bookRepository>
下面就根据上面XML实例来创建一个EMF模型。(当然EMF支持用一个XSD文件来生成模型,这种方式我们这里先不做介绍)
注意:下面的内容我用的是Eclipse Modeling Tools版本的Eclipse
(1) 创建一个空的EMF项目(并不一定非要是EMF项目)
(2) 项目名称EMFTest
(3) 在model目录下创建一个Diagram模型设计文件
(4) 给这个Diagram模型设计文件所对应的ecore文件起名: book.ecore
创建完成之后会同时生成两个文件,.ecore文件为模型文件,.ecorediag 为模型的设计文件用来图形化设计器EMF模型。
(5) 打开book.ecorediag文件设计模型,这里我们可以修改一下命名空间,EClass 对应到XML的Element,EAttribute对应到XML Element的字段。
(6) 创建两个EClass 分别起名 BookRepository 和 Book ,在Book类的定义中 添加三个 EAttribute id、name、author。
(7) 设置 EAttribute 的属性 ,除了名字,三个 EAttribute 采用相同的设置。
设置为attribute类型
(8)设置两个类之间的关系,添加一个 BookRepository 到 Book 的引用
继续关系设置
这样我们的模型文件设计完毕,下面我们需要来生成java代码。
生成Java代码
要生成java代码光有 .ecore文件和.ecorediag文件还不够,还需要一个.genmodel文件。
(1)创建一个.genmodel 配置文件
(2) 配置.genmodel文件
(3)生成Java模型文件
读写XML文件
模型和java代码创建完毕之后我们来创建测试类,来尝试读写一个XML文件。
创建一个 test.java 带main方法的:
1 import java.io.IOException; 2 import java.util.Collections; 3 import java.util.Map; 4 5 import org.eclipse.emf.common.util.URI; 6 import org.eclipse.emf.ecore.resource.Resource; 7 import org.eclipse.emf.ecore.resource.ResourceSet; 8 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 9 import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; 10 import org.fixflow.model.book.Book; 11 import org.fixflow.model.book.BookFactory; 12 import org.fixflow.model.book.BookPackage; 13 import org.fixflow.model.book.BookRepository; 14 import org.fixflow.model.book.util.BookResourceImpl; 15 16 public class test { 17 18 19 public static void main(String[] args) { 20 21 // 初始化模型 22 BookPackage.eINSTANCE.eClass(); 23 24 // 创建根元素 25 BookRepository bookRepository = BookFactory.eINSTANCE.createBookRepository(); 26 27 // 创建书籍1 28 Book book = BookFactory.eINSTANCE.createBook(); 29 book.setId("1"); 30 book.setName("我的奋斗"); 31 book.setAuthor("阿道夫·希特勒"); 32 // 将创建的书创建到根元素下 33 bookRepository.getBook().add(book); 34 35 // 创建书籍2 36 book = BookFactory.eINSTANCE.createBook(); 37 book.setId("2"); 38 book.setName("闪击英雄"); 39 book.setAuthor("海因茨·古德里安"); 40 // 将创建的书创建到根元素下 41 bookRepository.getBook().add(book); 42 43 // 创建书籍3 44 book = BookFactory.eINSTANCE.createBook(); 45 book.setId("3"); 46 book.setName("失去的胜利"); 47 book.setAuthor("冯·埃里希·曼施泰因"); 48 // 将创建的书创建到根元素下 49 bookRepository.getBook().add(book); 50 51 //注册XML扩展 52 Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; 53 Map<String, Object> m = reg.getExtensionToFactoryMap(); 54 m.put("xml", new XMIResourceFactoryImpl()); 55 56 // 创建一个资源 57 BookResourceImpl resource = new BookResourceImpl(URI.createURI("modelfile/book.xml")); 58 59 //设置文件编码 60 resource.setEncoding("UTF-8"); 61 //将模型保存到资源中 62 resource.getContents().add(bookRepository); 63 64 try { 65 //保存文件 66 resource.save(Collections.EMPTY_MAP); 67 } catch (IOException e) { 68 e.printStackTrace(); 69 } 70 71 //加载测试 72 load(); 73 74 75 } 76 77 public static BookRepository load() { 78 // 初始化模型 79 BookPackage.eINSTANCE.eClass(); 80 81 // 注册XML扩展 82 Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; 83 Map<String, Object> m = reg.getExtensionToFactoryMap(); 84 m.put("xml", new XMIResourceFactoryImpl()); 85 86 //创建一个 资源 ResourceSet 87 ResourceSet resSet = new ResourceSetImpl(); 88 89 // 获取资源 90 Resource resource = resSet.getResource(URI.createURI("modelfile/book.xml"), true); 91 92 //或者根节点 93 BookRepository bookRepository = (BookRepository) resource.getContents().get(0); 94 95 return bookRepository; 96 } 97 }
下面运行测试类之后生成文件:
至此一个最简单的XML文件通过EMF来读写的功能已经介绍完了,在后面的章节中我还会详细介绍EMF提供的高级功能。