使用 Eclipse Modeling Framework 进行建模,第 3 部分

EclipseModelingFramework中文版 EclipseModelingFramework中文版,影印版,清华大学出版社 立即下载
 
Eclipse Modeling Framework(EMF)中包含了一个开放源代码的工具 JMerge,这个工具可以使代码生成更加灵活,可定制性更好。本文使用一个例子来展示如何将 JMerge 添加到一个应用程序中,并为不同的环境定制 JMerge 的行为。

概述

本系列文章的 前一篇介绍了有关 Eclipse 的 Java Emitter Templates (JET)和代码生成的知识,在那篇文章中,您已经看到如何通过使用模板和代码生成器来节省时间,并实现模式级的代码重用。然而在大部分情况中,这都还不够。您需要能够将所生成的代码插入现有的代码中,或者允许以后的开发人员来定制所生成的代码,而不需要在重新生成代码时重新编写任何内容。理想情况下,代码生成器的创建者希望可以支持今后开发人员所有的需求:从修改方法的实现、修改各种方法签名,到修改所生成类的继承结构。这是一个非常有趣的问题,目前还没有很好的通用解决方案;但是有一个很好的纯 Java 的解决方案,称为 JMerge。

JMerge 是 EMF 中包含的一个开放源代码的工具,可以让您定制所生成的模型和编辑器,而重新生成的代码不会损坏已经修改过的内容。如果描述了如何将新生成的代码合并到现有定制过的代码中,那么 JETEmitter 就可以支持 JMerge。本文通过一个例子来展示其中的一些可用选项。





回页首


第一步

假设您已经添加了一个新项目,在这个项目中需要为编写的每个类都创建一个 JUnit 测试类,这样必须要对编写的每个方法都进行测试。作为一个认真且高效的(或者比较懒的)程序员来说,您决定要编写一个插件,它接受一个 Java 类作为输入,并生成 JUnit 测试例子的存根(stub)。您热情高涨地创建了 JET 和插件, 现在想允许用户定制所生成的测试类;然而在原有类的接口发生变化时,仍然需要重新生成代码。要实现这种功能,可以使用 JMerge。

从插件中调用 JMerge 的代码非常简单(参见清单 1)。这会创建一个新的 JMerger 实例,以及一个 URI merge.xml,设置要合并的来源和目标,并调用 merger.merge() 。然后合并的内容就可以展开为 merger.getTargetCompilationUnit() 。


清单 1. 调用 JMerge
	// ...
	JMerger merger = getJMerger();
	
	// set source
	merger.setSourceCompilationUnit(
		merger.createCompilationUnitForContents(generated));
	
	// set target
	merger.setTargetCompilationUnit(
		merger.createCompilationUnitForInputStream( 
			new FileInputStream(target.getLocation().toFile())));
	
	// merge source and target
	merger.merge();
	// extract merged contents
	InputStream mergedContents = new ByteArrayInputStream(
		merger.getTargetCompilationUnit().getContents().getBytes());
		
	// overwrite the target with the merged contents
	target.setContents(mergedContents, true, false, monitor);
	// ...
// ...
private JMerger getJMerger() {
	// build URI for merge document
	String uri = 
	   Platform.getPlugin(PLUGIN_ID).getDescriptor().getInstallURL().toString();
	uri += "templates/merge.xml";
		
	JMerger jmerger = new JMerger();
	JControlModel controlModel = new JControlModel( uri );
	jmerger.setControlModel( controlModel );
	return jmerger;
}

要启动这个过程,可以使用清单 2 这个简单的 merge.xml。其中声明了 <merge> 标签,以及缺省的命名空间声明。这段代码最主要的部分在 merge:pull 元素中。此处,源类中每个方法的代码都会被替换为目标类的对应方法的代码。如果一个方法在目标类不存在,就会被创建。如果一个方法只在源类中存在,而在目标类不存在,就会被保留。


清单 2. 一个非常简单的 merge.xml
<?xml version="1.0" encoding="UTF-8"?>
<merge:options xmlns:merge=
   "http://www.eclipse.org/org/eclipse/emf/codegen/jmerge/Options">
    <merge:pull 
      sourceGet="Method/getBody"
      targetPut="Method/setBody"/>
</merge:options>





回页首


区分生成的方法

这种简单的方法有一个非常明显的问题:每次修改源类并重新生成代码时,此前所做的修改就全部丢失了。我们需要增加某种机制来告诉 JMerge 有些方法已经被修改过了,因此这些方法不应该被重写。要实现这种功能,可以使用 <merge:dictionaryPattern> 元素。 merge:dictionaryPattern 允许您使用正则表达式来区分 Java 元素(参见清单 3)。


清单 3. 一个简单的 dictionaryPattern
<merge:dictionaryPattern
   name="generatedMember" 
   select="Member/getComment" 
   match=
        "/s*@/s*(gen)erated/s*/n"/>
<merge:pull 
   targetMarkup=
        "^gen$"
   sourceGet="Method/getBody"
   targetPut="Method/setBody"/>
      

dictionaryPattern 定义了一个正则表达式,它可以匹配注释中包含 " @generated " 的成员。 select 属性列出了要对这个成员的哪些部分与在 match 属性中给出的正则表达式进行比较。 dictionaryPattern 是由字符串 gen 定义的,它就是 match 属性值中圆括号中的内容。

merge:pull 元素多了一个附加属性 targetMarkup 。这个属性可以匹配 dictionaryPattern ,它必须在应用合并规则之前对目标代码进行匹配。此处,我们正在检查的是目标代码,而不是源代码,因此用户可以定制这些代码。当用户删除注释中的 " @generated " 标签时, dictionaryPattern 就不会与目标代码匹配,因此就不会合并这个方法体。请参见清单 4。


清单 4. 定制代码
/**
 * test case for getName
 * 
        @generated
 */
public void testSimpleGetName() {
	// because of the @generated tag,
	// any code in this method will be overridden
}
/**
 * test case for getName
 */
public void testSimpleSetName() {
	// code in this method will not be regenerated
}
      

您或许会注意到有些元素是不能定制的,任何试图定制这些代码的企图都应该被制止。为了支持这种功能,要定义另外一个 dictionaryPattern ,它负责在源代码(而不是目标代码)中查找其他标记,例如 @unmodifiable 。然后再定义一条 pull 规则,来检查 sourceMarkup ,而不是 targetMarkup ,这样就能防止用户删除标签或阻碍合并操作。请参见清单5。


清单 5. 不可修改代码的 merge.xml
<merge:dictionaryPattern
   name="generatedUnmodifiableMembers" 
   select="Member/getComment" 
   match=
        "/s*@/s*(unmod)ifiable/s*/n"/>
<merge:pull 
   
        sourceMarkup="^unmod$"
   sourceGet="Member/getBody"
   targetPut="Member/setBody"/>
      





回页首


细粒度的定制

在使用这种解决方案一段时间之后,您将注意到有些方法在定制的代码中具有一些通用的不可修改的代码(例如跟踪和日志记录代码)。此时我们既不希望禁止生成代码,也不希望全部生成整个方法的代码,而是希望能够让用户定制一部分代码。

要实现这种功能,可以将前面的 pull 目标替用清单 6 来代替。


清单 6. 细粒度的定制代码
<!-- if target is generated, transfer -->
<!-- change to sourceMarkup if the source is the standard -->
<merge:pull 
   targetMarkup="^gen$"
   sourceGet="Method/getBody"
   sourceTransfer=
        "(/s*///s*begin-user-code.*?///s*end-user-code/s*)/n"
   targetPut="Method/setBody"/>
      

这样会只重写字符串 " // begin-user-code " 之前和 " // end user-code " 之后的内容,因此就可以在定制代码中保留二者之间的内容。在上面的正则表达式中, "?" 表示在目标代码中,除了要替换的内容之外,其他内容全部保留。您可以实现与 JavaDoc 注释类似的功能,这样就可以拷贝注释,同时为用户定制预留了空间。请参见清单 7。


清单 7. 细粒度的 JavaDoc 定制
<!-- copy comments except between the begin-user-doc
     and end-user-doc tags -->
<merge:pull 
  sourceMarkup="^gen$"
  sourceGet="Member/getComment"
  sourceTransfer="(/s*<!--/s*begin-user-doc.*?end-user-doc/s*-->/s*)/n"
  targetMarkup="^gen$"
  targetPut="Member/setComment"/>

要支持这种注释,首先要修改开始标签和结束标签,使其遵循 HTML 注释语法,这样它们就不会出现在所生成的 JavaDoc 中;然后修改 sourceGet 和 targetPut 属性,以便使用 "Member/ getComment" 和 "Member/ setComment" 。 JMerge 允许您在细粒度级别上存取 Java 代码的不同部分。(更多内容请参见 附录 A)。





回页首


下一步

到现在为止,我们已经介绍了如何转换方法体,但是 JMerge 还可以处理域、初始化、异常、返回值、import 语句以及其他 Java 元素。它们也采用类似的基本思想,可能只需稍加修改即可。参考 plugins/org.eclipse.emf.codegen_1.1.0/test/merge.xml 就可以知道如何使用这些功能(我使用的是 Eclipse 2.1,因此如果您使用的是其他版本的 Eclipse,那么 ecore 插件的版本可能会不同)。这个例子非常简单,其中并没有使用 sourceTransfer 标记,但是该例显示了处理异常、标志和其他 Java 元素的方法。

更复杂的例子请参见 EMF 使用 JMerge 的方法: plugins/org.eclipse.emf.codegen.ecore_1.1.0/templates/emf-merge.xml 。从这个例子中可以看出 EMF 只允许部分定制 JavaDoc,但是采用上面介绍的一些技巧,就可以为方法体添加支持(这样可以增强 JET 的功能)。

 

附录 A:有效的目标选项

在 dictionaryPattern 和 pull 规则中,我们已经使用了 " Member/getComment " 和 " Member/getBody " 以及它们的 setter 方法,但是还有很多其他可用的选项。JMerge 支持 org.eclipse.jdt.core.jdom.IDOM* 中定义的任何类的匹配和取代。所有可用的选项如表 1 所示。

表 1. 有效的目标选项

类型 方法 注释
CompilationUnitgetHeader/setHeader
getName/setName
FieldgetInitializer/setInitializer不包含 "="
getName/setName变量名
getName/setName类名
ImportgetName/setName要么是一个完全限定的类型名,要么是一个随需应变的包
InitializergetName/setName
getBody/setBody
MembergetComment/setComment
getFlags/setFlags例如: abstract, final, native 等。
MethodaddException
addParameter
getBody/setBody
getName/setName
getParameterNames/setParameterNames
getParameterTypes/setParameterTypes
getReturnType/setReturnType
PackagegetName/setName
TypeaddSuperInterface
getName/setName
getSuperclass/setSuperclass
getSuperInterfaces/setSuperInterfaces





回页首


附录 B:merge:pull 属性

表2 给出了 merge:pull 元素的属性。

表 2. merge:pull 属性

属性 条件
sourceGet必需的。该值必须是 附录 A中列出的一个选项,例如 "Member/getBody"。
targetPut必需的。该值必须是 附录 A中列出的一个选项,例如 "Member/setBody"。
sourceMarkup可选的。用来在触发 merge:pull 规则之前过滤必须匹配源代码的 dictionaryPatterns 。格式如 "^dictionaryName$",也可以使用 "|" 将多个 dictionaryPatterns 合并在一行中。
targetMarkup可选的。用来在触发 merge:pull 规则之前过滤必须匹配目标代码的 dictionaryPatterns 。格式如 "^dictionaryName$",也可以使用 "|" 将多个 dictionaryPatterns 合并在一行中。
sourceTransfer可选的。一个正则表达式,指定要传递给目标代码的源代码的数量。






回页首


下载

名字大小下载方法
os-ecemf3/com.ibm.pdc.example.jet_1.0.0.zip HTTP
关于下载方法的信息


参考资料



 

关于作者

Adrian Powell 从刚开始加入 VisualAge for Java Enterprise Tooling 小组开始使用 IBM 的 Java 开发工具,在这里他花费了两年的时间来手工编写一个代码生成器。从那以后,他一直从事 Eclipse 和 VisualAge for Java 中的工具和插件的开发,他现在几乎为 Eclipse 和 VisualAge for Java 的每一个版本都开发了这种工具和插件。Adrian 目前在 IBM 的 Vancouver Centre 从事于电子商务创新方面的研究,在这里他阅读源代码,为同事提供一些支持。


Eclipse Modeling Framework 2.0中文版 [(美)斯泰因贝格等著][清华大学出版社] 本书全面介绍Eclipse建模架构EMF,并指导 开发人员学习EMF。 立即下载

相关推荐

用EclipseModelingFramework实现模型驱动开发,第1部分

火龙果软件工程技术中心  本文内容包括:EMF究竟是什么?让工具自己说话使用生成的EMF模型生成Java代码定制生成的代码在Java中操纵模型结束语参考资料EclipseModelingFramework(EMF)是一个开放源代码的模型驱动应用程序开发框架。它可以基于XMLSchema、UML或经过注释的Java中指定的模型,创建Java代码,实现图形化的数据编辑、操纵、读取和序列化。EMF是IBMWebSphereStudio和Eclipse项目中很多工具的基础。本文将帮助您逐步了解创建模型、生成代码、使用生成的应用程序和定制编辑器的整个过程。EMF究竟是什么?EclipseModeling

不再手画UML,这些工具帮你智能生成!

使用这些工具时,你可能需要将你的代码或项目作为输入,工具会分析代码结构,并生成相应的 UML 图表。有些工具提供了插件或扩展,可以集成到 IDE 中,如 IntelliJ IDEA 和 Eclipse,使得在开发环境中直接生成和更新 UML 图表变得更加方便。选择哪个工具取决于你的具体需求、预算(部分工具是商业软件)、以及你更倾向于哪种工作流程。生成 UML(统一建模语言)图表的工具有很多,其中一些可以直接从代码生成。

程序员野蛮成长 6374

药物重定位实战:如何用反向找靶技术挖掘老药新用(附Python代码示例)

本文详细介绍了药物重定位中的反向找靶技术,通过分子相似性计算、机器学习模型和结构对接等方法,挖掘已有药物的新治疗潜力。附Python代码示例,帮助读者快速实现从分子结构到潜在靶标的智能预测,显著提升药物研发效率。

weixin_28726671的博客 259

关于Eclipse Modeling Framework进行建模,第二部分

使用 Eclipse Modeling Framework 进行建模,第 2 部分 Eclipse 的 Java Emitter Templates(JET) 是一个开放源代码工具,可以在 Eclipse Modeling Framework(EMF)中生成代码。 JET 与 JSP 非常类似,不同之处在于 JET 功能更强大,也更灵活,可以生成 Java、 SQL 和任何其他语言的代码,包括 ...

weixin_34323858的博客 198

香橙派5b 移植 imx415

修改设备树,以为例,关闭ov13855,添加imx4151;0;1;0;1;0;1;0;1;0;1;0;1;0;以此类推,修改三个dtsi。

ChenYX的博客 4533

最全中文停用词表(可直接复制)

最全的停用此表整理 词表名 词表文件 中文停用词表 cn_stopwords.txt 哈工大停用词表 hit_stopwords.txt 百度停用词表 baidu_stopwords.txt 机器智能实验室停用词库 scu_stopwords.txt 以上停用词表链接:https://github.com/goto456/stopwords 以下是我常用的1893个停用词,可直接复制 ! " # $ % & ' ( ) * + , - -- . .. ... ....

dilifish的博客 12万+

手把手教你MyEclipseUML建模(下)

手把手教你MyEclipseUML建模(下) 点击访问:手把手教你MyEclipseUML建模(上) 1.用UML 2建模 MyEclipse提供了以下UML 2特性: UML 2图:类、组件、部署、组合结构、用例、活动、序列、状态机、配置文件 集成图表编辑器、大纲视图和属性视图 UML透视图 通过热区直接编辑节点 存储在UML 2模型图中的图表(.umldi)档案 对可能包含u...

开发猫 935

保姆级教程:用R语言自动化处理FAERS季度数据(从文件合并到删除废弃Case)

本文提供了一份详细的R语言教程,指导如何自动化处理FAERS季度数据,包括文件合并和删除废弃Case。通过使用tidyverse、fs等R包,构建健壮的自动化流程,特别适合药物安全监测领域的数据分析师。教程涵盖环境准备、智能合并多季度数据、精准删除废弃Case等关键步骤,并提供了错误处理与日志记录的实用技巧。

weixin_42701915的博客 124

【java】eclipse下生成工程类图

在应用软件开发过程中,如果软件由很多对象组成,它的结构仅仅凭借分析很难理清,同时为了有利于软件的开发及重用,所以在开发系统之前建模是非常有必要的,在众多的建模方法中选择一种适应自身应用特点,方便不同背景的人们交流的建模方法已经成为开发人员及用户的迫切愿望。UML 是面向对象软件开发中的一种通用、统一的图形模型语言,是用于软件系统规约化、可视化构造和建模的有效工具。 eclipse实现自动生成um...

XYZ 3362

BugkuCTF-PWN题pwn2-overflow超详细讲解

解题思路 1)计算出get_shell_的地址偏移量 2)算出来之后就直接溢出到后门函数 知识点 x64函数调用规则 解题之前我们先学下linux x64的函数调用规则。 x64机器在调用某个函数前,比如int func(int a, int b, int c, int d, int e, int f, int g, int h),首先他会把前6个参数从左往右存入到寄存器rdi、rsi、rdx、rcx、r8、r9,其余参数存入到栈里,保存的顺序是从右往左入栈。比如abcdef会存入到寄存器里,然后一次入栈h

am_03的博客 3013

【声纳技术】声呐时间反转镜技术:从被动聚焦到主动空间复用

时间反转镜技术以其独特的物理机制,为水声通信与声呐探测提供了一条绕过传统自适应均衡器的新路径。被动时间反转利用接收端的空间分集实现脉冲压缩,结构简洁、计算高效;主动时间反转则通过发射端预编码,将多径能量引导至目标位置,为多用户下行链路的空间复用奠定了物理基础。从Kuperman等人在海洋中首次验证声学时间反转镜,到TR-MIMO声呐的湖试验证,再到VTRM-CRK多用户通信系统的海试成功,该技术已从理论概念逐步走向工程实用。

u012133341的博客 55

[转载]使用 Eclipse Modeling Framework 进行建模,第 3 部分

使用 Eclipse Modeling Framework 进行建模,第 3 部分Eclipse Modeling Framework(EMF)中包含了一个开放源代码的工具 JMerge,这个工具可以使代码生成更加灵活,可定制...

congji3817的博客 380

VAY 是 SAP 自动科目确定(OBYC-GBB)中的科目修改码,专用于带科目分配对象的销售订单发货场景,核心是触发 “Dr 成本要素科目(如销售费用 / 特定成本对象) Cr 库存商品” 的分录,

摘要:VAY是SAP中用于带科目分配对象(如成本中心、WBS)的销售订单发货的科目修改码,与标准VAX场景不同,它生成"借成本要素科目/贷库存商品"的分录。配置路径为OBYC-GBB-VAY,需确保借方科目为成本要素。典型业务场景包括免费样品、项目专用发货等。常见问题包括VAY未触发或科目记账错误,需检查销售订单科目分配、移动类型设置及OBYC配置。特殊场景建议单独配置科目以便费用分析。

金牌架构师 1253

使用 Eclipse Modeling Framework 进行建模,第 2 部分

Eclipse 的 Java Emitter Templates(JET) 是一个开放源代码工具,可以在 Eclipse Modeling Framework(EMF)中生成代码。 JET 与 JSP 非常类似,不同之处在于 JET 功能更强大,也更灵活,可以生成 Java、 SQL 和任何其他语言的代码,包括 JSP。本文将介绍如何创建和配置 JET,并将其部署到各种环境中。Java Emi

CS_Mercy的专栏 731

【华为OD机试真题 新系统】1043、魔法咒语组合 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

【华为OD机试真题 新系统】1043、魔法咒语组合 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备战华为od

KJ.JK 281

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

用 Eclipse Modeling Framework 实现模型驱动开发,第 1 部分

转自http://www.ibm.com/developerworks/cn/linux/opensource/os-ecemf1/  用 Eclipse Modeling Framework 实现模型驱动开发,第 1 部分 创建 UML 模型并生成代码

笨笨熊的专栏 1188

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

[转载]使用 Eclipse Modeling Framework 进行建模,第 2 部分

使用 Eclipse Modeling Framework 进行建模,第 2 部分Eclipse 的 Java Emitter Templates(JET) 是一个开放源代码工具,可以在 Eclipse Modeling Fr...

congji3817的博客 307

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Eclipse Modeling Framework

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。http://blog.youkuaiyun.com/topmvp - topmvpThis book is a comprehensive introduction to and developers quick reference for the Eclipse Modeling Framewo

TopMVP 724

关于Eclipse中的开源框架EMF(Eclipse Modeling Framework)

Eclipse项目本身可以划分为4个主要的子项目:Equinox,平台,Java开发工具(Java Development Tools,JDT)和插件开发环境(Plug-in Development Environment,PDE).一般来说,这4个子项目足以来扩展架构和开发基于Eclipse的工具. Equinox和平台是Eclipse的核心组件,许多人直接将他们当做Eclipse.Equin...

weixin_34132768的博客 261

Eclipse Modeling Tools安装GMF插件

1.首先介绍一个Eclipse各个版本的区别(此处为转载http://blog.youkuaiyun.com/chafferers/article/details/51834584) Eclipse IDE for Java Developers 是Eclipse的platform加上JDT插件,用来java开发的  Eclipse IDE for Java EE Developers 应该是Eclips

zhangustb 3892
上一篇: 使用 Eclipse Modeling Framework 进行建模,第 2 部分
下一篇: 使用 EMF Query 查询 EMF 模型
CS_Mercy
博客等级 码龄18年 12粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值