package de.ovgu.cide.language.jdt; import java.io.Serializable; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ConstructorInvocation; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.InfixExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import org.eclipse.jdt.core.dom.SuperMethodInvocation; import org.eclipse.jdt.core.dom.SwitchStatement; import org.eclipse.jdt.core.dom.TryStatement; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; public class ASTID implements Serializable { private static final long serialVersionUID = 1L; public final String id; private ASTID(ASTNode node) { this.id = calculateId(node); } private ASTID(ASTNode node, boolean old) { if (old) this.id = calculateId_old(node); else this.id = calculateId(node); } // private static String convertToHex(byte[] data) { // StringBuffer buf = new StringBuffer(); // for (int i = 0; i < data.length; i++) { // int halfbyte = (data[i] >>> 4) & 0x0F; // int two_halfs = 0; // do { // if ((0 <= halfbyte) && (halfbyte <= 9)) // buf.append((char) ('0' + halfbyte)); // else // buf.append((char) ('a' + (halfbyte - 10))); // halfbyte = data[i] & 0x0F; // } while (two_halfs++ < 1); // } // return buf.toString(); // } // // public static String MD5(String text) { // try { // MessageDigest md; // md = MessageDigest.getInstance("MD5"); // byte[] md5hash = new byte[32]; // md.update(text.getBytes("iso-8859-1"), 0, text.length()); // md5hash = md.digest(); // return convertToHex(md5hash); // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // return text; // } catch (NoSuchAlgorithmException e) { // e.printStackTrace(); // return text; // } // } // private ASTID(String id) { // this.id = id; // } private static final Map<ASTNode, ASTID> cache = Collections .synchronizedMap(new WeakHashMap<ASTNode, ASTID>()); public static String id(ASTNode node) { ASTID id = cache.get(node); if (id == null) { id = new ASTID(node); cache.put(node, id); } return id.id; } public static ASTID id_old(ASTNode node) { return new ASTID(node, true); } private static String clean(String str) { str = str.replace('/', '_'); return str.replace(':', '_'); } public static String calculateId(ASTNode node) { if (node == null) return "/"; String id = calculateId(node.getParent()); if (node.getParent() instanceof Block) { Block block = (Block) node.getParent(); int idx = block.statements().indexOf(node); id += "[" + idx + "]"; } if (node.getParent() instanceof ArrayInitializer) { ArrayInitializer block = (ArrayInitializer) node.getParent(); int idx = block.expressions().indexOf(node); id += "[" + idx + "]"; } if (node.getLocationInParent() != null && node.getParent() != null) { id += ":" + node.getLocationInParent().getId(); } if (node.getParent() instanceof TryStatement) { TryStatement trystmt = (TryStatement) node.getParent(); if (trystmt.getBody() == node) id += "[body]"; } // if (node.getLocationInParent() instanceof // ChildListPropertyDescriptor) { // List children = (List) node.getParent().getStructuralProperty( // node.getLocationInParent()); // id += "[" + children.indexOf(node) + "]"; // } id += "/" + clean(node.getClass().getSimpleName()); if (node instanceof TypeDeclaration) { id += ":" + clean(((TypeDeclaration) node).getName().toString()); } if (node instanceof EnumDeclaration) { id += ":" + clean(((EnumDeclaration) node).getName().toString()); } if (node instanceof FieldDeclaration) { for (Object fragment : ((FieldDeclaration) node).fragments()) { id += ":" + clean(((VariableDeclarationFragment) fragment) .getName().toString()); } } if (node instanceof Type) { ITypeBinding b = ((Type) node).resolveBinding(); id += "::" + (b == null ? "null" : b.getQualifiedName()); } if (node instanceof VariableDeclaration) id += ":" + clean(((VariableDeclaration) node).getName().toString()); if (node instanceof EnumConstantDeclaration) id += ":" + clean(((EnumConstantDeclaration) node).getName() .toString()); if (node instanceof Name) id += ":" + clean(((Name) node).getFullyQualifiedName()); if (node instanceof ImportDeclaration) id += ":" + clean(((ImportDeclaration) node).getName().toString()); if (node instanceof MethodDeclaration) { Type rt = ((MethodDeclaration) node).getReturnType2(); id += ":" + clean(rt == null ? "void" : rt.toString()); id += ":" + clean(((MethodDeclaration) node).getName().toString()); id += ":" + clean(getParameterTypes(((MethodDeclaration) node) .parameters())); } ChildListPropertyDescriptor[] enumLists = new ChildListPropertyDescriptor[] { SwitchStatement.STATEMENTS_PROPERTY, InfixExpression.EXTENDED_OPERANDS_PROPERTY, TryStatement.CATCH_CLAUSES_PROPERTY, MethodInvocation.ARGUMENTS_PROPERTY, ConstructorInvocation.ARGUMENTS_PROPERTY, ClassInstanceCreation.ARGUMENTS_PROPERTY, SuperConstructorInvocation.ARGUMENTS_PROPERTY, SuperMethodInvocation.ARGUMENTS_PROPERTY }; for (ChildListPropertyDescriptor prop : enumLists) { if (node.getLocationInParent() == prop) { List<?> childList = (List<?>) node.getParent() .getStructuralProperty(prop); int idx = childList.indexOf(node); id += "[" + idx + "]"; } } if (node instanceof CompilationUnit) { // IJavaElement je = ((CompilationUnit) node).getJavaElement(); CompilationUnit cu = ((CompilationUnit) node); id += "["; if (cu.getPackage() != null && cu.getPackage().getName() != null) id += clean(cu.getPackage().getName().getFullyQualifiedName() + "."); if (cu.types() != null && cu.types().size() >= 1 && ((AbstractTypeDeclaration) cu.types().get(0)).getName() != null) id += ((AbstractTypeDeclaration) cu.types().get(0)).getName() .getFullyQualifiedName(); id += "]"; // id += "[" + clean(je.getPath().toPortableString()) + "]"; } return id; } private static String getParameterTypes(List<?> list) { String result = ""; for (Object p : list) { if (p instanceof SingleVariableDeclaration) { Type t = ((SingleVariableDeclaration) p).getType(); if (t != null) result += t.toString() + ";"; } } if (result.length() > 0) result = result.substring(0, result.length() - 1); return "[" + result + "]"; } public boolean equals(Object obj) { if (!(obj instanceof ASTID)) return false; ASTID otherIdentifier = ((ASTID) obj); return id.equals(otherIdentifier.id); } @Override public int hashCode() { return id.hashCode(); } public static String calculateId_old(ASTNode node) { if (node == null) return "/"; String id = calculateId(node.getParent()); if (node.getParent() instanceof Block) { Block block = (Block) node.getParent(); int idx = block.statements().indexOf(node); id += "[" + idx + "]"; } if (node.getLocationInParent() != null && node.getParent() != null) { id += ":" + node.getLocationInParent().getId(); } if (node.getParent() instanceof TryStatement) { TryStatement trystmt = (TryStatement) node.getParent(); if (trystmt.getBody() == node) id += "[body]"; } // if (node.getLocationInParent() instanceof // ChildListPropertyDescriptor) { // List children = (List) node.getParent().getStructuralProperty( // node.getLocationInParent()); // id += "[" + children.indexOf(node) + "]"; // } id += "/" + clean(node.getClass().getSimpleName()); if (node instanceof TypeDeclaration) { id += ":" + clean(((TypeDeclaration) node).getName().toString()); } if (node instanceof EnumDeclaration) { id += ":" + clean(((EnumDeclaration) node).getName().toString()); } if (node instanceof FieldDeclaration) { for (Object fragment : ((FieldDeclaration) node).fragments()) { id += ":" + clean(((VariableDeclarationFragment) fragment) .getName().toString()); } } if (node instanceof Type) { ITypeBinding b = ((Type) node).resolveBinding(); id += "::" + (b == null ? "null" : b.getQualifiedName()); } if (node instanceof VariableDeclaration) id += ":" + clean(((VariableDeclaration) node).getName().toString()); if (node instanceof EnumConstantDeclaration) id += ":" + clean(((EnumConstantDeclaration) node).getName() .toString()); if (node instanceof Name) id += ":" + clean(((Name) node).getFullyQualifiedName()); if (node instanceof ImportDeclaration) id += ":" + clean(((ImportDeclaration) node).getName().toString()); if (node instanceof MethodDeclaration) { Type rt = ((MethodDeclaration) node).getReturnType2(); id += ":" + clean(rt == null ? "void" : rt.toString()); id += ":" + clean(((MethodDeclaration) node).getName().toString()); id += ":" + clean(getParameterTypes(((MethodDeclaration) node) .parameters())); } ChildListPropertyDescriptor[] enumLists = new ChildListPropertyDescriptor[] { SwitchStatement.STATEMENTS_PROPERTY, InfixExpression.EXTENDED_OPERANDS_PROPERTY, TryStatement.CATCH_CLAUSES_PROPERTY }; for (ChildListPropertyDescriptor prop : enumLists) { if (node.getLocationInParent() == prop) { List<?> childList = (List<?>) node.getParent() .getStructuralProperty(prop); int idx = childList.indexOf(node); id += "[" + idx + "]"; } } if (node instanceof CompilationUnit) { // IJavaElement je = ((CompilationUnit) node).getJavaElement(); CompilationUnit cu = ((CompilationUnit) node); id += "["; if (cu.getPackage() != null && cu.getPackage().getName() != null) id += clean(cu.getPackage().getName().getFullyQualifiedName() + "."); if (cu.types() != null && cu.types().size() >= 1 && ((AbstractTypeDeclaration) cu.types().get(0)).getName() != null) id += ((AbstractTypeDeclaration) cu.types().get(0)).getName() .getFullyQualifiedName(); id += "]"; // id += "[" + clean(je.getPath().toPortableString()) + "]"; } return id; } }