/* * Created on Dec 9, 2004 */ package fr.lifl.stc.stan.signature; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; /** * @author yann */ public class ClassHierarchy implements Serializable { static final long serialVersionUID = 0; /** * class name (key) -> super class name (value) */ private HashMap superclass; // String -> String /** * class name (key) -> array of all interfaces' names (value) */ private HashMap interfaces; // String -> String[] /** * maps the name of the class to a HashSet containing all the methods in that class, including * methods herited from superclass */ private HashMap> methods; // String -> HashSet /** * maps the name of the class to a HashSet containing the methods declared in that class (methods * herited from superclass are not contained) */ private HashMap> localMethods; //String -> HashSet private HashSet method_private; /** * */ protected ClassHierarchy() { superclass = new HashMap(); interfaces = new HashMap(); methods = new HashMap>(); localMethods = new HashMap>(); method_private = new HashSet(); } public void register(JavaClass cl) { //Printer.println("Registering class " + SignatureDictionary.key(cl.getClassName())); String name = SignatureDictionary.key(cl.getClassName()); String sclass = SignatureDictionary.key(cl.getSuperclassName()); if(!(name.equals(sclass))) superclass.put(name, sclass); String[] intf = cl.getInterfaceNames(); String [] nintf = new String[intf.length]; for(int i = 0; i < nintf.length; i++) { nintf[i] = SignatureDictionary.key(intf[i]); } interfaces.put(name,nintf); } public void registerMethods(JavaClass cl) { //Printer.println("Registering methods of class " + SignatureDictionary.key(cl.getClassName())); String name = SignatureDictionary.key(cl.getClassName()); Method[] meths = cl.getMethods(); HashSet s = methods.get(name); HashSet ls = localMethods.get(name); if(s == null) s = new HashSet(); if(ls == null) ls = new HashSet(); for(int i = 0; i < meths.length; i++) { String sign = SignatureDictionary.key(meths[i].getName() + meths[i].getSignature()); s.add(sign); ls.add(sign); if(!meths[i].isPrivate()) putRecursively(sign,name); else method_private.add(name + "." + sign); } methods.put(name,s); localMethods.put(name,ls); } public String getSuperClass(String cl) { return superclass.get(cl); } public String[] getInterfaces(String cl) { Object res = interfaces.get(cl); if(res == null) { System.err.println("Warning: " + cl + " is unknown !"); res = new String[0]; } return (String[]) res; } /** * Returns all the interfaces that precede the class cl in the class hierarchy. * * @param cl the class name of which interfaces implemented must be returned * @return */ public String[] getInterfacesClosure(String cl) { String [] direct = getInterfaces(cl); String [][] indirect = new String[direct.length][]; HashSet hash = new HashSet(); for(int i = 0; i < direct.length; i++) { hash.add(direct[i]); indirect[i] = getInterfacesClosure(direct[i]); for(int j = 0; j < indirect[i].length; j++) hash.add(indirect[i][j]); } String[] res = new String[hash.size()]; System.arraycopy(hash.toArray(),0,res,0,res.length); return res; } /** * Returns all direct subclasses of cl * @param cl * @return */ public String[] getSubClasses(String cl) { Set res = new HashSet(); Set s = superclass.keySet(); Iterator it = s.iterator(); while(it.hasNext()) { String key = it.next(); if(superclass.get(key).equals(cl)) res.add(key); } if(res.isEmpty()) return null; String[] r = new String[res.size()]; System.arraycopy(res.toArray(),0,r,0,r.length); return r; } public String[] getSubClassesClosure(String cl) { int number = 0; String[] s = getSubClasses(cl); if(s == null) return null; number += s.length; String[][] ss = new String[s.length][]; for(int i = 0; i < s.length; i++) { ss[i] = getSubClassesClosure(s[i]); if(ss[i] != null) number += ss[i].length; } String[] res = new String[number]; int index = 0; System.arraycopy(s,0,res,index,s.length); index += s.length; for(int i = 0; i < ss.length; i++) { if(ss[i] != null) { System.arraycopy(ss[i],0,res,index,ss[i].length); index += ss[i].length; } } return res; } private void putRecursively(String meth, String cl) { String[] cls = getSubClassesClosure(cl); if(cls == null) return; for(int i = 0; i < cls.length; i++) { HashSet s = methods.get(cls[i]); if(s == null) { s = new HashSet(); methods.put(cls[i],s); } s.add(meth); methods.put(cls[i],s); } } public boolean containsMethod(String cl, String meth) { HashSet s = methods.get(cl); return (s != null) && s.contains(meth); } /** * tests if the method meth was implemented in class cl. * Method will return false for a method herited from superclass. * @param cl * @param meth * @return true if meth was implemented in that class * false if meth was not implemented in that class (e.g. not defined of herited from * the superclass) */ public boolean containsLocalMethod(String cl, String meth) { HashSet s = localMethods.get(cl); return (s != null) && s.contains(meth); } public boolean isPrivate(String fq_meth) { return method_private.contains(fq_meth); } public String toString(){ String s=""; Set set = methods.keySet(); Iterator it = set.iterator(); while(it.hasNext()) { String key = it.next(); HashSet meth = methods.get(key); s+="\n\n"+key; Iterator it1 = meth.iterator(); while(it1.hasNext()){ String x = it1.next(); s+=" "+x+"\n"; } } s+="\n\n\nLocalMethods\n\n"; set = localMethods.keySet(); it = set.iterator(); while(it.hasNext()) { String key = it.next(); HashSet meth = localMethods.get(key); s += "\n\n"+key; Iterator it1 = meth.iterator(); while(it1.hasNext()){ String x = it1.next(); s+=" "+x+"\n"; } } return s; } }