简单的说就是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):
在workspace新建一个.JETEmitters project. [EclipseHelper.initialize()]
javaProject = JavaCore.create(project);
对project做好相应的准备: 设置Java Nature,class path variables. 在.JETEmitters project中将template translate成template implementation java 文件. Build the project把template implementation source code 编译成Java .class file 调用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.