简单的说就是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("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即可.
详细来看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;
}
}result = (String)method.invoke( object , arguments);//implementation class的generate()返回的字串.再保存为一个java文件,就成为生成的最终代码.
使用JETEmitter:[JETGateWay.generate()]
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())
String content = gateway.generate(monitor);
IFile file = gateway.save(monitor, content.getBytes());
最后调用JETGateway.save()保存文件.代码生成完成.
贴个例子:一般情况,使用JETcomplier
[GreetingEx.jet]
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]
... {
/**//* (non-javadoc)
* @see IGenerator#generate(Object)
*/
public String s="ok";
public String generate(Object argument)
...{
return "";
}
}
再build project就自动生成类 GreetingExTemplate.java 其格式完全按照自定义的skeleton来.
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.