知识准备:
IJavaElement是Java工程中所有Java特有元素(包,源文件,Java工程等)的基础接口。
private IJavaProject getCurrentJavaProject()
{
if(selection!=null&&selection.isEmpty()==false&&selection instanceof IStructuredSelection)
{
IStructuredSelection ssel=(IStructuredSelection)selection;
Object obj=ssel.getFirstElement();
if(obj instanceof IJavaElement)
{
return ((IJavaElement)obj).getJavaProject();
}
}
return null;
}
开发过程:
对于newWizard的扩展点开发,所能得到的只是外界传进来的selection,所以一切操作都要基于这个selection进行。这个selection即鼠标点击对应的对象(包括包,文件夹,项目,文件等)
private void initialize() {
if (selection != null && selection.isEmpty() == false
&& selection instanceof IStructuredSelection) {
IStructuredSelection ssel = (IStructuredSelection) selection;
if (ssel.size() > 1)
return;
Object obj = ssel.getFirstElement();
if(obj instanceof IPackageFragment)
{
IPackageFragment pack=(IPackageFragment)obj;
containerText.setText(pack.getElementName());
}
else if (obj instanceof IResource) {
IContainer container;
if (obj instanceof IContainer)
container = (IContainer) obj;
else
container = ((IResource) obj).getParent();
containerText.setText(container.getFullPath().toString());
}
}
fileText.setText("*.java");
}
代码生成:
JFace对进度对话框提供了很好的支持,我们只要创建一个实现了IRunnableWithProgress接口的为的实例,把要运行的任务放到IRunnableWithProgress的run方法中即可。
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException {
try {
doFinish(pckFragment, packageName, fileName, monitor, items);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
如上所示,则会为我们创建一个新的线程,进行doFinish的操作。
调用:
try {
getContainer().run(true, false, op);
} catch (InterruptedException e) {
return false;
} catch (InvocationTargetException e) {
Throwable realException = e.getTargetException();
MessageDialog.openError(getShell(), "Error",
realException.getMessage());
return false;
}
通过run传入这个IRunnableWithProgress op对象即可。而第一个参数表示是滞要在一个独立的线程中运行,第二个表示进度对话框是否能被取消。如果能被取消,则在单击取消按钮时,会抛出InterruptedException异常。因此我们捕捉此异常并返回false,表明此次向导操作没有完成。
private void doFinish(IPackageFragment pckFragment, String packageName,
String fileName, IProgressMonitor monitor, Set<String> items) throws CoreException{
monitor.beginTask("Creating " + fileName, 2);
final ICompilationUnit cu = pckFragment.createCompilationUnit(fileName,EnumCodeGenUtils.getEnumSourceCode(packageName, fileName, items), true,
monitor);
monitor.worked(1);
monitor.setTaskName("Opening file for editing...");
getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
try {
JavaUI.openInEditor(cu);
} catch (PartInitException e) {
e.printStackTrace();
} catch (JavaModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
monitor.worked(1);
}
monitor.beginTask的第一个参数代表此任务的名称,会显示在进度对话框上,此名称可以通过setTaskName方法动态设置,第二个参数表示此工作有几步,以后随着任务的一步步完成,我们就同步地调用monitor.worked来推动滚动条的前进。
在向导完成之后,生成代码并保存到磁盘,由于保存的是java文件,只需要此文件的父源文件包对象,然后调用createCompilationUnit方法即可。
第一个参数表示的是java文件名,第二个参数表示的是java文件的内容,第三个表示文件已经存在的时候是否覆盖原有文件。
最后一步就是用Eclipse的Java文件编辑器打开生成的谁的。由于打开文件编辑器的操作在另一个线程,所以此处要采用asyncExec进行同步。
代码自动生成:
本例采用JET实现代码的生成。
步骤如下:
1把项目转化成JET项目
利用new选中如图所示,之后选中你要转化的项目,则可以进行转换。转换完成之后会在根目录下创建一个名为templates的文件夹,而且一个JET Builder,这个构建器会自动将templates文件夹的模板进行编译,生成代码。
2设置JET的生成代码文件的源路径
3创建模板文件
JET的模板文件的命名规定是在要生成的代码生成器类的文件名后加上jet(如你命名jet模板文件为hello.javajet,则会生成hello.java文件)
注意模板里有一个参数argument这个参数是表示传递给模板的参数。
<%@jet package="generatorCode" class="EnumCodeGenerator" imports="java.util.* enumgenerator.code.EnumGenArgInfo"%>
<%EnumGenArgInfo argInfo=(EnumGenArgInfo)argument;
Set<String> items=argInfo.getItems();
String className=argInfo.getClassName();
String packageName=argInfo.getPackageName();
%>
package <%=packageName%>;
public class <%=className%>
{
private String type;
<%for(String str:items)
{%>
public <%=className%> <%=str%> =new <%=className%>("<%=str%>"); <%}%>
private <%=className%>(String type)
{
super();
this.type=type;
}
}
以上为jet模板文件
package generatorCode;
import java.util.*;
import enumgenerator.code.EnumGenArgInfo;
public class EnumCodeGenerator
{
protected static String nl;
public static synchronized EnumCodeGenerator create(String lineSeparator)
{
nl = lineSeparator;
EnumCodeGenerator result = new EnumCodeGenerator();
nl = null;
return result;
}
public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
protected final String TEXT_1 = "package ";
protected final String TEXT_2 = ";" + NL + "public class ";
protected final String TEXT_3 = NL + "{" + NL + "\tprivate String type;" + NL + "\t";
protected final String TEXT_4 = " " + NL + "\tpublic ";
protected final String TEXT_5 = " ";
protected final String TEXT_6 = " =new ";
protected final String TEXT_7 = "(\"";
protected final String TEXT_8 = "\");\t";
protected final String TEXT_9 = NL + "\tprivate ";
protected final String TEXT_10 = "(String type)" + NL + "\t{" + NL + "\t\tsuper();" + NL + "\t\tthis.type=type;" + NL + "\t}" + NL + "}" + NL + "\t";
public String generate(Object argument)
{
final StringBuffer stringBuffer = new StringBuffer();
EnumGenArgInfo argInfo=(EnumGenArgInfo)argument;
Set<String> items=argInfo.getItems();
String className=argInfo.getClassName();
String packageName=argInfo.getPackageName();
stringBuffer.append(TEXT_1);
stringBuffer.append(packageName);
stringBuffer.append(TEXT_2);
stringBuffer.append(className);
stringBuffer.append(TEXT_3);
for(String str:items)
{
stringBuffer.append(TEXT_4);
stringBuffer.append(className);
stringBuffer.append(TEXT_5);
stringBuffer.append(str);
stringBuffer.append(TEXT_6);
stringBuffer.append(className);
stringBuffer.append(TEXT_7);
stringBuffer.append(str);
stringBuffer.append(TEXT_8);
}
stringBuffer.append(TEXT_9);
stringBuffer.append(className);
stringBuffer.append(TEXT_10);
return stringBuffer.toString();
}
}
以上为自动生成的代码文件,主要利用他的generator方法。
public static void main(String[] args) {
// TODO Auto-generated method stub
EnumCodeGenerator gen = new EnumCodeGenerator();
EnumGenArgInfo argInfo = new EnumGenArgInfo();
Set<String> s = new HashSet<String>();
s.add("Mon");
s.add("Tue");
argInfo.setItems(s);
argInfo.setPackageName("Day");
argInfo.setClassName("Days");
System.out.println(gen.generate(argInfo));
}
测试方法。
简单的说因为要生成的类文件里面最基本的还是一此字符串。
模板文件定义好了这此字符串,当然对于一些需要外部处理之后的信息,要通过argument参数传递。
模板生成的文件虽然是模板文件生成的,但他同时利用模板文件定义的格式,利用generator的方法(其中有一个参数)进行字符串的拼接。因为如果没有这个生成文件,我们当然也可以自定义解析模板文件的类,再拼接字符串,而jet引擎为我们做了这此事。