001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 021 package org.sonar.squid; 022 023 import java.util.Collection; 024 import java.util.HashSet; 025 import java.util.List; 026 import java.util.Set; 027 028 import org.picocontainer.MutablePicoContainer; 029 import org.picocontainer.containers.TransientPicoContainer; 030 import org.sonar.graph.DirectedGraph; 031 import org.sonar.graph.DirectedGraphAccessor; 032 import org.sonar.squid.api.CodeScanner; 033 import org.sonar.squid.api.CodeVisitor; 034 import org.sonar.squid.api.Query; 035 import org.sonar.squid.api.SourceCode; 036 import org.sonar.squid.api.SourceCodeEdge; 037 import org.sonar.squid.api.SourceCodeSearchEngine; 038 import org.sonar.squid.api.SourceCodeTreeDecorator; 039 import org.sonar.squid.api.SourceProject; 040 import org.sonar.squid.api.SquidConfiguration; 041 import org.sonar.squid.indexer.SquidIndex; 042 import org.sonar.squid.measures.Metric; 043 import org.sonar.squid.measures.MetricDef; 044 045 public class Squid implements DirectedGraphAccessor<SourceCode, SourceCodeEdge>, SourceCodeSearchEngine { 046 047 private MutablePicoContainer pico; 048 private SourceProject project; 049 private SquidIndex squidIndex; 050 private DirectedGraph<SourceCode, SourceCodeEdge> graph = new DirectedGraph<SourceCode, SourceCodeEdge>(); 051 private Set<CodeVisitor> externalCodeVisitors = new HashSet<CodeVisitor>(); 052 053 public Squid(SquidConfiguration conf) { 054 pico = new TransientPicoContainer(); 055 pico.addComponent(conf); 056 project = new SourceProject("Project"); 057 squidIndex = new SquidIndex(); 058 squidIndex.index(project); 059 pico.addComponent(squidIndex); 060 pico.addComponent(project); 061 pico.addComponent(graph); 062 } 063 064 public Squid() { 065 this(new SquidConfiguration()); 066 } 067 068 public void registerVisitor(CodeVisitor visitor) { 069 externalCodeVisitors.add(visitor); 070 } 071 072 public void registerVisitor(Class<? extends CodeVisitor> visitor) { 073 addToPicocontainer(visitor); 074 externalCodeVisitors.add(pico.getComponent(visitor)); 075 } 076 077 public <SCANNER extends CodeScanner> SCANNER register(Class<SCANNER> scannerClass) { 078 if(pico.getComponent(scannerClass) != null){ 079 throw new IllegalStateException("The Squid SCANNER '" + scannerClass.getName() + "' can't be registered multiple times."); 080 } 081 addToPicocontainer(scannerClass); 082 SCANNER scanner = pico.getComponent(scannerClass); 083 for (Object clazz : scanner.getVisitorClasses()) { 084 addToPicocontainer((Class) clazz); 085 scanner.accept(pico.<CodeVisitor> getComponent((Class) clazz)); 086 } 087 for (CodeVisitor externalVisitor : externalCodeVisitors) { 088 scanner.accept(externalVisitor); 089 } 090 return scanner; 091 } 092 093 /** 094 * @deprecated use {@link #decorateSourceCodeTreeWith(MetricDef...)} instead 095 */ 096 @Deprecated 097 public SourceProject aggregate() { 098 return decorateSourceCodeTreeWith(Metric.values()); 099 } 100 101 public SourceProject decorateSourceCodeTreeWith(MetricDef... metrics) { 102 SourceCodeTreeDecorator decorator = new SourceCodeTreeDecorator(project); 103 decorator.decorateWith(metrics); 104 return project; 105 } 106 107 public SourceProject getProject() { 108 return project; 109 } 110 111 private void addToPicocontainer(Class classToExpose) { 112 if (pico.getComponent(classToExpose) == null) { 113 pico.addComponent(classToExpose); 114 } 115 } 116 117 public SourceCode search(String key) { 118 return squidIndex.search(key); 119 } 120 121 public Collection<SourceCode> search(Query... query) { 122 return squidIndex.search(query); 123 } 124 125 public SourceCodeEdge getEdge(SourceCode from, SourceCode to) { 126 return graph.getEdge(from, to); 127 } 128 129 public Collection<SourceCodeEdge> getIncomingEdges(SourceCode to) { 130 return graph.getIncomingEdges(to); 131 } 132 133 public Collection<SourceCodeEdge> getOutgoingEdges(SourceCode from) { 134 return graph.getOutgoingEdges(from); 135 } 136 137 public Set<SourceCode> getVertices() { 138 return graph.getVertices(); 139 } 140 141 public List<SourceCodeEdge> getEdges(Collection<SourceCode> vertices) { 142 return graph.getEdges(vertices); 143 } 144 145 public boolean hasEdge(SourceCode from, SourceCode to) { 146 return graph.hasEdge(from, to); 147 } 148 149 public void flush() { 150 graph = null; 151 pico = null; 152 } 153 }