`

代码生成技术学习之二 JMerger

阅读更多
代码自动生成,生成的代码许多时候需要修改,以满足我们的需求,而修改的代码我们希望重新生成代码的时候不被覆盖,那就需要一种Merge技术。JMerger和JET模板是在EMF代码生成中使用的关键技术。下面我们看一下一个使用JMerger的例子:
两个java文件:
HelloSrc.java

package hello;

public class Hello{
    
    public void say(){
        System.out.println("hello");
    }
    
    /**
     * @generated
     */
    public void sayHelloTo(String name){
        System.out.println("Hello," + name);
    }
    
    public void test(){
        
    }
}


HelloTarget.java
package hello;

public class Hello 
{
    
   public void say(){
       System.out.println("hello world");
   }
   /**
    * @generated
    */
   public void sayHelloTo(String name){
       System.out.println(name);
   }
}


我们使用JMerger来合并覆盖原先生成的的方法//@generated标记的方法,而我们
自己定义的方法和去掉@generated的的方法则不被覆盖。
我们需要增加某种机制来告诉 JMerge 有些方法已经被修改过了,因此这些方法不应该被重写。要实现这种功能,可以使用 <merge:dictionaryPattern> 元素。 merge:dictionaryPattern 允许您使用正则表达式来区分 Java 元素:
<?xml version="1.0" encoding="UTF-8"?>
<merge:options xmlns:merge="http://www.eclipse.org/org/eclipse/emf/codegen/jmerge/Options">
 <merge:dictionaryPattern
   name="generatedMember" 
   select="Member/getComment" 
   match=
        "s*@s*(gen)erateds*"/>
 
 <merge:pull 
   targetMarkup="^gen$"
   sourceGet="Method/getBody"
   targetPut="Method/setBody"/>
 
</merge:options>


dictionaryPattern 定义了一个正则表达式,它可以匹配注释中包含 " @generated " 的成员。 select 属性列出了要对这个成员的哪些部分与在 match 属性中给出的正则表达式进行比较。 dictionaryPattern 是由字符串 gen 定义的,它就是 match 属性值中圆括号中的内容。merge:pull 元素多了一个附加属性 targetMarkup 。这个属性可以匹配 dictionaryPattern ,它必须在应用合并规则之前对目标代码进行匹配。此处,我们正在检查的是目标代码,而不是源代码,因此用户可以定制这些代码。当用户删除注释中的 " @generated " 标签时, dictionaryPattern 就不会与目标代码匹配,因此就不会合并这个方法体
package hello;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.codegen.merge.java.JControlModel;
import org.eclipse.emf.codegen.merge.java.JMerger;
import org.eclipse.emf.codegen.merge.java.facade.ast.ASTFacadeHelper;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;

public class JMergerTest
{
    public static void merge( File src, File target )
    {
        JControlModel model = new JControlModel();
        ASTFacadeHelper astFacadeHelper = new ASTFacadeHelper()
        {
            Map<String, String> options;
            @SuppressWarnings("unchecked")
            @Override
            public Map getJavaCoreOptions()
            {
                if( options == null )
                {
                    options = new HashMap<String, String>();
                    options.put( JavaCore.COMPILER_COMPLIANCE,
                                 JavaCore.VERSION_1_6 );
                    options.put( JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6 );
                    options.put( JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
                                 JavaCore.VERSION_1_6 );
                    options.put( JavaCore.COMPILER_PB_ASSERT_IDENTIFIER,
                                 JavaCore.ERROR );
                    options.put( JavaCore.COMPILER_PB_ENUM_IDENTIFIER,
                                 JavaCore.ERROR );
                    options.put( JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE,
                                 JavaCore.ENABLED );
                    options.put( JavaCore.COMPILER_DOC_COMMENT_SUPPORT,
                                 JavaCore.ENABLED );
                    Map cfo = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
                    options.putAll( cfo );
                    options.put( DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_PACKAGE,
                                 "1" );
                }
                return options;
            }

        };
        String mergexml = JMergerTest.class.getResource( "merge.xml" ).getFile();
        model.initialize( astFacadeHelper, mergexml );
        JMerger jMerger = new JMerger(model);
        try
        {
            jMerger.setSourceCompilationUnit( jMerger.createCompilationUnitForInputStream( 
                                                            new FileInputStream( src )));
            jMerger.setTargetCompilationUnit( jMerger.createCompilationUnitForInputStream( 
                                                            new FileInputStream(target)));
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
        jMerger.merge();
        String contents = jMerger.getTargetCompilationUnit().getContents();
        System.out.println(contents);
    }

    public static void main( String[] args )
    {
        File src = new File("HelloSrc.java" );
        File target = new File("HelloTarget.java");

        JMergerTest.merge( src, target );
    }
}

结果:
package hello;

public class Hello 
{
    
   public void say(){
       System.out.println("hello world");
   }
   /**
    * @generated
    */
   public void sayHelloTo(String name){
        System.out.println("Hello," + name);
    }
   public void test(){
        
    }
}

参考http://www.ibm.com/developerworks/library/os-ecemf3/
上面有更详细的介绍,但代码使用的版本有点老。
1
1
分享到:
评论

相关推荐

    Simulink仿真及代码生成技术入门到精通 (2).zip

    《Simulink仿真及代码生成技术入门到精通》是一本专为嵌入式开发者准备的指导书籍,旨在帮助读者从基础到高级全面掌握Simulink的使用和代码生成技术。Simulink是MATLAB环境中的一个强大工具箱,主要用于动态系统建模...

    C#代码生成器

    二、C#代码生成器的使用步骤 1. 设计模板:首先,用户需要设计或选择合适的代码生成模板,模板可以包含基本的类结构、属性、方法等元素。 2. 配置参数:根据项目需求,配置生成代码的相关参数,如命名空间、类名、...

    Matlab——Simulink仿真及代码生成技术入门到精通_第三章 Simulink高级篇(1-8).rar

    《Matlab Simulink仿真及代码生成技术入门到精通》第三章主要涵盖了Simulink的高级功能,包括代码生成的控制、代码可读性的提升、生成代码的文件结构解析、ERT下默认配置的理解以及rtw文件的相关操作。以下是对这些...

    代码生成器(Asp.net(c#))源码

    代码生成器是通过自动化技术根据预设模板或元数据自动生成源代码的工具。在Asp.net(C#)环境中,代码生成器通常用于创建控制器、视图、模型等核心组件,减少手动编写重复性代码的工作量,从而让开发者能更专注于业务...

    Simulink仿真及代码生成技术入门到精通

    与其说这是一本关于Simulink/MATLAB的书,不如说这是一本作者的成长手册——从入门,到进阶,先夯实了基础,再来攻克代码生成的难题,作者前进的脚步一直踏踏实实稳稳当当的。作者凭借这些能成功,你学完这些也不会...

    动软.Net代码生成器

    动软.Net代码生成器源码的开放,对于.NET开发者来说,不仅意味着可以免费获取和使用这款工具,更重要的是,可以学习到代码生成技术的实现细节,提升自身的编程技能。通过研究源码,开发者可以了解到如何利用.NET 2.0...

    时空之门前端代码生成器4.5独立版Beta10版。三大变形功能群齐备。

    时空之门前端代码生成器,是第四代动词算子式代码生成器,经过彻底的重构的先进动词算子式代码生成器,也是专用的Vue+ElementUI前端代码生成器,可以和多种后端代码生成器搭配。和平之翼和光对前端代码生成的支持是...

    编译原理 三地址代码生成器

    《编译原理:深入理解三地址代码生成器》 在计算机科学领域,编译原理是研究编程语言如何转化为机器可执行代码的理论基础。其中,三地址代码(Three-Address Code,TAC)是一种中间表示形式,常用于编译器的设计,...

    中间代码生成器的设计(实验报告+代码+运行结果) 编译方法

    实验报告的标题为“中间代码生成器的设计”,其主要探讨了编译方法中涉及的中间代码生成技术。实验的核心目标是设计和实现一个能够将算术表达式转换为四元式序列的工具。四元式是一种常用的中间表示形式,它在编译...

    编译原理中间代码生成报告

    本报告主要关注如何在实验二的基础上,为赋值语句、if语句和while语句生成四元式中间代码。 一、实验目的 实验的主要目标是扩展原有的编译器功能,使其能够对已识别的赋值语句、if语句和while语句进行语义分析,并...

    动软代码生成器的开源源码

    "动软代码生成器"是一款高效实用的软件开发工具,其开源源码为开发者提供了深入学习和交流的机会。代码生成器在IT行业中扮演着重要的角色,它能够自动生成常见的业务逻辑代码,极大地提高了开发效率,减少了手动编写...

    乐谱代码生成软件 乐谱代码生成软件

    9. **学习与教育**:对于教育领域,乐谱代码生成软件能帮助教师创建练习材料,学生则可以更方便地查看、修改和演奏乐谱。 10. **协作与共享**:部分软件提供了云同步功能,让多人可以同时编辑同一份乐谱,方便团队...

    零基础速成simulink代码生成-结合CANOE的DBC文件CAN报文代码生成 移植到硬件4 模型

    零基础速成simulink代码生成——结合CANOE的DBC文件CAN报文代码生成 移植到硬件4 模型;此专栏面向嵌入式工程没有matlab开发经验的人,可以快速学习和实践这门技术。MDB技术,越来越成熟和普遍,从手写代码转到基于...

    代码生成器源代码

    这个“代码生成器源代码”是实现这一功能的具体实现,让我们来深入了解一下这个工具及其背后的技术原理。 首先,代码生成器的核心功能是解析数据库结构。在开发过程中,开发者通常会先设计数据库模式,包括表、字段...

    伪代码生成器PseudoCodeTool

    适用于java/C/C++等代码,源代码为java代码通过运行代码将代码输入程序框中D盘自动生成伪代码文件PseudoCode.txt。(注意:由于是简单代码只可适用于糊弄老师,实验报告等,不可用于学术研究)。

    和平之翼代码生成器SM版新版0.7.12

    和平之翼代码生成器是无垠式代码生成器的第二代,轻量级定制版的代码生成器。 他有如下的特点 1)每个版本都是单一技术栈支持。分为不同版本。本版是SpingMVC Spring Mybati技术栈。 2)比无垠式代码生成器更美观的...

    c++代码生成器

    【C++代码生成器】 C++代码生成器是一种工具,它使用编程语言(在这个案例中是Python)来自动生成C++源代码。这样的工具在软件工程中非常有用,尤其是在需要大量重复或结构化代码时,可以极大地提高开发效率,减少...

    和平之翼代码生成器SMEU Swing单机1.6版源码

    和平之翼代码生成器SMEU Swing单机1.6版源码 是和平之翼代码生成器的Swing单机版,是可运行的Jar包。 在装好JDK或JRE的计算机上双击即可执行。 也可在命令窗口以java -jar PeaceWingSMEU_Swing_1_6.jar运行。 和平之...

Global site tag (gtag.js) - Google Analytics