Using Xpand in Your Eclipse Wizards
Join the DZone community and get the full member experience.
Join For Freeat ese , i had a nice chat with chris (actually, i had a lot of nice chats with a lot of nice people - it was quite a challenge to attend any of the sessions), who told me that he was looking into template engines. i leave it up to you to make any assumptions on why he's interested in template engines. i happen to know at least three template engines: velocity (which i had the joy of using in my active days at andromda.org), the template, erhm, ... mechanism being used in pde (i once fixed a bug which had been caused by this engine) and - you might have guessed it - xpand (which i am a committer on).
so, i gave a short demo of xtext and xpand to show chris how easy it is to create (model-aware) code generation templates. xpand comes with a nice editor which makes template editing a joy - it features code highlighting, hyperlink navigation, model-awareness and other editor goodness.
instead of letting only chris know how that works, here's a short guide on how to write your own xpand template and use it in a wizard. to make the example more realistic, i chose to implement a wizard that creates an ant build.xml file for a simple project (something which is missing in eclipse, afaik). so, here we go.
prerequisites:
- eclipse 3.5m3 (3.4 might also do)
- emf 2.5.0m3
- emf compare 0.8.1
- mwe 0.7.0m3
- xpand 0.7.0m3
how to do it
- download and install the prerequisites.
- create a new plug-in project named "de.peterfriese.antwizard"
- add a new file wizard to the project. i used the custom plug-in wizard to get me started.
- brush up the wizard page and add some fields for project name, source folder and binary folder.
-
we want to transfer the values entered in this wizard into our template, so we need to create an ecore model that describes our data model.
- add org.eclipse.emf and org.eclipse.emf.edit to the dependencies of you plug-in.
- create a genmodel and let emf generate the model code for you.
-
add code to your wizard that transfers the values from the input fields to your model. one might consider using databinding for doing this, i used a straight forward read'n'write approach for the time being:
public boolean performfinish() { final string containername = page.getcontainername(); final string srcdirname = page.getsrcdirname(); final string bindirname = page.getbindirname(); // ... } private buildspecification createmodel(iproject project, string srcdirname, string bindirname) { buildspecification buildspecification = buildspecificationfactory.einstance.createbuildspecification(); project projectspecification = buildspecificationfactory.einstance.createproject(); projectspecification.setname(project.getname()); projectspecification.setbinaryfolder(bindirname); projectspecification.setsourcefolder(srcdirname); buildspecification.setproject(projectspecification); return buildspecification; }
-
create an xpand template
de.peterfriese.antwizard/src/template/buildtemplate.xpt
:
in case you wonder how to get those funky characters: make sure us create this file using the xpand editor - it has code assist (ctrl + space) for those characters. -
create an xtend file
de.peterfriese.antwizard/src/template/generatorextensions.ext
:
- add org.eclipse.xpand , org.eclipse.xtend and org.eclipse.xtend.typesystem.emf to the depencies of your plug-in.
-
finally, we need to provide some code to invoke the generator:
private void generate(buildspecification buildspec, iprogressmonitor monitor) throws coreexception { // get project root folder as absolute file system path iworkspaceroot root = resourcesplugin.getworkspace().getroot(); iresource resource = root.findmember(new path(buildspec.getproject().getname())); string containername = resource.getlocation().toportablestring(); // configure outlets outputimpl output = new outputimpl(); outlet outlet = new outlet(containername); outlet.setoverwrite(true); output.addoutlet(outlet); // create execution context map globalvarsmap = new hashmap(); xpandexecutioncontextimpl execctx = new xpandexecutioncontextimpl(output, null, globalvarsmap, null, null); emfregistrymetamodel metamodel = new emfregistrymetamodel() { @override protected epackage[] allpackages() { return new epackage[] { buildspecificationpackage.einstance, ecorepackage.einstance }; } }; execctx.registermetamodel(metamodel); // generate xpandfacade facade = xpandfacade.create(execctx); string templatepath = "template::buildtemplate::main"; facade.evaluate(templatepath, buildspec); // refresh the project to get external updates: resource.refreshlocal(iresource.depth_infinite, monitor); }
that's it!
taking it for a spin
- launch a runtime workbench by selecting de.peterfriese.antwizard/meta-inf/manifest.mf and invoking run as -> eclipse application
- create a new java project in the runtime workspace.
- invoke your wizard by selecting file -> new -> other... -> ant -> ant build file from existing project
- enter the required information (project name, source folder, binariy folder)
-
after clicking on
finish
, you should get a fresh ant file for your project:
- enjoy!
you can download the project here . feedback and comments are welcome!
Opinions expressed by DZone contributors are their own.
Comments