package org.projectusus.metrics; import java.util.Stack; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.projectusus.core.basis.MetricsResults; import org.projectusus.core.filerelations.model.ASTNodeHelper; import org.projectusus.core.filerelations.model.BoundTypeConverter; import org.projectusus.core.filerelations.model.WrappedTypeBinding; import org.projectusus.core.metrics.MetricsCollector; public class ClassRelationsCollector extends MetricsCollector { private Stack<WrappedTypeBinding> types = new Stack<WrappedTypeBinding>(); /** * Action method, for testing purposes only! */ public void connectTypes( WrappedTypeBinding sourceType, WrappedTypeBinding targetType ) { getMetricsWriter().addClassReference( sourceType, targetType ); } /** * Action method, for testing purposes only! */ public void initRawDataTree( AbstractTypeDeclaration node ) { getMetricsWriter().putData( getFile(), node, MetricsResults.CLASS_CREATION, 0 ); } private void addCurrentType( AbstractTypeDeclaration node ) { initRawDataTree( node ); addCurrentType( new BoundTypeConverter( new ASTNodeHelper() ).wrap( node ) ); } private void addCurrentType( WrappedTypeBinding wrap ) { types.push( wrap ); } private void connectCurrentTypeAnd( WrappedTypeBinding targetType ) { if( currentType() != null && targetType != null && !currentType().equals( targetType ) ) { connectTypes( currentType(), targetType ); } } private void dropCurrentType() { if( !types.empty() ) { types.pop(); } } // these must be ignored: @Override public boolean visit( ImportDeclaration node ) { return false; } // capturing the current type: @Override public boolean visit( TypeDeclaration node ) { addCurrentType( node ); return true; } @Override public boolean visit( AnnotationTypeDeclaration node ) { addCurrentType( node ); return true; } @Override public boolean visit( EnumDeclaration node ) { addCurrentType( node ); return true; } // resetting the current type: @Override public void endVisit( TypeDeclaration node ) { dropCurrentType(); } @Override public void endVisit( AnnotationTypeDeclaration node ) { dropCurrentType(); } @Override public void endVisit( EnumDeclaration node ) { dropCurrentType(); } // referenced types @Override public boolean visit( SimpleType node ) { connectCurrentTypeAnd( new BoundTypeConverter( new ASTNodeHelper() ).wrap( node ) ); return true; } // expressions @Override public boolean visit( SimpleName node ) { if( node.isDeclaration() ) { return false; } connectCurrentTypeAnd( new BoundTypeConverter( new ASTNodeHelper() ).wrap( node ) ); return true; } @Override public boolean visit( MethodInvocation node ) { Expression targetExpression = node.getExpression(); if( targetExpression == null ) { connectCurrentTypeAnd( new BoundTypeConverter( new ASTNodeHelper() ).wrap( node ) ); } return true; } @Override public boolean visit( FieldAccess node ) { Expression targetExpression = node.getExpression(); if( targetExpression == null ) { connectCurrentTypeAnd( new BoundTypeConverter( new ASTNodeHelper() ).wrap( node ) ); } return true; } private WrappedTypeBinding currentType() { if( types.empty() ) { return null; } return types.peek(); } }