/*******************************************************************************
* Copyright (c) 2013-2014 Red Hat, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* JBoss by Red Hat - initial API and implementation
*******************************************************************************/
package org.jboss.tools.arquillian.core.internal.dependencies;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.jboss.tools.arquillian.core.ArquillianCoreActivator;
/**
*
* @author snjeza
*
*/
public class DependencyCache {
private static Map<ICompilationUnit, Set<DependencyType>> dependencies = new HashMap<ICompilationUnit, Set<DependencyType>>();
public static Map<ICompilationUnit, Set<DependencyType>> getDependencies() {
return dependencies;
}
private static void collectDependencies(ICompilationUnit unit, boolean excludeSuperclass) {
if (unit == null || getDependencies().get(unit) != null) {
return;
}
CompilationUnit cu = getAST(unit);
IType primaryType = unit.findPrimaryType();
if (primaryType == null) {
return;
}
Set<String> excludeSet = new HashSet<String>();
String name = primaryType.getFullyQualifiedName();
if (excludeSuperclass) {
try {
ITypeHierarchy hierarchy = primaryType.newSupertypeHierarchy(null);
IType superclass = hierarchy.getSuperclass(primaryType);
if (superclass != null) {
excludeSet.add(superclass.getFullyQualifiedName());
}
IType[] superInterfaces = hierarchy.getAllSuperInterfaces(primaryType);
for (IType superInterface:superInterfaces) {
excludeSet.add(superInterface.getFullyQualifiedName());
}
} catch (JavaModelException e) {
ArquillianCoreActivator.logWarning(e.getLocalizedMessage());
}
}
DependencyVisitor visitor = new DependencyVisitor(cu, name, excludeSet, unit.getJavaProject());
cu.accept(visitor);
getDependencies().put(unit, visitor.getTypes());
IJavaProject javaProject = unit.getJavaProject();
for (DependencyType dependencyType: visitor.getTypes()) {
String typeName = dependencyType.getName();
try {
IType type = javaProject.findType(typeName);
if (type == null) {
continue;
}
ICompilationUnit compilationUnit = type.getCompilationUnit();
collectDependencies(compilationUnit, false);
} catch (JavaModelException e) {
ArquillianCoreActivator.log(e);
}
}
return;
}
public static Set<DependencyType> getDependentTypes(ICompilationUnit unit) {
Set<DependencyType> types = new HashSet<DependencyType>();
if (unit == null) {
return types;
}
IJavaProject javaProject = unit.getJavaProject();
DependencyCache.collectDependencies(unit, true);
Set<DependencyType> toVisit = new HashSet<DependencyType>();
toVisit.addAll(getDependencies().get(unit));
types.addAll(toVisit);
Set<DependencyType> visited = new HashSet<DependencyType>();
Set<DependencyType> add = new HashSet<DependencyType>();
while (!toVisit.isEmpty()) {
Iterator<DependencyType> iter = toVisit.iterator();
add.clear();
while (iter.hasNext()) {
DependencyType type = iter.next();
if (visited.contains(type)) {
iter.remove();
continue;
}
try {
IType javaType = javaProject.findType(type.getName());
if (javaType != null) {
ICompilationUnit cu = javaType.getCompilationUnit();
if (cu != null && DependencyCache.getDependencies().get(cu) != null) {
add.addAll(DependencyCache.getDependencies().get(cu));
types.addAll(DependencyCache.getDependencies().get(cu));
}
}
} catch (JavaModelException e) {
ArquillianCoreActivator.log(e);
}
visited.add(type);
}
toVisit.addAll(add);
}
return types;
}
private static CompilationUnit getAST(ICompilationUnit cu) {
ASTParser parser= ASTParser.newParser(AST.JLS8);
parser.setSource(cu);
parser.setResolveBindings(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setProject(cu.getJavaProject());
return (CompilationUnit) parser.createAST(null);
}
public static void removeDependencies(IResource resource) {
if (resource instanceof IProject) {
IProject project = (IProject) resource;
Set<ICompilationUnit> keySet = getDependencies().keySet();
Iterator<ICompilationUnit> iter = keySet.iterator();
while (iter.hasNext()) {
ICompilationUnit unit = iter.next();
if (project.equals(unit.getJavaProject().getProject())) {
iter.remove();
}
}
} else if (resource instanceof IFile) {
IFile file = (IFile) resource;
IJavaElement element = JavaCore.create(file);
if (!(element instanceof ICompilationUnit)) {
return;
}
ICompilationUnit unit = (ICompilationUnit) element;
getDependencies().remove(unit);
}
}
}