在生成java代码的中经常会遇到Java文件的合并问题,EMF的org.eclipse.emf.codegen插件提供了Java文件合并的工具类,用户只需要配置一定的规则就可以解决java文件的合并问题。
EMF提供了简介的API调用:
public String mergeContent(String sourceContent,String targetContent) { //用户配置的合并规则 String jmergeRuleURI= URI.createPlatformPluginURI( "org.eclipse.emf.codegen.ecore/templates/emf-merge.xml", false).toString(); //$NON-NLS-1$ JControlModel model = new JControlModel(); model.initialize(new ASTFacadeHelper(), jmergeRuleURI); JMerger jMerger = new JMerger(model); jMerger.setSourceCompilationUnit(jMerger.createCompilationUnitForContents(sourceContent)); jMerger.setTargetCompilationUnit(jMerger.createCompilationUnitForContents(targetContent); //执行合并规则 jMerger.merge(); return jMerger.getTargetCompilationUnit().getContents(); }
从上面代码可以看出合并规则是重点,我们以"org.eclipse.emf.codegen.ecore"插件中本身提供的emf-merge.xml来简要说明规则。
首先需要说明的是,我们对Java中的元素用节点(Node)表示,例如Field、Method都是java可编译单元的节点。对于java文件合并,无非三种情况:
1、如果Java Source中存在该节点,而且Java Target中也同样存在该节点,如何合并
2、如果Java Source中存在该节点,但是Java Target中不存在该节点,如何处理
3、如果Java Source中不存在该节点,但是Java Target中存在该节点,如何处理
在合并规则的xml文件中对这三种情况都有相应的配置。
其次在合并规则中有个重要的标记概念(markup),个人理解就是对节点的划分,比如一部分节点是自动生成的,这部分就属于“gen”的标记范围。这样在运用合并规则的时候,就可以对某一个范围进行操作。
下面首先看一下如何定义标记,
<merge:dictionaryPattern
name="generatedUnmodifiableMembers"
select="Member/getComment"
match="@\s*(gen)erated\s*(This field/method[^(?:\n\r?|\r\n?)]*)*(?:\n\r?|\r\n?)"/>
name属性仅仅在没有捕获的内容的时候作为标记名,例如 match="@\s*model" 可以匹配这个正则表达式,但是正则表达式中没有捕获的内容,那么将会用该名字作为标记,select属性中的内容分为两部分,并由‘/’分割。前面的部分表示节点的具体类型,示例中为Member,则表示节点的实际类型为org.eclipse.emf.codegen.merge.java.facade.JMember(可以查看该包下的JNode及子类,把Java可编译单元解析成具体的语法树模型),后面的getComment表示该实际类型的方法名。match属性为正则表达式。这个标记就表示如果JMember类型的comment可以匹配match所表示的正则表达式,那么这个JMember就属性'gen'标记。其中‘gen’就是正则表达式中捕获的字符串。
如果我的java代码如下:
/**
* Returns the value of the '<em><b>Title</b></em>' attribute.
* @generated
*/
String getTitle();
那么该节点会放在‘gen’标记中。
其他定义标签示例:
<merge:dictionaryPattern
name="modelMembers"
select="Member/getComment"
match="@\s*(model)"/>
EMF生成的Java代码的模型标记
如何定义合并规则:
1、如果Java Source中存在该节点,而且Java Target中也同样存在该节点,如何合并
使用pull元素来定义规则:
<merge:pull
sourceMarkup="^gen$"
sourceGet="Member/getComment"
targetMarkup="^gen$"
targetPut="Member/setComment"/>
sourceMarkup表示节点所属的标记,sourceGet也是有两部分组成,一部分表示节点的类型,另一部分表示获得的方法。该合并规则表示,如果target中的JMember类型属于'gen'标签,而且对应的source JMember类型也属于'gen'标签,那么会把source的comment设置到target的comment中。
如果想保留target中的部分java注释的话需要使用sourceTransfer属性,例如sourceTransfer="(\s*<!--\s*begin-user-doc.*?end-user-doc\s*-->\s*)(?:\n\r?|\r\n?)",表示将会保留target中“// begin-user-code”
和“
// end-user-code”
包围住的所有的字符。
2、如果Java Source中存在该节点,但是Java Target中不存在该节点,如何处理
使用push元素定义规则:
<merge:push targetParentMarkup="^gen$" select="Annotation"/>
表示如果Annotation节点的父属于'gen'标记,则会在target中添加该注解。
事实上在默认情况下如果没有声明所属的标记,默认markup为ture的,个人理解这个节点可以实现那些节点可以不用合并到target中,即仅仅在target父类型标记不为'gen'标记,则不会合并到target中。
3、如果Java Source中不存在该节点,但是Java Target中存在该节点,如何处理
使用sweep元素来定义规则:
<merge:sweep markup="^gen$" select="Member"/>
表示如果该节点类型为JMember,而且属于'gen'标记,则会删除该节点。
实际上对于这种情况,如果JMerger提供了三种策略,删除节点,注释节点、重命名节点。默认为删除策略,通过action属性设置
如何根据source排序
如果想根据source中的顺序对target进行排序,需要定义排序规则:
<merge:sort markup="^ordered$" select="Field"/>
如果source中field为f2/f1/f3.而且target中存在相应的Field,那么在合并后的输出Field为source的顺序,即f2/f1/f3。
在合并规则的xml根节点上可以定义不执行合并的Pattern
<merge:options
indent=" "
braceStyle="matching"
redirect="Gen"
block="\s*@\s*generated\s*NOT\s*(?:\n\r?|\r\n?)"
noImport="\s*//\s*import\s+([\w.*]*)\s*;\s*(?:\n\r?|\r\n?)"
xmlns:merge="http://www.eclipse.org/org/eclipse/emf/codegen/jmerge/Options">
block属性就是不执行合并的模式,当用户的comment能匹配这种模式的时候,pull规则不会应用(即失效)。如果Type的comment匹配这种模式,这这个类型就不会执行合并操作。
参考:http://www.blogjava.net/JetGeng/archive/2006/05/01/44261.html
http://www.blogjava.net/JetGeng/archive/2006/05/02/44342.html
相关推荐
《Eclipse开发使用GEF和EMF》是IBM红皮书系列中的一部经典著作,主要探讨了如何在Eclipse环境中利用GEF(图形编辑框架)和EMF( Eclipse模型框架)进行图形化应用程序的开发。这两项技术是Eclipse平台上的核心组件,...
通过阅读这份文档,读者可以了解到如何创建、编辑和解析EMF文件,以及EMF在应用程序中的使用方式,比如打印、图像处理和图形显示。 **emf.hlp**:这是一个帮助文件,通常用于提供快速查询和参考。在这个文件中,...
EMF(Enhanced MetaFile)是一种在Windows操作系统中广泛使用的高级元文件格式。它作为WMF(Windows Metafile)格式的32位增强版,旨在解决WMF在印刷行业中的一些限制。EMF格式的一个显著特点是其设备独立性,这意味...
EMF(Enhanced Metafile)文件是Windows操作系统中使用的一种矢量图形和图元文件格式。这种文件类型被广泛用于存储图形、图像和打印数据,因为它支持复杂的图形操作,如曲线绘制、渐变填充和透明效果。EMF文件是GDI+...
- 使用EMF,首先需要创建一个Ecore模型,这是EMF的数据模型定义,包含了类、属性和关系等元数据。 - 可以通过Eclipse的EMF插件自动生成Ecore模型,或者手动编写.xmi文件来定义模型。 - 一旦模型创建完成,EMF会...
本示例代码是关于如何使用Java将SVG转换为EMF,这在需要在Windows系统中处理矢量图形时非常有用,因为EMF是Windows系统广泛支持的格式。 SVG是一种基于XML的开放标准,用于描述2D图形。它支持复杂的形状、路径、...
总的来说,将EMF转换为PNG的过程涉及到了Java编程、图像处理库的使用以及文件格式的转换。通过`freehep`库,我们可以方便地在Java环境中实现这种转换,为跨平台的应用提供了便利。在实际开发中,你还可以扩展这个...
解决方案文件"emf2wmf.sln"和项目文件"emf2wmf.vcproj"则表明这是一个使用Microsoft Visual Studio开发的C++项目,用于编译和运行转换代码。 在转换过程中,开发者需要考虑的关键点包括: 1. **记录解析**:EMF和...
### 使用EMF开发基于模型的Eclipse插件 #### EMF简介 Eclipse Modeling Framework(EMF)是Eclipse项目下的一个重要的组成部分,它提供了一种基于Java的模型构建框架。EMF的主要特点在于它能够极大程度上简化基于...
本教程旨在帮助初学者理解EMF的基础概念,并通过实践掌握EMF插件的使用。 1. **EMF基础** EMF基于MDE(Model Driven Engineering)理念,允许开发者创建、编辑和管理模型。模型是业务逻辑的一种抽象表示,可以用来...
3. "使用EMF Query查询EMF模型(2) - 编程入门网" 这部分可能深入介绍了EMF Query(EMF QL),这是一个用于查询和操作EMF模型的强大工具。通过EMF QL,开发者可以方便地检索、分析和修改模型数据。 总结来说,EMF ...
通过将GEF与EMF结合使用,可以轻松创建高度可定制的图形化编辑器,用于编辑由EMF生成的模型。 **3.3 GEF编辑器开发流程** 1. **定义模型**:首先使用EMF定义模型。 2. **创建视图**:使用GEF创建一个图形化的视图...
首先,从提供的标签“源码”和“工具”来看,我们可以推断这篇文章可能涉及了EMF.compare的源代码分析以及它是如何作为开发者工具来使用的。EMF.compare作为一个开源项目,其源代码对开发者来说是开放的,允许他们...
### EMF自学笔记知识点详述 #### 一、EMF框架概述 EMF(Eclipse Modeling Framework)是Eclipse项目中的一个子项目,它提供了一套用于构建模型驱动的开发工具和应用程序的框架。EMF的主要目标是简化元数据驱动应用...
1. **元模型(Metamodel)定义**:EMF允许开发者使用Ecore语言定义元模型,这是对数据模型的一种抽象描述。 2. **代码生成**:基于元模型,EMF可以自动生成Java类和其他相关代码,这些代码可以直接在应用程序中使用...
为了解决这个问题,我们需要有一种方法来识别并获取WMF和EMF图片中使用的特定字体。这正是"获取WMF、EMF图片中文字所用字体名称"这个程序的功能。这个代码能够解析WMF和EMF文件的元数据,提取出其中涉及的所有字体...
本文将深入探讨EMF插件的核心功能、使用场景以及如何在Eclipse环境中集成和使用EMF。 一、EMF插件概述 EMF插件是基于Java的元数据框架,它允许开发人员创建、编辑和管理复杂的模型。这些模型可以用来表示业务逻辑、...