2 * Sonar, open source software quality management tool.
3 * Copyright (C) 2008-2012 SonarSource
4 * mailto:contact AT sonarsource DOT com
6 * Sonar is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * Sonar is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Sonar; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
20 package org.sonar.java.bytecode.visitor;
22 import org.sonar.graph.DirectedGraph;
23 import org.sonar.java.bytecode.asm.AsmClass;
24 import org.sonar.java.bytecode.asm.AsmEdge;
25 import org.sonar.squid.api.SourceClass;
26 import org.sonar.squid.api.SourceCode;
27 import org.sonar.squid.api.SourceCodeEdge;
28 import org.sonar.squid.api.SourceCodeEdgeUsage;
29 import org.sonar.squid.api.SourceFile;
30 import org.sonar.squid.api.SourcePackage;
31 import org.sonar.squid.measures.Metric;
33 public class DependenciesVisitor extends BytecodeVisitor {
35 private SourceClass fromSourceClass;
36 private final DirectedGraph<SourceCode, SourceCodeEdge> graph;
38 public DependenciesVisitor(DirectedGraph<SourceCode, SourceCodeEdge> graph) {
42 public void visitClass(AsmClass asmClass) {
43 this.fromSourceClass = getSourceClass(asmClass);
46 public void visitEdge(AsmEdge edge) {
47 AsmClass toAsmClass = edge.getTargetAsmClass();
48 SourceClass toSourceClass = getSourceClass(toAsmClass);
49 switch (edge.getUsage()) {
51 link(fromSourceClass, toSourceClass, SourceCodeEdgeUsage.EXTENDS);
54 link(fromSourceClass, toSourceClass, SourceCodeEdgeUsage.IMPLEMENTS);
57 link(fromSourceClass, toSourceClass, SourceCodeEdgeUsage.USES);
62 private void link(SourceClass from, SourceClass to, SourceCodeEdgeUsage link) {
63 if (canWeLinkNodes(from, to) && graph.getEdge(from, to) == null) {
64 SourceCodeEdge edge = new SourceCodeEdge(from, to, link);
66 from.add(Metric.CE, 1);
68 SourceCodeEdge fileEdge = createEdgeBetweenParents(SourceFile.class, from, to, edge);
69 createEdgeBetweenParents(SourcePackage.class, from, to, fileEdge);
73 private SourceCodeEdge createEdgeBetweenParents(Class<? extends SourceCode> type, SourceClass from, SourceClass to,
74 SourceCodeEdge rootEdge) {
75 SourceCode fromParent = from.getParent(type);
76 SourceCode toParent = to.getParent(type);
77 SourceCodeEdge parentEdge = null;
78 if (canWeLinkNodes(fromParent, toParent) && rootEdge != null) {
79 if (graph.getEdge(fromParent, toParent) == null) {
80 parentEdge = new SourceCodeEdge(fromParent, toParent, SourceCodeEdgeUsage.USES);
81 parentEdge.addRootEdge(rootEdge);
82 graph.addEdge(parentEdge);
83 fromParent.add(Metric.CE, 1);
84 toParent.add(Metric.CA, 1);
86 parentEdge = graph.getEdge(fromParent, toParent);
87 if ( !parentEdge.hasAnEdgeFromRootNode(rootEdge.getFrom())) {
88 toParent.add(Metric.CA, 1);
90 if ( !parentEdge.hasAnEdgeToRootNode(rootEdge.getTo())) {
91 fromParent.add(Metric.CE, 1);
93 parentEdge.addRootEdge(rootEdge);
99 private boolean canWeLinkNodes(SourceCode from, SourceCode to) {
100 return from != null && to != null && !from.equals(to);