package de.ovgu.cide.mining.database;
import java.io.Serializable;
import java.util.Set;
import java.util.Stack;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import cide.gparser.ParseException;
import de.ovgu.cide.features.IFeature;
import de.ovgu.cide.features.source.SourceFileColorManager;
import de.ovgu.cide.language.jdt.ASTBridge;
import de.ovgu.cide.language.jdt.JDTParserWrapper;
import de.ovgu.cide.mining.database.model.AElement;
import de.ovgu.cide.mining.database.model.AFlyweightElementFactory;
import de.ovgu.cide.mining.database.model.AICategories;
import de.ovgu.cide.mining.database.model.ARelationKind;
import de.ovgu.cide.mining.database.recommendationengine.AElementColorManager;
/**
* @author A.Dreiling
*
*/
public class ADeclareRelationBuilder implements Serializable {
private static final long serialVersionUID = 3L;
private AbstractProgramDatabase aDB;
private AFlyweightElementFactory elementFactory;
private int cuHash;
private AElement curCUElement;
private AElement curType;
private AElement curMethod;
private int curParamIndex;
private Stack<AElement> curTypeReminder;
private AElementColorManager elementColorManager;
private SourceFileColorManager sourceColorManager;
public ADeclareRelationBuilder(AbstractProgramDatabase aDB,
AFlyweightElementFactory elementFactory) {
this.aDB = aDB;
this.elementFactory = elementFactory;
curTypeReminder = new Stack<AElement>();
curType = null;
curMethod = null;
curParamIndex = -1;
}
void traverseAST(ASTNode node) {
node.accept(new ASTVisitor() {
@Override
public boolean visit(CompilationUnit node) {
// create the CU element and store it
curCUElement = (AElement) elementFactory.createElement(
AICategories.COMPILATION_UNIT, null, cuHash, node);
addElement(curCUElement, getColor(node));
return super.visit(node);
}
private void addElement(AElement element, Set<IFeature> colors) {
aDB.addElement(element);
for (IFeature color : colors)
elementColorManager.addElementToColor(color, element);
}
private Set<IFeature> getColor(ASTNode node) {
return sourceColorManager.getColors(ASTBridge.bridge(node));
}
@Override
public boolean visit(ImportDeclaration node) {
AElement curImport = (AElement) elementFactory.createElement(
AICategories.IMPORT, null, cuHash, node);
addElement(curImport, getColor(node));
aDB.addRelationAndTranspose(curCUElement,
ARelationKind.DECLARES_IMPORT, curImport);
return super.visit(node);
}
@Override
public boolean visit(EnumDeclaration node) {
ITypeBinding binding = node.resolveBinding();
visitType(node, binding);
return super.visit(node);
}
@Override
public boolean visit(TypeDeclaration node) {
ITypeBinding binding = node.resolveBinding();
visitType(node, binding);
return super.visit(node);
}
public void visitType(ASTNode node, ITypeBinding binding) {
if (binding == null)
return;
// backup the current type
AElement oldType = curType;
curType = (AElement) elementFactory.createElement(
AICategories.TYPE, binding, cuHash, node);
addElement(curType, getColor(node));
if (!binding.isTopLevel()) {
// ADD DECLARE RELATIONSHIP FOR COMPILTATTION UNIT
aDB.addRelationAndTranspose(curCUElement,
ARelationKind.DECLARES_TYPE_TRANSITIVE, curType);
// ADD DECLARE RELATIONSHIP FOR TYPE
aDB.addRelationAndTranspose(oldType,
ARelationKind.DECLARES_TYPE, curType);
// ADD TRANSITIVE DECLARE RELATIONSHIP FOR SUPER TYPES
for (AElement remType : curTypeReminder) {
aDB
.addRelationAndTranspose(remType,
ARelationKind.DECLARES_TYPE_TRANSITIVE,
curType);
}
curTypeReminder.push(oldType);
} else {
// ADD DECLARE RELATIONSHIP FOR COMPILTATTION UNIT
aDB.addRelationAndTranspose(curCUElement,
ARelationKind.DECLARES_TYPE, curType);
}
}
@Override
public void endVisit(EnumDeclaration node) {
ITypeBinding binding = node.resolveBinding();
endVisitType(binding);
}
@Override
public void endVisit(TypeDeclaration node) {
ITypeBinding binding = node.resolveBinding();
endVisitType(binding);
}
public void endVisitType(ITypeBinding binding) {
if (binding == null)
return;
// restore current type and temp method
if (!curTypeReminder.isEmpty()) {
curType = (AElement) curTypeReminder.pop();
} else {
curType = null;
}
}
public boolean visit(MethodDeclaration node) {
IMethodBinding binding = node.resolveBinding();
if (binding != null) {
curMethod = (AElement) elementFactory.createElement(
AICategories.METHOD, binding, cuHash, node);
addElement(curMethod, getColor(node));
curParamIndex = 0;
// ADD DECLARE RELATIONSHIP FOR TYPE
aDB.addRelationAndTranspose(curType,
ARelationKind.DECLARES_METHOD, curMethod);
// ADD TRANSITIVE DECLARE RELATIONSHIP FOR COMPILTATTION
// UNIT
aDB
.addRelationAndTranspose(curCUElement,
ARelationKind.DECLARES_METHOD_TRANSITIVE,
curMethod);
// ADD TRANSITIVE DECLARE RELATIONSHIP FOR SUPER TYPES
for (AElement remType : curTypeReminder) {
aDB.addRelationAndTranspose(remType,
ARelationKind.DECLARES_METHOD_TRANSITIVE,
curMethod);
}
}
return super.visit(node);
}
@Override
public void endVisit(MethodDeclaration node) {
curMethod = null;
}
public boolean visit(VariableDeclarationFragment node) {
IVariableBinding binding = node.resolveBinding();
visitFieldOrVariable(node, binding);
return super.visit(node);
}
public boolean visit(SingleVariableDeclaration node) {
IVariableBinding binding = node.resolveBinding();
visitFieldOrVariable(node, binding);
return super.visit(node);
}
public boolean visit(EnumConstantDeclaration node) {
IVariableBinding binding = node.resolveVariable();
visitFieldOrVariable(node, binding);
return super.visit(node);
}
public void visitFieldOrVariable(ASTNode node,
IVariableBinding binding) {
if (binding == null)
return;
AElement curElement = null;
ARelationKind curRelation = null;
ARelationKind curTransitiveRelation = null;
if (binding.isField() || binding.isEnumConstant()) {
curElement = (AElement) elementFactory.createElement(
AICategories.FIELD, binding, cuHash, node);
addElement(curElement, getColor(node));
curRelation = ARelationKind.DECLARES_FIELD;
curTransitiveRelation = ARelationKind.DECLARES_FIELD_TRANSITIVE;
// ADD DECLARE RELATIONSHIP FOR TYPE
aDB.addRelationAndTranspose(curType, curRelation,
curElement);
} else {
// is "Parameter" or "Local Variable"
curElement = (AElement) elementFactory.createElement(
AICategories.LOCAL_VARIABLE, binding, cuHash, node);
if (binding.isParameter())
((AElement) curElement).setParamIndex(curParamIndex++);
addElement(curElement, getColor(node));
curRelation = ARelationKind.DECLARES_LOCAL_VARIABLE;
curTransitiveRelation = ARelationKind.DECLARES_LOCAL_VARIABLE_TRANSITIVE;
// ADD DECLARE RELATIONSHIP FOR TYPE
aDB.addRelationAndTranspose(curType, curTransitiveRelation,
curElement);
// check if null as block could also be an intializer
if (curMethod != null) {
// ADD DECLARE RELATIONSHIP FOR METHOD
aDB.addRelationAndTranspose(curMethod, curRelation,
curElement);
}
}
// ADD TRANSITIVE DECLARE RELATIONSHIP FOR COMPILTATTION UNIT
aDB.addRelationAndTranspose(curCUElement,
curTransitiveRelation, curElement);
// ADD TRANSITIVE DECLARE RELATIONSHIP FOR SUPER TYPES
for (AElement remType : curTypeReminder) {
aDB.addRelationAndTranspose(remType, curTransitiveRelation,
curElement);
}
}
});
}
public void createElementsAndDeclareRelations(ICompilationUnit cu,
int cuHash, AElementColorManager elementColorManager,
SourceFileColorManager sourceColorManager) {
this.cuHash = cuHash;
this.elementColorManager = elementColorManager;
this.sourceColorManager = sourceColorManager;
try {
CompilationUnit ast = JDTParserWrapper.parseCompilationUnit(cu);
traverseAST(ast);
} catch (ParseException e) {
e.printStackTrace();
}
}
}