I am currently working on a project that switched the UI framework from JSF2 to Wicket.
In my opinion it is a very productive decision, but I don’t want to discuss pros and cons of Web frameworks.
What I want to discuss here is the Eclipse Wicket PlugIn “qwickie“.

It is a nice plugin and it has some cool features like hyperlinking from Java to HTML wicket components and vice versa. Autocompletion and Error Highlighting.

Than I looked under the hood and saw some stuff that could be done better in my opinion. I contacted the project owner and he asked me to write down some ideas.

So hear I am :)

First of all the main concept that drives the plugin is the evaluation of wicket id.
This is made text based at this moment and in my opinion it should be structure based.

So here is an example of wicket id evaluation for wicket id in java source code.

At first we need a data structure that represents wicket id found in java code.

package qwickie.model;
import java.lang.ref.WeakReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jface.text.IRegion;
public class JavaWicketId {
	private String id;
	private IRegion idRegion;
	private WeakReference<IType> complonentType = new WeakReference<IType>(null);
	private WeakReference<IVariableBinding> representingVariable = new WeakReference<IVariableBinding>(null);
	public JavaWicketId(String id, IRegion idRegion) {
		this.id = id;
		this.idRegion = idRegion;
	public String getId() {
		return id;
	public IRegion getIdRegion() {
		return idRegion;
	public IType getComplonentType() {
		return complonentType.get();
	public void setComplonentType(IType complonentType) {
		this.complonentType = new WeakReference<IType>(complonentType);
	public void setRepresentingVariable(IVariableBinding representingVariable) {
		this.representingVariable = new WeakReference<IVariableBinding>(representingVariable);
	public IVariableBinding getRepresentingVariable() {
		return representingVariable.get();
	public String toString() {
		return "WicketId [id=" + id + ", componentType=" + getComplonentType().getFullyQualifiedName() + ", representingVariable=" + getRepresentingVariable() + ", idRegion=" + idRegion + "]";

The Class is not only hosting the id itself but also the region where it was found in the document, a type that is representing the component like for example Label and the representing variable.

Why should we care about component type and representing variable?

Well with component type we could evaluate if the component type matching the HTML tag counterpart. For example if you create a new Label with wicket id of an form tag that should be marked as error.

Representing variable is needed to evaluate the structure of tags. Lets imagine we collected all components that are created in java code. Than we can trace the add method invocation to reproduce the structure of the components – how they are nested. Than we can compare the structure to HTML counterpart and show errors if there are some.

The evaluation has to be fuzzy but it is better that runtime errors I guess :) .

Here is a simple visitor implementation for JavaWicketIdCollector:

package qwickie.util;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jface.text.Region;
import qwickie.model.JavaWicketId;
public class JavaWicketIdCollector extends ASTVisitor {
	private List<JavaWicketId> wicketIds = new ArrayList<JavaWicketId>();
	public boolean visit(ClassInstanceCreation node) {
		IMethodBinding methodBinding = node.resolveConstructorBinding();
		IMember javaElement = (IMember) methodBinding.getJavaElement();
		try {
			if (!TypeHelper.isWicketComponent(javaElement)) {
				return super.visit(node);
			JavaWicketId wicketId = getWicketId(node.arguments());
			// javaElement.getDe
			if (wicketId != null) {
		} catch (JavaModelException e) {
		return super.visit(node);
	private JavaWicketId getWicketId(List<?> arguments) {
		if (arguments.size() < 1 || !(arguments.get(0) instanceof ASTNode)) {
			return null;
		ASTNode argument = (ASTNode) arguments.get(0);
		if (argument instanceof StringLiteral) {
			StringLiteral stringLiteral = (StringLiteral) argument;
			// Region is computed only for text. Exclude ".
			Region idRegion = new Region(argument.getStartPosition() + 1, argument.getLength() - 2);
			return new JavaWicketId(stringLiteral.getLiteralValue(), idRegion);
		} else if (argument instanceof SimpleName) {
			SimpleName simpleName = (SimpleName) argument;
			IBinding resolveBinding = simpleName.resolveBinding();
			if (resolveBinding instanceof IVariableBinding) {
				Object constantValue = ((IVariableBinding) resolveBinding).getConstantValue();
				if (constantValue instanceof String) {
					Region idRegion = new Region(argument.getStartPosition(), argument.getLength());
					return new JavaWicketId((String) constantValue, idRegion);
		return null;
	private IVariableBinding computeVariableBinding(ClassInstanceCreation node) {
		IVariableBinding variableBinding = null;
		VariableDeclarationFragment variableDecl = ASTNodeHelper.getParent(node, VariableDeclarationFragment.class);
		if (variableDecl != null) {
			variableBinding = variableDecl.resolveBinding();
		Assignment assignment;
		assignment = ASTNodeHelper.getParent(node, Assignment.class);
			Expression leftHandSide = assignment.getLeftHandSide();
			if (leftHandSide instanceof SimpleName) {
				IBinding resolveBinding = ((SimpleName)leftHandSide).resolveBinding();
				if(resolveBinding instanceof IVariableBinding){
					variableBinding = (IVariableBinding)resolveBinding;
		return variableBinding;
	public List<JavaWicketId> getWicketIds() {
		return wicketIds;

The ASTNodeHelpre is an old friend from my post category “to Test or not to Test
Here is the code anyway:

package qwickie.util;
import org.eclipse.jdt.core.dom.ASTNode;
public class ASTNodeHelper {
	public static <T extends ASTNode> T getParent(ASTNode node, Class<T> parentClass) {
		ASTNode searchNode = node;
		while(searchNode.getParent() != null && !parentClass.isInstance(searchNode.getParent())){
			searchNode = searchNode.getParent();
		return (T) searchNode.getParent();

If you want to test the collector you will need something like this:

	IFile javaFile = (IFile) resource;
	final ICompilationUnit cu = JavaCore.createCompilationUnitFrom(javaFile);
	final ASTParser parser = ASTParser.newParser(AST.JLS3);
	ASTNode ast = parser.createAST(null);
	JavaWicketIdCollector collector = new JavaWicketIdCollector();
	List<JavaWicketId> wicketIds = collector.getWicketIds();

Anyway I will ping qwickie project owner about this things and maybe I will become a comitter for the project.

PS: tip for everybody who want to do static code analysis in Eclipse. JDT AST View is your friend ;)

Leave a Reply



You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Before you submit form:
Human test by Not Captcha

© 2011 Max Blog Suffusion theme by Sayontan Sinha