六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 52|回复: 0

代码生成技术学习之二 JMerger

[复制链接]

升级  98.33%

147

主题

147

主题

147

主题

举人

Rank: 3Rank: 3

积分
495
 楼主| 发表于 2013-1-15 02:57:52 | 显示全部楼层 |阅读模式
代码自动生成,生成的代码许多时候需要修改,以满足我们的需求,而修改的代码我们希望重新生成代码的时候不被覆盖,那就需要一种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/
上面有更详细的介绍,但代码使用的版本有点老。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表