Eclipse插件开发EnumGenerator

知识准备:

IStructuredSelection
被选择对象用ISelection来表示,但是ISelection表达的内容太少,因此继承一个子接口IStructuredSelection出来,通过这个接口可以得到被选择的对象,而且支持多选。
包(非文件夹)对应IPackageFragment
.java文件对应ICompilationUnit
IJavaElement是Java工程中所有Java特有元素(包,源文件,Java工程等)的基础接口。
 
FormLayout是SWT2.0中新增加的布局管理器,在其中可以设定控件与容器以及容器与容器之间的“附着关系”,这样界面控件就会随着界面大小变化自动伸展,从而不会造成控件之间的错位。


 

IPackageFragmentRoot并不仅仅代表源文件夹,它是一组IPackageFragment的根,所以它既可以是文件夹,也可是jar,zip包。
IPackageFragment代表Java的包,但是又有区别,比如源文件平面src中的包com.sunquan.code和jar包中的com.sunquan.code的名称相同,因此它们是同一个包,但是由于这两个包在不同的IPackageFragmentRoot下,所以它们是不同的IPackageFragment。


 

在得到了其父包的IPackageFragment以后, 我们创建Java文件会很方便。只需要调用IPackageFragment的
ICompilationUnit的createCompilationUnit(String name,String contents,boolean force,IProcessMonitor monitor)方法即可。
 
在任何一个IJavaElement都可以得到当前的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引擎为我们做了这此事。

代码下载


 

 

 

 

 

 



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值