package org.incha.core.jswingripples.parser; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.incha.compiler.dom.JavaDomUtils; import org.incha.core.jswingripples.MethodOverrideTester; import org.incha.core.jswingripples.TypeHierarchySupport; import org.incha.core.jswingripples.eig.JSwingRipplesEIG; import org.incha.core.jswingripples.eig.JSwingRipplesEIGNode; import org.incha.ui.JSwingRipplesApplication; import org.incha.ui.TaskProgressMonitor; import org.incha.ui.util.SubProgressMonitor; class Analyzer extends Thread { private static final Log log = LogFactory.getLog(Analyzer.class); private boolean accountForPolymorphism=false; private final TaskProgressMonitor monitor; private JSwingRipplesEIG eig; public Analyzer(final JSwingRipplesEIG eig, final TaskProgressMonitor mon) { this.monitor=mon; this.eig = eig; } public void setAccountForPolymorphismMode(final boolean accountForPolymorphism) { this.accountForPolymorphism=accountForPolymorphism; } public boolean getAccountForPolymorphismMode() { return accountForPolymorphism; } @Override public void run() { try { try { final ICompilationUnit[] units = JavaDomUtils.getCompilationUnits( eig.getJavaProject(), monitor); if (units.length > 0) { //initially add all nodes for (final ICompilationUnit u : units) { final List<IJavaElement> allNodes = JavaDomUtils.getAllNodes(u); for (final IJavaElement el : allNodes) { if (el instanceof IMember) { eig.addNode((IMember) el); } } } final Map<IMethod, HashSet<IMethod>> overrides = loadMembers(units); processEdges(units, overrides); } } catch (final Exception e) { } } catch (final Exception e) { } } private Map<IMethod,HashSet <IMethod>> loadMembers(final ICompilationUnit[] units) { final Map<IMethod, HashSet<IMethod>> overridesMap = new HashMap<IMethod, HashSet<IMethod>>(); try { monitor.setTaskName("Looking for classes in the project"); final IType types[] = JavaDomUtils.getAllTypes(units); final TaskProgressMonitor typesMonitor=new SubProgressMonitor(monitor); final TypeHierarchySupport hierarchy = new TypeHierarchySupport(types); final MethodOverrideTester tester=new MethodOverrideTester(null, hierarchy); final HashSet <IMethod> overrides=new HashSet <IMethod>(); try { typesMonitor.beginTask("Populating database", types.length); for (int i = 0; i < types.length; i++) { final IType type = types[i]; if (!type.isBinary() && !(type.isMember())) { typesMonitor.setTaskName("Process class " + type.getElementName()); final IMethod[] methods=type.getMethods(); final TaskProgressMonitor tmpMonitor = new SubProgressMonitor(typesMonitor); tmpMonitor.beginTask("Process methods of " + type.getFullyQualifiedName() , methods.length); try { for (int j= 0;j < methods.length;j++) { tmpMonitor.setTaskName("Process method " + methods[j] + " of " + type.getElementName()); if (accountForPolymorphism) { if (hierarchy.getSuperclass(type) != null) { tester.setFocusType(type); tester.findAllDeclaringMethods(methods[j],true,overrides); tmpMonitor.worked(1); if (overrides.size()>0) { for (final IMethod m : overrides) { if (!overridesMap.containsKey(m)) overridesMap.put(m, new HashSet<IMethod> ()); overridesMap.get(m).add(methods[j]); } } tmpMonitor.worked(2); overrides.clear(); } } tmpMonitor.worked(j); } } finally { tmpMonitor.done(); } } if (monitor.isCanceled()) { return overridesMap; } typesMonitor.worked(i); } } finally { typesMonitor.done(); } } catch (final Exception e) { log.error(e); } return overridesMap; } private void processEdges(final ICompilationUnit[] units, final Map<IMethod, HashSet<IMethod>> overrides) { final TaskProgressMonitor subMonitor= new SubProgressMonitor(JSwingRipplesApplication.getInstance().getProgressMonitor()); try { subMonitor.beginTask("Analysing files",units.length); //---------------------- for (int i=0;i<units.length;i++) { final ICompilationUnit unit = units[i]; processEdges(unit, eig.getJavaProject().getName(), units, overrides); subMonitor.worked(i); subMonitor.setTaskName("Analyzing "+unit.getElementName()+" ("+ i +" out of "+units.length+")"); } subMonitor.done(); } catch (final Exception e) { log.error(e); } } /** * @param unit * @param projectName * @param units * @param overrides * @throws JavaModelException */ public void processEdges(final ICompilationUnit unit, final String projectName, final ICompilationUnit[] units, final Map<IMethod, HashSet<IMethod>> overrides) throws JavaModelException { if (monitor.isCanceled()) { return; } final Set<Edge> edges = EdgesCalculator.getEdges(eig.getJavaProject(), unit, units); final Iterator<Edge> iter = edges.iterator(); while (iter.hasNext()) { final Edge edge = iter.next(); final IMember mem1= edge.getFrom(); final IMember mem2= edge.getTo(); final JSwingRipplesEIGNode node1= eig.getNode(mem1); final JSwingRipplesEIGNode node2= eig.getNode(mem2); if (node1!=null && node2!=null) { eig.addEdge(node1, node2); if (accountForPolymorphism) if ((mem1 instanceof IMethod) && (mem2 instanceof IMethod)) { if (overrides.containsKey(mem2)) for (final IMethod m : overrides.get(mem2)) { eig.addEdge(node1, eig.getNode(m)); } } } } } }