code: package gr.uom.java.ast.decomposition.matching;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.jdt.core.dom.ASTVisitor;
  import org.eclipse.jdt.core.dom.ArrayAccess;
  import org.eclipse.jdt.core.dom.ArrayCreation;
  import org.eclipse.jdt.core.dom.ArrayInitializer;
  import org.eclipse.jdt.core.dom.ArrayType;
  import org.eclipse.jdt.core.dom.Assignment;
  import org.eclipse.jdt.core.dom.BooleanLiteral;
  import org.eclipse.jdt.core.dom.CastExpression;
  import org.eclipse.jdt.core.dom.CharacterLiteral;
  import org.eclipse.jdt.core.dom.ClassInstanceCreation;
  import org.eclipse.jdt.core.dom.ConditionalExpression;
  import org.eclipse.jdt.core.dom.Expression;
  import org.eclipse.jdt.core.dom.FieldAccess;
  import org.eclipse.jdt.core.dom.IBinding;
  import org.eclipse.jdt.core.dom.ITypeBinding;
  import org.eclipse.jdt.core.dom.InfixExpression;
  import org.eclipse.jdt.core.dom.InstanceofExpression;
  import org.eclipse.jdt.core.dom.MethodInvocation;
  import org.eclipse.jdt.core.dom.Modifier;
  import org.eclipse.jdt.core.dom.NullLiteral;
  import org.eclipse.jdt.core.dom.NumberLiteral;
  import org.eclipse.jdt.core.dom.ParameterizedType;
  import org.eclipse.jdt.core.dom.ParenthesizedExpression;
  import org.eclipse.jdt.core.dom.PostfixExpression;
  import org.eclipse.jdt.core.dom.PrefixExpression;
  import org.eclipse.jdt.core.dom.PrimitiveType;
  import org.eclipse.jdt.core.dom.QualifiedName;
  import org.eclipse.jdt.core.dom.QualifiedType;
  import org.eclipse.jdt.core.dom.SimpleName;
  import org.eclipse.jdt.core.dom.SimpleType;
  import org.eclipse.jdt.core.dom.StringLiteral;
  import org.eclipse.jdt.core.dom.SuperFieldAccess;
  import org.eclipse.jdt.core.dom.SuperMethodInvocation;
  import org.eclipse.jdt.core.dom.ThisExpression;
  import org.eclipse.jdt.core.dom.Type;
  import org.eclipse.jdt.core.dom.TypeLiteral;
  import org.eclipse.jdt.core.dom.UnionType;
  import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
  import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
  import org.eclipse.jdt.core.dom.WildcardType;
  
  public class BindingSignatureVisitor extends ASTVisitor {
  	private List<String> bindingKeys = new ArrayList<String>();
  	
  	public List<String> getBindingKeys() {
  		return bindingKeys;
  	}
  
  	public boolean visit(SimpleName expr) {
  		IBinding binding = expr.resolveBinding();
  		if(binding != null) {
  			bindingKeys.add(binding.getKey());
  		}
  		else {
  			bindingKeys.add(expr.toString());
  		}
  		return false;
  	}
  	
  	public boolean visit(BooleanLiteral expr) {
  		bindingKeys.add(String.valueOf(expr.booleanValue()));
  		return false;
  	}
  	
  	public boolean visit(CharacterLiteral expr) {
  		bindingKeys.add(expr.getEscapedValue());
  		return false;
  	}
  	
  	public boolean visit(NullLiteral expr) {
  		bindingKeys.add(expr.toString());
  		return false;
  	}
  
  	public boolean visit(NumberLiteral expr) {
  		bindingKeys.add(expr.getToken());
  		return false;
  	}
  
  	public boolean visit(StringLiteral expr) {
  		bindingKeys.add(expr.getEscapedValue());
  		return false;
  	}
  
  	public boolean visit(TypeLiteral expr) {
  		String key;
  		if(expr.getType().resolveBinding() != null)
  			key = expr.getType().resolveBinding().getKey() + ".class";
  		else
  			key = expr.toString();
  		bindingKeys.add(key);
  		return false;
  	}
  
  	public boolean visit(InfixExpression expr) {
  		handleExpression(expr.getLeftOperand());
  		bindingKeys.add(expr.getOperator().toString());
  		handleExpression(expr.getRightOperand());
  		List extendedOperands = expr.extendedOperands();
  		for (int i = 0; i < extendedOperands.size(); i++){
  			bindingKeys.add(expr.getOperator().toString());
  			handleExpression((Expression) extendedOperands.get(i));
  		}
  		return false;
  	}
  
  	public boolean visit(Assignment expr) {
  		handleExpression(expr.getLeftHandSide());
  		bindingKeys.add(expr.getOperator().toString());
  		handleExpression(expr.getRightHandSide());
  		return false;
  	}
  
  	public boolean visit(PostfixExpression expr) {
  		handleExpression(expr.getOperand());
  		bindingKeys.add(expr.getOperator().toString());
  		return false;
  	}
  
  	public boolean visit(PrefixExpression expr) {
  		bindingKeys.add(expr.getOperator().toString());
  		handleExpression(expr.getOperand());
  		return false;
  	}
  
  	public boolean visit(ArrayAccess expr) {
  		handleExpression(expr.getArray());
  		handleExpression(expr.getIndex());
  		return false;
  	}
  
  	public boolean visit(ArrayCreation expr) {
  		handleType(expr.getType());
  		List dimensions = expr.dimensions();
  		for (int i = 0; i < dimensions.size(); i++) {
  			handleExpression((Expression) dimensions.get(i));
  		}
  		if(expr.getInitializer() != null) {
  			visit(expr.getInitializer());
  		}
  		return false;
  	}
  
  	public boolean visit(ArrayInitializer expr) {
  		List expressions = expr.expressions();
  		for (int i = 0; i < expressions.size(); i++) {
  			handleExpression((Expression) expressions.get(i));
  		}
  		return false;
  	}
  
  	public boolean visit(ArrayType type) {
  		handleType(type.getElementType());
  		return false;
  	}
  
  	public boolean visit(CastExpression expr) {
  		handleType(expr.getType());
  		handleExpression(expr.getExpression());
  		return false;
  	}
  
  	public boolean visit(ClassInstanceCreation expr) {
  		handleType(expr.getType());
  		handleParameters(expr.arguments());
  		return false;
  	}
  
  	public boolean visit(ConditionalExpression expr) {
  		handleExpression(expr.getExpression());
  		handleExpression(expr.getThenExpression());
  		handleExpression(expr.getElseExpression());
  		return false;
  	}
  
  	public boolean visit(FieldAccess expr) {
  		handleExpression(expr.getExpression());
  		handleExpression(expr.getName());
  		return false;
  	}
  	
  	public boolean visit(InstanceofExpression expr) {
  		handleExpression(expr.getLeftOperand());
  		handleType(expr.getRightOperand());
  		return false;
  	}
  
  	public boolean visit(MethodInvocation expr) {
  		if (expr.getExpression() != null) {
  			handleExpression(expr.getExpression());
  		}
  		handleExpression(expr.getName());
  		handleParameters(expr.arguments());
  		return false;
  	}
  
  	public boolean visit(Modifier modifier) {
  		bindingKeys.add(modifier.getKeyword().toString());
  		return false;
  	}
  
  	public boolean visit(ParameterizedType type) {
  		handleType(type.getType());
  		List typeArguments = type.typeArguments();
  		for (int i = 0; i < typeArguments.size(); i++) {
  			handleType((Type) typeArguments.get(i));
  		}
  		return false;
  	}
  
  	public boolean visit(ParenthesizedExpression expr) {
  		handleExpression(expr.getExpression());
  		return false;
  	}
  
  	public boolean visit(PrimitiveType type) {
  		bindingKeys.add(type.getPrimitiveTypeCode().toString());
  		return false;
  	}
  
  	public boolean visit(QualifiedName name) {
  		if (name.getQualifier() != null) {
  			handleExpression(name.getQualifier());
  		}
  		handleExpression(name.getName());
  		return false;
  	}
  
  	public boolean visit(QualifiedType type) {
  		handleType(type.getQualifier());
  		handleExpression(type.getName());
  		return false;
  	}
  
  	public boolean visit(SimpleType type) {
  		ITypeBinding typeBinding = type.resolveBinding();
  		if(typeBinding != null)
  			bindingKeys.add(typeBinding.getKey());
  		else
  			bindingKeys.add(type.toString());
  		return false;
  	}
  
  	public boolean visit(SuperFieldAccess expr) {
  		if (expr.getQualifier() != null) {
  			handleExpression(expr.getQualifier());
  		}
  		handleExpression(expr.getName());
  		return false;
  	}
  
  	public boolean visit(SuperMethodInvocation expr) {
  		if (expr.getQualifier() != null) {
  			handleExpression(expr.getQualifier());
  		}
  		List typeArguments = expr.typeArguments();
  		for (int i = 0; i < typeArguments.size(); i++) {
  			handleType((Type) typeArguments.get(i));
  		}
  		handleExpression(expr.getName());
  		handleParameters(expr.arguments());
  		return false;
  	}
  
  	public boolean visit(UnionType type) {
  		List types = type.types();
  		for (int i = 0; i < types.size(); i++){
  			handleType((Type) types.get(i));
  		}
  		return false;
  	}
  
  	public boolean visit(VariableDeclarationExpression expr) {
  		List modifiers = expr.modifiers();
  		for (int i = 0; i < modifiers.size(); i++) {
  			visit((Modifier) modifiers.get(i));
  		}
  		// Append Type
  		handleType(expr.getType());
  		// Visit Fragments
  		List fragments = expr.fragments();
  		for (int i = 0; i < fragments.size(); i++) {
  			visit((VariableDeclarationFragment) fragments.get(i));
  		}
  		return false;
  	}
  
  	public boolean visit(VariableDeclarationFragment expr) {
  		handleExpression(expr.getName());
  		if (expr.getInitializer() != null) {
  			handleExpression(expr.getInitializer());
  		}
  		return false;
  	}
  
  	public boolean visit(WildcardType type) {
  		if(type.getBound() != null) {
  			if (type.isUpperBound()) {
  				bindingKeys.add("extends");
  			} else {
  				bindingKeys.add("super");
  			}
  			handleType(type.getBound());
  		}
  		return false;
  	}
  
  	// Handle expressions and determine which "Visit" to visit
  	private void handleExpression(Expression expression) {
  		if (expression instanceof ArrayAccess) {
  			visit((ArrayAccess) expression);
  		} else if (expression instanceof ArrayCreation) {
  			visit((ArrayCreation) expression);
  		} else if (expression instanceof ArrayInitializer) {
  			visit((ArrayInitializer) expression);
  		} else if (expression instanceof Assignment) {
  			visit((Assignment) expression);
  		} else if (expression instanceof BooleanLiteral) {
  			visit((BooleanLiteral) expression);
  		} else if (expression instanceof CastExpression) {
  			visit((CastExpression) expression);
  		} else if (expression instanceof CharacterLiteral) {
  			visit((CharacterLiteral) expression);
  		} else if (expression instanceof ClassInstanceCreation) {
  			visit((ClassInstanceCreation) expression);
  		} else if (expression instanceof ConditionalExpression) {
  			visit((ConditionalExpression) expression);
  		} else if (expression instanceof FieldAccess) {
  			visit((FieldAccess) expression);
  		} else if (expression instanceof InfixExpression) {
  			visit((InfixExpression) expression);
  		} else if (expression instanceof InstanceofExpression) {
  			visit((InstanceofExpression) expression);
  		} else if (expression instanceof MethodInvocation) {
  			visit((MethodInvocation) expression);
  		} else if (expression instanceof NullLiteral) {
  			visit((NullLiteral) expression);
  		} else if (expression instanceof NumberLiteral) {
  			visit((NumberLiteral) expression);
  		} else if (expression instanceof ParenthesizedExpression) {
  			visit((ParenthesizedExpression) expression);
  		} else if (expression instanceof PostfixExpression) {
  			visit((PostfixExpression) expression);
  		} else if (expression instanceof PrefixExpression) {
  			visit((PrefixExpression) expression);
  		} else if ((expression instanceof QualifiedName)) {
  			visit((QualifiedName) expression);
  		} else if (expression instanceof SimpleName) {
  			visit((SimpleName) expression);
  		} else if (expression instanceof StringLiteral) {
  			visit((StringLiteral) expression);
  		} else if (expression instanceof SuperFieldAccess) {
  			visit((SuperFieldAccess) expression);
  		} else if (expression instanceof SuperMethodInvocation) {
  			visit((SuperMethodInvocation) expression);
  		} else if (expression instanceof ThisExpression) {
  			visit((ThisExpression) expression);
  		} else if (expression instanceof TypeLiteral) {
  			visit((TypeLiteral) expression);
  		} else if (expression instanceof VariableDeclarationExpression) {
  			visit((VariableDeclarationExpression) expression);
  		}
  	}
  
  	private void handleType(Type type) {
  		if (type instanceof PrimitiveType) {
  			visit((PrimitiveType) type);
  		} else if (type instanceof ArrayType) {
  			visit((ArrayType) type);
  		} else if (type instanceof SimpleType) {
  			visit((SimpleType) type);
  		} else if (type instanceof QualifiedType) {
  			visit((QualifiedType) type);
  		} else if (type instanceof ParameterizedType) {
  			visit((ParameterizedType) type);
  		} else if (type instanceof WildcardType) {
  			visit((WildcardType) type);
  		}
  	}
  
  	private void handleParameters(List args) {
  		for (int i = 0; i < args.size(); i++) {
  			handleExpression((Expression) args.get(i));
  		}
  	}
  }
  