简单的说就是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()]
[JETEmitter.generate()]
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;
}
}
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.
本文介绍JET模板引擎的工作原理,包括如何将模板文件转换为Java类,以及这些类如何生成代码。涵盖JETCompiler与JETEmitter的作用,并提供实例说明。
5241

被折叠的 条评论
为什么被折叠?



