EMF中的code generation(一)

 

简单的说就是template files(*.XXjet) 由Jet Builder,JETNature 转换成为 java 类(*.java) 这些类可以按照定义的模版(skeleton)生成. 

如果使用Jet生成code,第一步生成的java 类还是属于template implementation class,只有这些java class输出的text才达到真正的目的.

归纳为2步:translation and generation.

1>JETCompiler 是translation中最关键的类.先parse()再generate()输出为template implementation class:

[JETCompiler.parse()]

    directive.getDirectives().add("jet" );
    directive.getDirectives().add(
"include"
);
    directive.getDirectives().add(
"start"
);
    directive.getDirectives().add(
"end");//这些就是*.jet中的那些关键字.

2>JETEmitter提供了high-level api,其generate()一个方法完成了2个步骤:translation 和 generation.

JETEmitter默认把template implementation class输出到.JETEmitters这个project中.想输出到其他地方,修改这个projectName即可.

 protected String projectName = ".JETEmitters";

 详细来看JETEmitter.generate()完成的5个步骤(这个是通过内部的一个EclipseHelper来完成的,以一个plugin代码为例,该plugin利用jet生成typesafe enum class):

  1. 在workspace新建一个.JETEmitters project. [EclipseHelper.initialize()]
    javaProject = JavaCore.create(project);
  2. 对project做好相应的准备: 设置Java Nature,class path variables.
  3. .JETEmitters project中将template translate成template implementation java 文件. 
  4. Build the project把template implementation source code 编译成Java .class file
  5. 调用translated Java template implementation class的generate() and return the generated text as a String.[EclipseHelper.initialize()]
    Class theClass  =  
                theClassLoader.loadClass
                  ((packageName.length() 
    ==   0   ?   ""  : packageName  +   " . " +  jetCompiler.getSkeleton().getClassName());
              String methodName 
    =  jetCompiler.getSkeleton().getMethodName();
              Method [] methods 
    =  theClass.getDeclaredMethods();
              
    for  ( int  i  =   0 ; i  <  methods.length;  ++ i)
              
    {
                
    if (methods[i].getName().equals(methodName))
                
    {
                  jetEmitter.setMethod(methods[i]);
                  
    break;
                }

              }
    [JETEmitter.generate()]
     result  =  (String)method.invoke( object , arguments);//implementation class的generate()返回的字串.再保存为一个java文件,就成为生成的最终代码.

使用JETEmitter:[JETGateWay.generate()]

JETEmitter emitter  =   new  JETEmitter(config.getTemplateFullUri(), getClass().getClassLoader());
    emitter.addVariable(config.getClasspathVariable(), config.getPluginId());

    IProgressMonitor sub 
=   new  SubProgressMonitor(monitor,  1 );
    String result 
=  emitter.generate(sub,  new  Object [] { config.getModel() } );

[NewTypesafeEnumCreationWizard.finishPage()](在该plugin的wizard的performFinish()中调用了finishPage())

JETGateway gateway  =   new  JETGateway(config);
    String content 
=  gateway.generate(monitor);
    IFile file 
=  gateway.save(monitor, content.getBytes());

最后调用JETGateway.save()保存文件.代码生成完成.

 贴个例子:一般情况,使用JETcomplier

[GreetingEx.jet]

<%@ jet package="hello" class="GreetingEXTemplate" skeleton="generator.skeleton"%><!-使用自定义的skeleton,没声明就用默认的(见org.eclipse.emf.codegen.jet.JETSkeleton.->
 Hello, 
<%=argument%>!  <!-argument是默认的skeleton中传给generate的参数名字.->
The current time 
is <%=(new java.util.Date()).getTime()%> .
<% if (java.util.Calendar.getInstance().get(java.util.Calendar.HOUR_OF_DAY)<12
{%>
 Good Morning
 
<% }
 else  %>
 Good Afternoon
 
<% }
%>
 here it 
is <%= s %> .<!-s是在skeleton中已经定义好的一个String 变量.见下面代码->

[generator.skeleton]

public class  CLASS implements ICustomGeneratorInterface
 
{
/* (non-javadoc)
    * @see IGenerator#generate(Object)
    
*/

    
public String s="ok";
public
 String generate(Object argument)
   
{
     
return ""
;
   }

 }

再build project就自动生成类 GreetingExTemplate.java 其格式完全按照自定义的skeleton来.

package hello;

public class
 GreetingEXTemplate implements ICustomGeneratorInterface
 
{
  
protected static
 String nl;
  
public static
 synchronized GreetingEXTemplate create(String lineSeparator)
  
{
    nl 
=
 lineSeparator;
    GreetingEXTemplate result 
= new
 GreetingEXTemplate();
    nl 
= null
;
    
return
 result;
  }


  
protected final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
  
protected final String TEXT_1 = " Hello, "
;
  
protected final String TEXT_2 = "!" + NL + "The current time is "
;
  
protected final String TEXT_3 = "."
;
  
protected final String TEXT_4 = NL + " Good Morning"
;
  
protected final String TEXT_5 = NL + " Good Afternoon"
;
  
protected final String TEXT_6 = NL + " here it is "
;
  
protected final String TEXT_7 = "."
;
  
protected final String TEXT_8 =
 NL;

/* (non-javadoc)
    * @see IGenerator#generate(Object)
    
*/

    
public String s="ok";
public
 String generate(Object argument)
  
{
    final StringBuffer stringBuffer 
= new
 StringBuffer();
    stringBuffer.append(TEXT_1);
    stringBuffer.append(argument);
    stringBuffer.append(TEXT_2);
    stringBuffer.append((
new
 java.util.Date()).getTime());
    stringBuffer.append(TEXT_3);
     
if (java.util.Calendar.getInstance().get(java.util.Calendar.HOUR_OF_DAY)<12
{
    stringBuffer.append(TEXT_4);
     }
 else 

    stringBuffer.append(TEXT_5);
     }

    stringBuffer.append(TEXT_6);
    stringBuffer.append( s );
    stringBuffer.append(TEXT_7);
    stringBuffer.append(TEXT_8);
    
return stringBuffer.toString();
  }

}

补充:

JETNature:this nature defines two properties:

  • Template Containers - a list of folders in the project that contain the JET templates to translate.
  • Source Container - the target folder in which to save translated template implementation Java classes.

JET Builder 编译的时候才会用到这2个properties.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值