/*
* CCVisu is a tool for visual graph clustering
* and general force-directed graph layout.
* This file is part of CCVisu.
*
* Copyright (C) 2005-2012 Dirk Beyer
*
* CCVisu is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* CCVisu is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CCVisu; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please find the GNU Lesser General Public License in file
* license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
*
* Dirk Beyer (firstname.lastname@uni-passau.de)
* University of Passau, Bavaria, Germany
*/
package org.sosy_lab.ccvisu.readers.factextractor;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.sosy_lab.ccvisu.graph.Relation;
import com.google.common.base.Strings;
public class EclipseFactVisitor extends ASTVisitor {
private static final String RELATION_NAME_PACKAGE_REFERENCE = "refPackage";
private static final String RELATION_NAME_CLASS_REFERENCE = "refClass";
private static final String RELATION_NAME_FUNCTIONCALL = "REFfunction";
private static final String RELATION_NAME_INTERFACE_IMPLEMENTATION = "implements";
private static final String RELATION_NAME_INHERITANCE = "inheritClass";
private static final String RELATION_NAME_PACKAGE_CONTAINS = "pckgContains";
private Relation relation;
private ITypeBinding currentTypeBinding;
private MethodDeclaration currentMethod;
public void reset() {
currentTypeBinding = null;
currentMethod = null;
}
public EclipseFactVisitor(Relation relation) {
this.relation = relation;
}
@Override
public boolean visit(EnumDeclaration node) {
String sourceName = FactUtils.getEnumFullName(node);
// Add package relation
sourceName = FactUtils.getPackageName(node);
String targetName = FactUtils.getEnumFullName(node);
addRelation(RELATION_NAME_PACKAGE_CONTAINS, sourceName, targetName);
return true;
}
@Override
public boolean visit(TypeDeclaration node) {
assert node != null;
currentTypeBinding = node.resolveBinding();
// Add inheritance relation
String sourceName = FactUtils.getTypeFullName(node);
String targetName = FactUtils.getTypeFullName(node.getSuperclassType());
addRelation(RELATION_NAME_INHERITANCE, sourceName, targetName);
// Add super interfaces relations
for (Object interfaceType : node.superInterfaceTypes()) {
targetName = FactUtils.getTypeFullName((Type) interfaceType);
addRelation(RELATION_NAME_INTERFACE_IMPLEMENTATION, sourceName, targetName);
}
// Add 'pckgContains' relation
sourceName = FactUtils.getPackageName(node);
targetName = FactUtils.getTypeFullName(node);
addRelation(RELATION_NAME_PACKAGE_CONTAINS, sourceName, targetName);
return true;
}
@Override
public boolean visit(MethodDeclaration node) {
if (currentMethod != null) { return false; }
currentMethod = node;
// EclipseFactUtils.getMethodFullName(currentMethod);
// projectStructureInfo.addNodeType(pSourceName, NodeType.METHOD);
return true;
}
@Override
public void endVisit(MethodDeclaration node) {
if (currentMethod == node) {
currentMethod = null;
}
}
@Override
public void endVisit(TypeDeclaration node) {
if (currentTypeBinding == node.resolveBinding()) {
// It can happen that we have just left an inner class - to now let's take
// its declaring class as current type
currentTypeBinding = node.resolveBinding().getDeclaringClass();
}
}
@Override
public boolean visit(MethodInvocation node) {
String sourceName = null;
// First add method call
if (currentMethod != null) {
sourceName = FactUtils.getMethodFullName(currentMethod);
} else {
// It can happen to be that a method is being called outside of any method,
// e.g. from a variable initializer.
sourceName = FactUtils.getTypeFullName(currentTypeBinding);
}
String targetName = FactUtils.getMethodFullName(node);
addRelation(RELATION_NAME_FUNCTIONCALL, sourceName, targetName);
// Now add class call
if (currentMethod != null) {
sourceName = FactUtils.getTypeFullName(currentMethod);
} else {
sourceName = FactUtils.getTypeFullName(currentTypeBinding);
}
targetName = FactUtils.getTypeFullName(node);
addRelation(RELATION_NAME_CLASS_REFERENCE, sourceName, targetName);
// Add package call
if (currentMethod != null) {
sourceName = FactUtils.getPackageName(currentMethod);
} else {
sourceName = FactUtils.getPackageName(currentTypeBinding);
}
targetName = FactUtils.getPackageName(node);
addRelation(RELATION_NAME_PACKAGE_REFERENCE, sourceName, targetName);
return false;
}
private void addRelation(String relName, String sourceName,
String targetName) {
if (!Strings.isNullOrEmpty(sourceName) && !Strings.isNullOrEmpty(targetName)) {
relation.addTuple(relName, sourceName, targetName);
}
}
}