diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
commit | aeadc1f9129274949daaa57738c7c4550bdfbc7b (patch) | |
tree | 08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /plugins/sonar-design-plugin | |
download | sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip |
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'plugins/sonar-design-plugin')
63 files changed, 3925 insertions, 0 deletions
diff --git a/plugins/sonar-design-plugin/pom.xml b/plugins/sonar-design-plugin/pom.xml new file mode 100644 index 00000000000..9c577fbb325 --- /dev/null +++ b/plugins/sonar-design-plugin/pom.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar</artifactId> + <version>2.3-SNAPSHOT</version> + <relativePath>../..</relativePath> + </parent> + <groupId>org.codehaus.sonar.plugins</groupId> + <artifactId>sonar-design-plugin</artifactId> + <packaging>sonar-plugin</packaging> + <name>Sonar :: Plugins :: Design</name> + + <dependencies> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-core</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-plugin-api</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-gwt-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.gwt</groupId> + <artifactId>gwt-user</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.gwt</groupId> + <artifactId>gwt-incubator</artifactId> + <scope>provided</scope> + </dependency> + + <!-- unit tests --> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-testing-harness</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + + <plugins> + <plugin> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-packaging-maven-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <pluginKey>design</pluginKey> + <pluginName>Design</pluginName> + <pluginClass>org.sonar.plugins.design.DesignPlugin</pluginClass> + </configuration> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>gwt-maven-plugin</artifactId> + <executions> + <execution> + <configuration> + <modules> + <module>org.sonar.plugins.design.ui.lcom4.Lcom4Tab</module> + <module>org.sonar.plugins.design.ui.page.DesignPage</module> + <module>org.sonar.plugins.design.ui.dependencies.DependenciesTab</module> + <module>org.sonar.plugins.design.ui.libraries.LibrariesPage</module> + </modules> + <skip>${skipGwt}</skip> + <webappDirectory>${project.build.directory}/classes</webappDirectory> + + <!-- do not break on two lines --> + <extraJvmArgs>-Xmx512m -Dgwt.jjs.permutationWorkerFactory=com.google.gwt.dev.ThreadedPermutationWorkerFactory</extraJvmArgs> + </configuration> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java new file mode 100644 index 00000000000..90fe463ed82 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java @@ -0,0 +1,84 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design; + +import org.sonar.api.*; +import org.sonar.plugins.design.batch.*; +import org.sonar.plugins.design.ui.dependencies.GwtDependenciesTab; +import org.sonar.plugins.design.ui.lcom4.GwtLcom4Tab; +import org.sonar.plugins.design.ui.page.GwtDesignPage; +import org.sonar.plugins.design.ui.widgets.ChidamberKemererWidget; +import org.sonar.plugins.design.ui.widgets.FileDesignWidget; +import org.sonar.plugins.design.ui.widgets.PackageDesignWidget; +import org.sonar.plugins.design.ui.libraries.GwtLibrariesPage; + +import java.util.ArrayList; +import java.util.List; + +@Properties({ + @Property( + key = CoreProperties.DESIGN_SKIP_DESIGN_PROPERTY, + defaultValue = "" + CoreProperties.DESIGN_SKIP_DESIGN_DEFAULT_VALUE, + name = "Skip design analysis", + project = true, + global = true) +}) +public class DesignPlugin implements Plugin { + + public String getKey() { + return "design"; + } + + public String getName() { + return "Design"; + } + + public String getDescription() { + return ""; + } + + public List<Class<? extends Extension>> getExtensions() { + List<Class<? extends Extension>> extensions = new ArrayList<Class<? extends Extension>>(); + + // Batch + extensions.add(MavenDependenciesSensor.class); + extensions.add(ProjectDsmDecorator.class); + extensions.add(PackageTangleIndexDecorator.class); + extensions.add(FileTangleIndexDecorator.class); + extensions.add(OldDependenciesPurge.class); + extensions.add(SuspectLcom4DensityDecorator.class); + extensions.add(GwtLibrariesPage.class); + + // UI + extensions.add(GwtDesignPage.class); + extensions.add(GwtDependenciesTab.class); + extensions.add(FileDesignWidget.class); + extensions.add(PackageDesignWidget.class); + extensions.add(ChidamberKemererWidget.class); + extensions.add(GwtLcom4Tab.class); + + return extensions; + } + + @Override + public String toString() { + return getKey(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/DsmSerializer.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/DsmSerializer.java new file mode 100644 index 00000000000..6ce0e006e57 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/DsmSerializer.java @@ -0,0 +1,92 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.design.Dependency; +import org.sonar.api.resources.Resource; +import org.sonar.graph.Dsm; +import org.sonar.graph.DsmCell; + +public final class DsmSerializer { + + private Dsm dsm; + private StringBuilder json; + + private DsmSerializer(Dsm<Resource> dsm) { + this.dsm = dsm; + this.json = new StringBuilder(); + } + + private String serialize() { + json.append('['); + serializeRows(); + json.append(']'); + return json.toString(); + } + + private void serializeRows() { + for (int y = 0; y < dsm.getDimension(); y++) { + if (y > 0) { + json.append(','); + } + serializeRow(y); + } + } + + private void serializeRow(int y) { + Resource resource = (Resource) dsm.getVertex(y); + + json.append("{"); + if (resource != null) { + json.append("\"i\":"); + json.append(resource.getId()); + json.append(",\"n\":\""); + json.append(resource.getName()); + json.append("\",\"q\":\""); + json.append(resource.getQualifier()); + json.append("\",\"v\":["); + for (int x = 0; x < dsm.getDimension(); x++) { + if (x > 0) { + json.append(','); + } + serializeCell(y, x); + } + json.append("]"); + } + json.append("}"); + } + + private void serializeCell(int y, int x) { + DsmCell cell = dsm.getCell(x, y); + json.append('{'); + if (cell.getEdge() != null && cell.getWeight() > 0) { + Dependency dep = (Dependency) cell.getEdge(); + json.append("\"i\":"); + json.append(dep.getId()); + json.append(",\"w\":"); + json.append(cell.getWeight()); + } + json.append('}'); + } + + public static String serialize(Dsm<Resource> dsm) { + return new DsmSerializer(dsm).serialize(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/FileTangleIndexDecorator.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/FileTangleIndexDecorator.java new file mode 100644 index 00000000000..fa449e0887e --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/FileTangleIndexDecorator.java @@ -0,0 +1,34 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.measures.CoreMetrics; + +public class FileTangleIndexDecorator extends TangleIndexDecorator { + + public FileTangleIndexDecorator() { + super(CoreMetrics.FILE_TANGLES, CoreMetrics.FILE_EDGES_WEIGHT, CoreMetrics.FILE_TANGLE_INDEX); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/MavenDependenciesSensor.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/MavenDependenciesSensor.java new file mode 100644 index 00000000000..dea1bfceb7d --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/MavenDependenciesSensor.java @@ -0,0 +1,126 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; +import org.apache.maven.shared.dependency.tree.filter.AncestorOrSelfDependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.filter.DependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.filter.StateDependencyNodeFilter; +import org.apache.maven.shared.dependency.tree.traversal.BuildingDependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor; +import org.apache.maven.shared.dependency.tree.traversal.FilteringDependencyNodeVisitor; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.SonarIndex; +import org.sonar.api.design.Dependency; +import org.sonar.api.resources.Library; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.SonarException; + +public class MavenDependenciesSensor implements Sensor { + + private ArtifactRepository localRepository; + private ArtifactFactory artifactFactory; + private ArtifactMetadataSource artifactMetadataSource; + private ArtifactCollector artifactCollector; + private DependencyTreeBuilder treeBuilder; + private SonarIndex index; + + public MavenDependenciesSensor(ArtifactRepository localRepository, ArtifactFactory artifactFactory, ArtifactMetadataSource artifactMetadataSource, ArtifactCollector artifactCollector, DependencyTreeBuilder treeBuilder, SonarIndex index) { + this.localRepository = localRepository; + this.artifactFactory = artifactFactory; + this.artifactMetadataSource = artifactMetadataSource; + this.artifactCollector = artifactCollector; + this.index = index; + this.treeBuilder = treeBuilder; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void analyse(final Project project, final SensorContext context) { + try { + DependencyNode root = treeBuilder.buildDependencyTree(project.getPom(), localRepository, artifactFactory, artifactMetadataSource, null, artifactCollector); + + DependencyNodeVisitor visitor = new BuildingDependencyNodeVisitor(new DependencyNodeVisitor() { + public boolean visit(DependencyNode node) { + return true; + } + + public boolean endVisit(DependencyNode node) { + if (node.getParent() != null && node.getParent() != node) { + saveDependency(node, project, context); + } + return true; + } + }); + + // mode verbose OFF : do not show the same lib many times + DependencyNodeFilter filter = StateDependencyNodeFilter.INCLUDED; + + CollectingDependencyNodeVisitor collectingVisitor = new CollectingDependencyNodeVisitor(); + DependencyNodeVisitor firstPassVisitor = new FilteringDependencyNodeVisitor(collectingVisitor, filter); + root.accept(firstPassVisitor); + + DependencyNodeFilter secondPassFilter = new AncestorOrSelfDependencyNodeFilter(collectingVisitor.getNodes()); + visitor = new FilteringDependencyNodeVisitor(visitor, secondPassFilter); + + root.accept(visitor); + + } catch (DependencyTreeBuilderException e) { + throw new SonarException("Can not load the graph of dependencies of the project " + project.getKey(), e); + } + } + + protected void saveDependency(DependencyNode node, Project project, SensorContext context) { + Resource from = (node.getParent().getParent()==null) ? index.getProject() : toResource(node.getParent().getArtifact(), context); + Resource to = toResource(node.getArtifact(), context); + Dependency dependency = new Dependency(from, to); + dependency.setUsage(node.getArtifact().getScope()); + dependency.setWeight(1); + context.saveDependency(dependency); + } + + protected static Resource toResource(Artifact artifact, SensorContext context) { + Project project = Project.createFromMavenIds(artifact.getGroupId(), artifact.getArtifactId()); + Resource result = context.getResource(project); + if (result == null || !((Project) result).getAnalysisVersion().equals(artifact.getBaseVersion())) { + Library lib = new Library(project.getKey(), artifact.getBaseVersion()); + context.saveResource(lib); + result = context.getResource(lib); + } + return result; + } + + @Override + public String toString() { + return "Maven dependencies"; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/OldDependenciesPurge.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/OldDependenciesPurge.java new file mode 100644 index 00000000000..2a17e576721 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/OldDependenciesPurge.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.batch.PurgeContext; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.design.DependencyDto; +import org.sonar.core.purge.AbstractPurge; + +import javax.persistence.Query; +import java.util.List; + +public class OldDependenciesPurge extends AbstractPurge { + + public OldDependenciesPurge(DatabaseSession session) { + super(session); + } + + public void purge(PurgeContext context) { + Query query = getSession().createQuery("SELECT d.projectSnapshotId FROM " + DependencyDto.class.getSimpleName() + + " d WHERE NOT EXISTS(FROM " + Snapshot.class.getSimpleName() + " s WHERE s.id=d.projectSnapshotId AND s.last=:last)"); + query.setParameter("last", true); + final List<Integer> projectSnapshotIds = query.getResultList(); + executeQuery(projectSnapshotIds, "DELETE FROM " + DependencyDto.class.getSimpleName() + " WHERE projectSnapshotId in (:ids)"); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/PackageTangleIndexDecorator.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/PackageTangleIndexDecorator.java new file mode 100644 index 00000000000..fa4e440fbe5 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/PackageTangleIndexDecorator.java @@ -0,0 +1,34 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.measures.CoreMetrics; + +public class PackageTangleIndexDecorator extends TangleIndexDecorator { + + public PackageTangleIndexDecorator() { + super(CoreMetrics.PACKAGE_TANGLES, CoreMetrics.PACKAGE_EDGES_WEIGHT, CoreMetrics.PACKAGE_TANGLE_INDEX); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/ProjectDsmDecorator.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/ProjectDsmDecorator.java new file mode 100644 index 00000000000..0f040a975a4 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/ProjectDsmDecorator.java @@ -0,0 +1,103 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import com.google.common.collect.Lists; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.SonarIndex; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.graph.*; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * For performance reasons, this decorator is currently limited to matrix between modules. + * Squid is optimized for cycle detections (better hashCode and equals methods of SourceCode classes than Resource). + */ +public class ProjectDsmDecorator implements Decorator { + + // hack as long as DecoratorContext does not implement SonarIndex + private SonarIndex index; + + public ProjectDsmDecorator(SonarIndex index) { + this.index = index; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void decorate(final Resource resource, DecoratorContext context) { + if (shouldDecorateResource(resource, context)) { + Collection<Resource> subProjects = getSubProjects((Project) resource); + + if (!subProjects.isEmpty()) { + Dsm<Resource> dsm = getDsm(subProjects); + saveDsm(context, dsm); + } + } + } + + private void saveDsm(DecoratorContext context, Dsm<Resource> dsm) { + context.saveMeasure(new Measure(CoreMetrics.DEPENDENCY_MATRIX, DsmSerializer.serialize(dsm))); + } + + private Dsm<Resource> getDsm(Collection<Resource> subProjects) { + CycleDetector<Resource> cycleDetector = new CycleDetector<Resource>(index, subProjects); + Set<Cycle> cycles = cycleDetector.getCycles(); + + MinimumFeedbackEdgeSetSolver solver = new MinimumFeedbackEdgeSetSolver(cycles); + Set<Edge> feedbackEdges = solver.getEdges(); + + Dsm<Resource> dsm = new Dsm<Resource>(index, subProjects, feedbackEdges); + DsmTopologicalSorter.sort(dsm); + return dsm; + } + + /** + * sub-projects, including all descendants but not only direct children + */ + private Collection<Resource> getSubProjects(final Project project) { + List<Resource> subProjects = Lists.newArrayList(); + addSubProjects(project, subProjects); + return subProjects; + } + + private void addSubProjects(Project project, List<Resource> subProjects) { + for (Project subProject : project.getModules()) { + Project indexedSubProject = (Project) index.getResource(subProject); + if (indexedSubProject != null) { + subProjects.add(indexedSubProject); + } + addSubProjects(subProject, subProjects); + } + } + + private boolean shouldDecorateResource(Resource resource, DecoratorContext context) { + return ResourceUtils.isProject(resource) && context.getMeasure(CoreMetrics.DEPENDENCY_MATRIX) == null; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecorator.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecorator.java new file mode 100644 index 00000000000..35370a02d2f --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecorator.java @@ -0,0 +1,90 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; + +import java.util.Collection; +import java.util.List; + +public class SuspectLcom4DensityDecorator implements Decorator { + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public final Metric generatesMetric() { + return CoreMetrics.SUSPECT_LCOM4_DENSITY; + } + + public void decorate(Resource resource, DecoratorContext context) { + if (ResourceUtils.isFile(resource)) { + // do nothing + } else if (ResourceUtils.isDirectory(resource)) { + decorateDirectory(context); + + } else { + decorateProject(context); + } + } + + private void decorateProject(DecoratorContext context) { + double total = 0.0; + int totalFiles = 0; + + List<DecoratorContext> children = context.getChildren(); + for (DecoratorContext child : children) { + int files = MeasureUtils.getValue(child.getMeasure(CoreMetrics.FILES), 0.0).intValue(); + totalFiles += files; + total += MeasureUtils.getValue(child.getMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY), 0.0) * files; + } + + if (totalFiles > 0) { + context.saveMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY, (total / totalFiles)); + } + } + + private void decorateDirectory(DecoratorContext context) { + double files = MeasureUtils.getValue(context.getMeasure(CoreMetrics.FILES), 0.0); + if (files > 0.0) { + double suspectFiles = 0.0; + + // directory children are files + Collection<Measure> fileLcoms = context.getChildrenMeasures(CoreMetrics.LCOM4); + for (Measure fileLcom : fileLcoms) { + if (MeasureUtils.getValue(fileLcom, 0.0) > 1.0) { + suspectFiles++; + } + } + double density = (suspectFiles / files) * 100.0; + context.saveMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY, density); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/TangleIndexDecorator.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/TangleIndexDecorator.java new file mode 100644 index 00000000000..703bd6334ad --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/TangleIndexDecorator.java @@ -0,0 +1,91 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +import java.util.Arrays; +import java.util.List; + +public abstract class TangleIndexDecorator implements Decorator { + + private Metric tanglesMetric; + private Metric edgesWeightMetric; + private Metric tangleIndexMetric; + + protected TangleIndexDecorator(Metric tanglesMetric, Metric edgesWeightMetric, Metric tangleIndexMetric) { + this.tanglesMetric = tanglesMetric; + this.edgesWeightMetric = edgesWeightMetric; + this.tangleIndexMetric = tangleIndexMetric; + } + + @DependsUpon + public final List<Metric> dependsUponMetrics() { + return Arrays.asList(tanglesMetric, edgesWeightMetric); + } + + /** + * Used to define downstream dependencies + */ + @DependedUpon + public final Metric generatesMetric() { + return tangleIndexMetric; + } + + public final boolean shouldExecuteOnProject(Project project) { + return true; + } + + /** + * {@inheritDoc} + */ + public final void decorate(Resource resource, DecoratorContext context) { + if (!shouldDecorateResource(context)) { + return; + } + Measure tangles = context.getMeasure(tanglesMetric); + Measure totalweight = context.getMeasure(edgesWeightMetric); + + if (MeasureUtils.hasValue(totalweight)) { + context.saveMeasure(new Measure(tangleIndexMetric, compute(MeasureUtils.getValue(tangles, 0.0), totalweight.getValue()))); + } + } + + private boolean shouldDecorateResource(DecoratorContext context) { + return context.getMeasure(tangleIndexMetric) == null; + } + + + private double compute(double tangles, double totalWeight) { + if (totalWeight==0.0) { + return 0.0; + } + double result = 2 * tangles / totalWeight; + return result * 100; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/GwtDependenciesTab.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/GwtDependenciesTab.java new file mode 100644 index 00000000000..f49bffdae1b --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/GwtDependenciesTab.java @@ -0,0 +1,45 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Java; + +import org.sonar.api.resources.Resource; +import org.sonar.api.web.*; +import org.sonar.plugins.design.ui.dependencies.client.DependenciesTab; + +@ResourceLanguage({Java.KEY, "web"}) // 'web' is a temporary workaround. See http://sonar-dev.787459.n3.nabble.com/sonar-dev-Dependencies-in-Web-Plugin-td822980.html#a822980 +@ResourceQualifier({Resource.QUALIFIER_FILE, Resource.QUALIFIER_CLASS, Resource.QUALIFIER_PACKAGE, Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE}) +@DefaultTab(metrics={CoreMetrics.AFFERENT_COUPLINGS_KEY, CoreMetrics.EFFERENT_COUPLINGS_KEY}) +@NavigationSection({NavigationSection.RESOURCE_TAB}) +@UserRole(UserRole.USER) +public class GwtDependenciesTab extends GwtPage { + + public String getTitle() { + return "Dependencies"; + } + + public String getGwtId() { + return DependenciesTab.GWT_ID; + } +} + + diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Data.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Data.java new file mode 100644 index 00000000000..2d457de0347 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Data.java @@ -0,0 +1,64 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies.client; + +import org.sonar.wsclient.services.Dependency; +import org.sonar.wsclient.services.Resource; + +import java.util.List; + +public class Data { + + private long resourceId; + private List<Dependency> dependencies = null; + private Resource resource = null; + + public Data(long resourceId) { + this.resourceId = resourceId; + } + + public long getResourceId() { + return resourceId; + } + + public boolean isLoaded() { + return dependencies!=null && resource!=null; + } + + public boolean canDisplay() { + return resource.getMeasure("ca")!=null && resource.getMeasure("ce")!=null; + } + + public List<Dependency> getDependencies() { + return dependencies; + } + + public void setDependencies(List<Dependency> dependencies) { + this.dependencies = dependencies; + } + + public Resource getResource() { + return resource; + } + + public void setMeasures(Resource resource) { + this.resource = resource; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTab.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTab.java new file mode 100644 index 00000000000..3e3541f0589 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTab.java @@ -0,0 +1,98 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies.client; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Widget; +import org.sonar.gwt.Metrics; +import org.sonar.gwt.ui.Loading; +import org.sonar.gwt.ui.Page; +import org.sonar.wsclient.gwt.AbstractCallback; +import org.sonar.wsclient.gwt.AbstractListCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.Dependency; +import org.sonar.wsclient.services.DependencyQuery; +import org.sonar.wsclient.services.Resource; +import org.sonar.wsclient.services.ResourceQuery; + +import java.util.List; + +public class DependenciesTab extends Page { + public static final String GWT_ID = "org.sonar.plugins.design.ui.dependencies.DependenciesTab"; + + private FlowPanel panel = null; + private DependenciesTable dependenciesTable = null; + private Loading loading; + + @Override + protected Widget doOnResourceLoad(Resource resource) { + prepare(); + Data data = new Data(resource.getId()); + loadMeasures(data); + loadDependencies(data); + return panel; + } + + private void prepare() { + if (panel == null) { + panel = new FlowPanel(); + panel.getElement().setId("deps"); + loading = new Loading(); + dependenciesTable = new DependenciesTable(); + panel.setWidth("100%"); + } + panel.clear(); + panel.add(loading); + } + + private void loadMeasures(final Data data) { + ResourceQuery query = new ResourceQuery(data.getResourceId()); + query.setMetrics(Metrics.EFFERENT_COUPLINGS, Metrics.AFFERENT_COUPLINGS); + query.setVerbose(true); + Sonar.getInstance().find(query, new AbstractCallback<org.sonar.wsclient.services.Resource>() { + @Override + protected void doOnResponse(org.sonar.wsclient.services.Resource resource) { + data.setMeasures(resource); + displayMeasures(data); + } + }); + } + + private void loadDependencies(final Data data) { + DependencyQuery query = DependencyQuery.createForResource(data.getResourceId()); + Sonar.getInstance().findAll(query, new AbstractListCallback<Dependency>() { + + @Override + protected void doOnResponse(List<Dependency> dependencies) { + data.setDependencies(dependencies); + displayMeasures(data); + } + }); + } + + + private void displayMeasures(Data data) { + if (data.isLoaded()) { + panel.clear(); + dependenciesTable.display(data); + panel.add(dependenciesTable); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTable.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTable.java new file mode 100644 index 00000000000..9faa122e7e7 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/DependenciesTable.java @@ -0,0 +1,97 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies.client; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.*; +import org.sonar.gwt.Links; +import org.sonar.gwt.ui.Icons; +import org.sonar.wsclient.services.Dependency; + +public class DependenciesTable extends Composite { + + private HorizontalPanel panel; + + public DependenciesTable() { + panel = new HorizontalPanel(); + panel.setStylePrimaryName("dependencies"); + initWidget(panel); + } + + + public void display(final Data data) { + panel.clear(); + if (data.canDisplay()) { + panel.add(createIncomingColumn(data)); + panel.add(createOutgoingColumn(data)); + } else { + panel.add(new Label(I18nConstants.INSTANCE.noData())); + } + } + + + private Panel createIncomingColumn(Data data) { + FlexTable grid = new FlexTable(); + grid.setStyleName("col"); + grid.setWidget(0, 1, new HTML("<b>" + I18nConstants.INSTANCE.afferentCouplings() + "</b>: " + data.getResource().getMeasureIntValue("ca"))); + grid.getRowFormatter().setStyleName(0, "coltitle"); + + int row = 1; + for (Dependency dependency : data.getDependencies()) { + if (data.getResourceId()==dependency.getToId()) { + addDependencyRow(grid, row, dependency.getFromId(), dependency.getFromName() + " (" + dependency.getWeight() + ")"); + grid.setWidget(row, 0, Icons.forQualifier(dependency.getFromQualifier()).createImage()); + row++; + } + } + + return grid; + } + + private Panel createOutgoingColumn(Data data) { + FlexTable grid = new FlexTable(); + grid.setStyleName("col"); + grid.setWidget(0, 1, new HTML("<b>" + I18nConstants.INSTANCE.efferentCouplings() + "</b>: " + data.getResource().getMeasureIntValue("ce"))); + grid.getRowFormatter().setStyleName(0, "coltitle"); + + int row = 1; + for (Dependency dependency : data.getDependencies()) { + if (data.getResourceId()==dependency.getFromId()) { + addDependencyRow(grid, row, dependency.getToId(), dependency.getToName() + " (" + dependency.getWeight() + ")"); + grid.setWidget(row, 0, Icons.forQualifier(dependency.getToQualifier()).createImage()); + row++; + } + } + + return grid; + } + + private void addDependencyRow(final FlexTable grid, final int row, final long resourceId, final String name) { + Label link = new Label(name); + link.setStyleName("link"); + link.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent clickEvent) { + Links.openResourcePopup(String.valueOf(resourceId)); + } + }); + grid.setWidget(row, 1, link); + } +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Header.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Header.java new file mode 100644 index 00000000000..8de67b00dc6 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/Header.java @@ -0,0 +1,75 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies.client; + +import com.google.gwt.user.client.ui.*; +import org.sonar.wsclient.services.Measure; +import org.sonar.wsclient.services.Resource; + +public class Header extends Composite { + private FlowPanel header; + + public Header() { + header = new FlowPanel(); + header.setStyleName("gwt-ViewerHeader"); + initWidget(header); + } + + private void addMeasure(Panel panel, Resource resource, String key, String label) { + Measure measure = resource.getMeasure(key); + if (measure != null) { + HTML html = new HTML(label + ": "); + html.setStyleName("metric"); + panel.add(html); + + html = new HTML(measure.getFormattedValue("-")); + html.setStyleName("value"); + panel.add(html); + } + } + + public void display(Data data) { + header.clear(); + HorizontalPanel panel = new HorizontalPanel(); + header.add(panel); + addMeasure(panel, data.getResource(), "classes", I18nConstants.INSTANCE.classes()); + addMeasure(panel, data.getResource(), "dit", I18nConstants.INSTANCE.dit()); + addMeasure(panel, data.getResource(), "noc", I18nConstants.INSTANCE.noc()); + addMeasure(panel, data.getResource(), "rfc", I18nConstants.INSTANCE.rfc()); + addLcom4(data, panel); + } + + private void addLcom4(Data data, HorizontalPanel panel) { + Measure lcom4 = data.getResource().getMeasure("lcom4"); + if (lcom4 != null && lcom4.getIntValue()!=null) { + HTML html = new HTML(I18nConstants.INSTANCE.lcom4() + ": "); + html.setStyleName("metric"); + panel.add(html); + + html = new HTML(lcom4.getIntValue() + ""); + html.setStyleName("value"); + if (lcom4.getIntValue()>1) { + html.addStyleName("red bold"); + } + + panel.add(html); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/I18nConstants.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/I18nConstants.java new file mode 100644 index 00000000000..a90e4fbfde5 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/dependencies/client/I18nConstants.java @@ -0,0 +1,52 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.dependencies.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.Constants; + +public interface I18nConstants extends com.google.gwt.i18n.client.Constants { + + static I18nConstants INSTANCE = GWT.create(I18nConstants.class); + + @DefaultStringValue("Afferent (incoming) couplings") + String afferentCouplings(); + + @DefaultStringValue("Efferent (outgoing) couplings") + String efferentCouplings(); + + @DefaultStringValue("Classes") + String classes(); + + @DefaultStringValue("Depth in Tree") + String dit(); + + @DefaultStringValue("Number of Children") + String noc(); + + @Constants.DefaultStringValue("Response for Class") + String rfc(); + + @DefaultStringValue("Lack of Cohesion of Methods") + String lcom4(); + + @DefaultStringValue("No data") + String noData(); +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/GwtLcom4Tab.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/GwtLcom4Tab.java new file mode 100644 index 00000000000..d4bee638d28 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/GwtLcom4Tab.java @@ -0,0 +1,42 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.lcom4; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Resource; +import org.sonar.api.web.*; +import org.sonar.plugins.design.ui.lcom4.client.Lcom4Tab; + +@ResourceLanguage(Java.KEY) +@ResourceQualifier({Resource.QUALIFIER_CLASS}) +@DefaultTab(metrics = {CoreMetrics.LCOM4_KEY}) +@NavigationSection({NavigationSection.RESOURCE_TAB}) +@UserRole(UserRole.CODEVIEWER) +public class GwtLcom4Tab extends GwtPage { + + public String getTitle() { + return "LCOM4"; + } + + public String getGwtId() { + return Lcom4Tab.GWT_ID; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Data.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Data.java new file mode 100644 index 00000000000..3f34d7400fe --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Data.java @@ -0,0 +1,52 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.lcom4.client; + +import com.google.gwt.core.client.JavaScriptObject; + +public final class Data { + + public static class Entity extends JavaScriptObject { + // Overlay types always have protected, zero-arg ctors + protected Entity() { + } + + public final native String getName() /*-{ return this.n; }-*/; + public final native String getQualifier() /*-{ return this.q; }-*/; + } + + public static class Block extends JavaScriptObject { + protected Block() { + } + public final native int size() /*-{ return this.length; }-*/; + public final native Entity get(int i) /*-{ return this[i]; }-*/; + } + + public static class Blocks extends JavaScriptObject { + protected Blocks() { + } + public final native int size() /*-{ return this.length; }-*/; + public final native Block get(int i) /*-{ return this[i]; }-*/; + } + + public static native Blocks parse(String json) /*-{ + return eval('(' + json + ')') + }-*/; +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Lcom4Tab.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Lcom4Tab.java new file mode 100644 index 00000000000..ee7a2f4292b --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/lcom4/client/Lcom4Tab.java @@ -0,0 +1,104 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.lcom4.client; + +import com.google.gwt.user.client.ui.*; +import org.sonar.gwt.ui.Icons; +import org.sonar.gwt.ui.Loading; +import org.sonar.gwt.ui.Page; +import org.sonar.wsclient.gwt.AbstractCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.Resource; +import org.sonar.wsclient.services.ResourceQuery; + +public class Lcom4Tab extends Page { + public static final String GWT_ID = "org.sonar.plugins.design.ui.lcom4.Lcom4Tab"; + + private VerticalPanel panel; + + @Override + protected Widget doOnResourceLoad(Resource resource) { + panel = new VerticalPanel(); + panel.setWidth("100%"); + loadData(resource); + return panel; + } + + private void loadData(Resource resource) { + panel.add(new Loading()); + ResourceQuery query = ResourceQuery.createForMetrics(resource.getId().toString(), "lcom4", "lcom4_blocks"); + Sonar.getInstance().find(query, new AbstractCallback<Resource>() { + @Override + protected void doOnResponse(Resource resource) { + panel.clear(); + panel.add(new Header(resource)); + if (resource != null && resource.getMeasure("lcom4_blocks") != null) { + String json = resource.getMeasure("lcom4_blocks").getData(); + Data.Blocks blocks = Data.parse(json); + + Grid grid = new Grid(blocks.size(), 2); + grid.setStyleName("lcom4blocks"); + grid.getColumnFormatter().setStyleName(0, "index"); + + for (int indexBlock = 0; indexBlock < blocks.size(); indexBlock++) { + Data.Block block = blocks.get(indexBlock); + grid.setHTML(indexBlock, 0, "<div class='index'>" + (indexBlock + 1) + "</div>"); + + VerticalPanel blockPanel = new VerticalPanel(); + blockPanel.setStyleName("lcom4block"); + + for (int indexEntity = 0; indexEntity < block.size(); indexEntity++) { + Data.Entity entity = block.get(indexEntity); + HTML row = new HTML(Icons.forQualifier(entity.getQualifier()).getHTML() + " " + entity.getName()); + row.setStyleName("lcom4row"); + blockPanel.add(row); + } + grid.setWidget(indexBlock, 1, blockPanel); + + } + panel.add(grid); + } + } + }); + } + + private static class Header extends Composite { + private FlowPanel header; + + public Header(Resource resource) { + header = new FlowPanel(); + header.setStyleName("gwt-ViewerHeader"); + + HorizontalPanel panel = new HorizontalPanel(); + HTML html = new HTML("Lack of Cohesion of Methods: "); + html.setStyleName("metric"); + panel.add(html); + + if (resource != null) { + html = new HTML(resource.getMeasureFormattedValue("lcom4", "-")); + html.setStyleName("value"); + panel.add(html); + } + + header.add(panel); + initWidget(header); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/GwtLibrariesPage.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/GwtLibrariesPage.java new file mode 100644 index 00000000000..32d54114a8d --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/GwtLibrariesPage.java @@ -0,0 +1,41 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries; + +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Resource; +import org.sonar.api.web.*; +import org.sonar.plugins.design.ui.libraries.client.LibrariesPage; + +@ResourceLanguage(Java.KEY) +@ResourceQualifier({Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE}) +@NavigationSection(NavigationSection.RESOURCE) +@UserRole(UserRole.USER) +public class GwtLibrariesPage extends GwtPage { + + public String getTitle() { + return "Libraries"; + } + + public String getGwtId() { + return LibrariesPage.GWT_ID; + } +} + diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Filters.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Filters.java new file mode 100644 index 00000000000..31f7888c04e --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Filters.java @@ -0,0 +1,116 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Label; +import org.sonar.gwt.Configuration; +import org.sonar.gwt.Links; +import org.sonar.wsclient.services.Resource; + +public class Filters extends Grid { + + private static final String PARAM_TEST = "test"; + + private KeywordFilter keywordFilter; + private CheckBox testCheckbox; + private Anchor expandCollapse; + private boolean isExpanded; + private Anchor usageLink; + + + public Filters(Resource resource) { + super(1, 5); + + setStyleName("libFilter"); + + keywordFilter = new KeywordFilter(); + setWidget(0, 0, new Label(I18nConstants.INSTANCE.filter())); + setWidget(0, 1, keywordFilter); + + testCheckbox = new CheckBox(I18nConstants.INSTANCE.displayTests()); + testCheckbox.getElement().setId("testCb"); + testCheckbox.setValue(Boolean.valueOf(Configuration.getRequestParameter(PARAM_TEST, "false"))); + setWidget(0, 2, testCheckbox); + + expandCollapse = new Anchor(I18nConstants.INSTANCE.collapse()); + isExpanded = true; + setWidget(0, 3, expandCollapse); + + usageLink = new Anchor(I18nConstants.INSTANCE.usageLink(), Links.baseUrl() + "/dependencies/index?search=" + resource.getKey()); + setWidget(0, 4, usageLink); + } + + public KeywordFilter getKeywordFilter() { + return keywordFilter; + } + + public CheckBox getTestCheckbox() { + return testCheckbox; + } + + public boolean isTestDisplayed() { + return testCheckbox.getValue(); + } + + public boolean isTestFiltered() { + return !isTestDisplayed(); + } + + public boolean hasKeyword() { + return getKeywordFilter().hasKeyword(); + } + + public Anchor getExpandCollapseLink() { + return expandCollapse; + } + + public boolean isExpanded() { + return isExpanded; + } + + public boolean isCollapsed() { + return !isExpanded; + } + + public Anchor getUsageLink() { + return usageLink; + } + + public void expand() { + if (!isExpanded) { + expandCollapse.setText(I18nConstants.INSTANCE.collapse()); + isExpanded = true; + } + } + + public void collapse() { + if (isExpanded) { + expandCollapse.setText(I18nConstants.INSTANCE.expand()); + isExpanded = false; + } + } + + public String toUrlParams() { + return PARAM_TEST + '=' + testCheckbox.getValue() + '&' + KeywordFilter.PARAM_FILTER + '=' + getKeywordFilter(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/I18nConstants.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/I18nConstants.java new file mode 100644 index 00000000000..496fb44a656 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/I18nConstants.java @@ -0,0 +1,45 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.core.client.GWT; + +public interface I18nConstants extends com.google.gwt.i18n.client.Constants { + + static I18nConstants INSTANCE = GWT.create(I18nConstants.class); + + @DefaultStringValue("Filter:") + String filter(); + + @DefaultStringValue("Display test libraries") + String displayTests(); + + @DefaultStringValue("Expand all") + String expand(); + + @DefaultStringValue("Collapse all") + String collapse(); + + @DefaultStringValue("No libraries") + String noLibraries(); + + @DefaultStringValue("Usages") + String usageLink(); +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/KeywordFilter.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/KeywordFilter.java new file mode 100644 index 00000000000..d162a4340e3 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/KeywordFilter.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.user.client.ui.TextBox; +import org.sonar.gwt.Configuration; + +public class KeywordFilter extends TextBox { + public static final String PARAM_FILTER = "filter"; + + public KeywordFilter() { + getElement().setId("keywordFilter"); + String filterValue = Configuration.getRequestParameter(PARAM_FILTER); + if (filterValue != null) { + setValue(filterValue); + } + } + + public String getKeyword() { + return getText().trim().toUpperCase(); + } + + public boolean hasKeyword() { + String keyword = getKeyword(); + return keyword!=null && !"".equals(keyword); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/LibrariesPage.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/LibrariesPage.java new file mode 100644 index 00000000000..54cb1deb2dc --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/LibrariesPage.java @@ -0,0 +1,103 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.user.client.ui.Panel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import org.sonar.gwt.ui.Page; +import org.sonar.wsclient.gwt.AbstractListCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.Resource; +import org.sonar.wsclient.services.ResourceQuery; + +import java.util.ArrayList; +import java.util.List; + +public class LibrariesPage extends Page implements KeyUpHandler, ClickHandler { + public static final String GWT_ID = "org.sonar.plugins.design.ui.libraries.LibrariesPage"; + + private Filters filters; + private List<ProjectPanel> projectPanels = new ArrayList<ProjectPanel>(); + private Panel container; + + @Override + protected Widget doOnResourceLoad(Resource resource) { + container = new VerticalPanel(); + container.setWidth("100%"); + + filters = new Filters(resource); + filters.getKeywordFilter().addKeyUpHandler(this); + filters.getTestCheckbox().addClickHandler(this); + filters.getExpandCollapseLink().addClickHandler(this); + + container.add(filters); + load(resource); + return container; + } + + + private void load(Resource resource) { + ResourceQuery resourceQuery = new ResourceQuery(resource.getId().toString()); + resourceQuery.setDepth(-1).setScopes(Resource.SCOPE_SET); + Sonar.getInstance().findAll(resourceQuery, new AbstractListCallback<Resource>() { + @Override + protected void doOnResponse(List<Resource> subProjects) { + for (Resource subProject : subProjects) { + ProjectPanel projectPanel = new ProjectPanel(subProject, filters); + projectPanels.add(projectPanel); + container.add(projectPanel); + } + } + }); + } + + public void onKeyUp(KeyUpEvent event) { + for (ProjectPanel projectPanel : projectPanels) { + projectPanel.filter(); + } + } + + public void onClick(ClickEvent event) { + if (event.getSource() == filters.getTestCheckbox()) { + for (ProjectPanel projectPanel : projectPanels) { + projectPanel.filter(); + } + } else if (event.getSource() == filters.getExpandCollapseLink()) { + if (filters.isExpanded()) { + filters.collapse(); + expandCollapseLibs(false); + } else { + filters.expand(); + expandCollapseLibs(true); + } + } + } + + private void expandCollapseLibs(boolean expand) { + for (ProjectPanel projectPanel : projectPanels) { + projectPanel.expandCollapse(expand); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Library.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Library.java new file mode 100644 index 00000000000..1e20f0c77b7 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/Library.java @@ -0,0 +1,98 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.user.client.ui.TreeItem; +import org.sonar.gwt.ui.Icons; +import org.sonar.wsclient.services.DependencyTree; + +public class Library extends TreeItem { + + private String keywords; + private String usage; + + public Library(DependencyTree dep) { + setHTML(toHTML(dep)); + keywords = toKeywords(dep); + usage = dep.getUsage(); + } + + private static String toKeywords(DependencyTree dep) { + String text = dep.getResourceName() + " "; + + if (dep.getResourceKey() != null) { + text += dep.getResourceKey() + " "; + } + if (dep.getResourceVersion() != null) { + text += dep.getResourceVersion() + " "; + } + text += dep.getUsage(); + return text.toUpperCase(); + } + + + /** + * @param keyword upper-case keyword + */ + public boolean containsKeyword(String keyword) { + if (keywords.indexOf(keyword) >= 0) { + return true; + } + for (int index = 0; index < getChildCount(); index++) { + if (((Library) getChild(index)).containsKeyword(keyword)) { + return true; + } + } + return false; + } + + private static String toHTML(DependencyTree tree) { + String html = Icons.forQualifier(tree.getResourceQualifier()).getHTML(); + html += " <span> " + tree.getResourceName() + "</span> "; + + if (tree.getResourceVersion() != null) { + html += tree.getResourceVersion() + " "; + } + html += "(" + tree.getUsage() + ")"; + return html; + } + + + public boolean filter(String keyword, boolean testFiltered) { + if (testFiltered && "test".equals(usage)) { + setVisible(false); + return true; + } + + boolean filtered = false; + if (!"".equals(keyword) && !containsKeyword(keyword)) { + filtered = true; + } + + boolean hasVisibleChild = false; + for (int index = 0; index < getChildCount(); index++) { + hasVisibleChild |= !((Library) getChild(index)).filter(keyword, testFiltered); + } + + boolean visible = !filtered || hasVisibleChild; + setVisible(visible); + return !visible; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/ProjectPanel.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/ProjectPanel.java new file mode 100644 index 00000000000..6cae74bf78c --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/libraries/client/ProjectPanel.java @@ -0,0 +1,130 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.libraries.client; + +import com.google.gwt.user.client.ui.*; +import org.sonar.gwt.ui.Icons; +import org.sonar.gwt.ui.Loading; +import org.sonar.wsclient.gwt.AbstractListCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.DependencyTree; +import org.sonar.wsclient.services.DependencyTreeQuery; +import org.sonar.wsclient.services.Resource; + +import java.util.List; + +public class ProjectPanel extends FlowPanel { + + private Label title; + private Tree tree; + private Filters filters; + + public ProjectPanel(Resource project, Filters filters) { + this.filters = filters; + setStyleName("libs"); + getElement().setId("libs-" + project.getKey()); + add(new Loading(project.getName())); + loadLibraries(project); + } + + private void loadLibraries(final Resource project) { + Sonar.getInstance().findAll(DependencyTreeQuery.createForProject(project.getId().toString()), new AbstractListCallback<DependencyTree>() { + + @Override + protected void doOnResponse(List<DependencyTree> dependencyTrees) { + createTitle(project); + createTree(); + + if (dependencyTrees == null || dependencyTrees.isEmpty()) { + clear(); + add(title); + add(createNoLibsMessage()); + + } else { + display(dependencyTrees, null); + filter(); + + clear(); + add(title); + add(tree); + } + } + + private void createTitle(Resource project) { + String html = Icons.forQualifier(project.getQualifier()).getHTML(); + html += " <span class=''> " + project.getName() + "</span> "; + + if (project.getVersion() != null) { + html += project.getVersion() + " "; + } + title = new HTML(html); + } + + private void display(List<DependencyTree> depTrees, TreeItem parentLibrary) { + if (depTrees != null) { + for (DependencyTree depTree : depTrees) { + Library library = new Library(depTree); + if (parentLibrary == null) { + tree.addItem(library); + library.setState(true); + } else { + parentLibrary.addItem(library); + } + display(depTree.getTo(), library); + library.setState(true); + } + } + } + + private void createTree() { + tree = new Tree(); + tree.setAnimationEnabled(false); + } + }); + } + + private Label createNoLibsMessage() { + Label msg = new Label(I18nConstants.INSTANCE.noLibraries()); + msg.setStyleName("nolibs"); + return msg; + } + + public void filter() { + boolean visible = (tree.getItemCount() == 0 && !filters.hasKeyword()); + for (int index = 0; index < tree.getItemCount(); index++) { + Library lib = (Library) tree.getItem(index); + visible |= !lib.filter(filters.getKeywordFilter().getKeyword(), filters.isTestFiltered()); + } + setVisible(visible); + } + + public void expandCollapse(boolean expand) { + for (int index = 0; index < tree.getItemCount(); index++) { + openItem(tree.getItem(index), expand); + } + } + + private void openItem(TreeItem item, boolean open) { + item.setState(open); + for (int i = 0; i < item.getChildCount(); i++) { + openItem(item.getChild(i), open); + } + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/GwtDesignPage.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/GwtDesignPage.java new file mode 100644 index 00000000000..54e8140fcef --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/GwtDesignPage.java @@ -0,0 +1,43 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Resource; +import org.sonar.api.web.*; +import org.sonar.plugins.design.ui.page.client.DesignPage; + +@ResourceLanguage(Java.KEY) +@ResourceScope({Resource.SCOPE_SET, Resource.SCOPE_SPACE}) +@DefaultTab(metrics={CoreMetrics.DEPENDENCY_MATRIX_KEY, CoreMetrics.PACKAGE_FEEDBACK_EDGES_KEY, CoreMetrics.PACKAGE_CYCLES_KEY, CoreMetrics.PACKAGE_TANGLE_INDEX_KEY, CoreMetrics.PACKAGE_TANGLES_KEY, CoreMetrics.FILE_CYCLES_KEY, CoreMetrics.FILE_TANGLE_INDEX_KEY, CoreMetrics.FILE_TANGLES_KEY, CoreMetrics.FILE_FEEDBACK_EDGES_KEY}) +@NavigationSection({NavigationSection.RESOURCE, NavigationSection.RESOURCE_TAB}) +@UserRole(UserRole.USER) +public class GwtDesignPage extends GwtPage { + + public String getGwtId() { + return DesignPage.GWT_ID; + } + + public String getTitle() { + return "Design"; + } + +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DependencyInfo.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DependencyInfo.java new file mode 100644 index 00000000000..72e263da58a --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DependencyInfo.java @@ -0,0 +1,180 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page.client; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.*; +import org.sonar.gwt.Configuration; +import org.sonar.gwt.Links; +import org.sonar.gwt.ui.Icons; +import org.sonar.gwt.ui.Loading; +import org.sonar.wsclient.gwt.AbstractCallback; +import org.sonar.wsclient.gwt.AbstractListCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.Dependency; +import org.sonar.wsclient.services.DependencyQuery; +import org.sonar.wsclient.services.Resource; + +import java.util.List; + +public class DependencyInfo extends Composite { + + private static DependencyInfo INSTANCE = new DependencyInfo(); + + private VerticalPanel panel; + private Loading loading = new Loading(); + private String currentDependencyId = null; + private boolean popupMode = false; + + private DependencyInfo() { + panel = new VerticalPanel(); + initWidget(panel); + } + + public static DependencyInfo getInstance() { + return INSTANCE; + } + + + public void showOrPopup(String dependencyId) { + if (popupMode) { + Window.open(Links.urlForResourcePage(Configuration.getResourceId(), DesignPage.GWT_ID, "layout=false&depId=" + dependencyId), "dependency", Links.DEFAULT_POPUP_HTML_FEATURES); + + } else { + INSTANCE.show(dependencyId); + } + } + + public void show(String dependencyId) { + panel.clear(); + currentDependencyId = dependencyId; + if (dependencyId !=null) { + panel.add(loading); + loadDependency(dependencyId); + } + } + + public DependencyInfo setPopupMode(boolean b) { + this.popupMode = b; + return this; + } + + public void popup() { + popupMode = true; + panel.clear(); + showOrPopup(currentDependencyId); + } + + private void setLoaded() { + loading.removeFromParent(); + } + + private void loadDependency(String dependencyId) { + DependencyQuery query = DependencyQuery.createForId(dependencyId); + Sonar.getInstance().find(query, new AbstractCallback<Dependency>() { + @Override + protected void doOnResponse(Dependency dependency) { + if (dependency == null) { + setLoaded(); + panel.add(new Label(I18nConstants.INSTANCE.noData())); + } else { + loadSubDependencies(dependency); + } + } + + @Override + protected void doOnError(int errorCode, String errorMessage) { + super.doOnError(errorCode, errorMessage); + } + }); + } + + private void loadSubDependencies(final Dependency dependency) { + DependencyQuery query = DependencyQuery.createForSubDependencies(dependency.getId()); + Sonar.getInstance().findAll(query, new AbstractListCallback<Dependency>() { + + @Override + protected void doOnResponse(final List<Dependency> subDependencies) { + Grid table = new Grid(subDependencies.size() + 1, 5); + table.setStyleName("depInfo"); + createHeader(dependency, table); + + for (int row = 0; row < subDependencies.size(); row++) { + Dependency dep = subDependencies.get(row); + table.setWidget(row + 1, 0, new HTML(Icons.forQualifier(dep.getFromQualifier()).getHTML())); + if (Resource.QUALIFIER_FILE.equals(dep.getFromQualifier()) || Resource.QUALIFIER_CLASS.equals(dep.getFromQualifier())) { + table.setWidget(row + 1, 1, createLink(dep.getFromId(), dep.getFromName())); + } else { + table.setText(row + 1, 1, dep.getFromName()); + } + table.setText(row + 1, 2, " " + dep.getUsage() + " "); + table.setWidget(row + 1, 3, new HTML(Icons.forQualifier(dep.getToQualifier()).getHTML())); + if (Resource.QUALIFIER_FILE.equals(dep.getToQualifier()) || Resource.QUALIFIER_CLASS.equals(dep.getToQualifier())) { + table.setWidget(row + 1, 4, createLink(dep.getToId(), dep.getToName())); + } else { + table.setText(row + 1, 4, dep.getToName()); + } + } + + + panel.clear(); + if (!popupMode) { + panel.add(createNewWindowLink()); + } + panel.add(table); + } + }); + } + + private Label createLink(final long resourceId, final String resourceName) { + Label link = new Label(resourceName); + link.setStyleName("link"); + link.addClickHandler(new ClickHandler() { + + public void onClick(ClickEvent event) { + Links.openResourcePopup(String.valueOf(resourceId)); + } + }); + return link; + } + + private void createHeader(final Dependency dependency, final Grid grid) { + grid.getRowFormatter().setStyleName(0, "depInfoHeader"); + + grid.setWidget(0, 0, Icons.forQualifier(dependency.getFromQualifier()).createImage()); + grid.setText(0, 1, dependency.getFromName()); + + grid.setWidget(0, 3, Icons.forQualifier(dependency.getToQualifier()).createImage()); + grid.setText(0, 4, dependency.getToName()); + } + + private Widget createNewWindowLink() { + Label popup = new Label(I18nConstants.INSTANCE.newWindow()); + popup.setStyleName("newwindow"); + popup.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + popup(); + } + }); + return popup; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DesignPage.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DesignPage.java new file mode 100644 index 00000000000..a8be3dfd472 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DesignPage.java @@ -0,0 +1,72 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page.client; + +import com.google.gwt.user.client.ui.Panel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import org.sonar.gwt.Configuration; +import org.sonar.gwt.Metrics; +import org.sonar.gwt.ui.Page; +import org.sonar.wsclient.gwt.AbstractCallback; +import org.sonar.wsclient.gwt.Sonar; +import org.sonar.wsclient.services.Measure; +import org.sonar.wsclient.services.Resource; +import org.sonar.wsclient.services.ResourceQuery; + +public class DesignPage extends Page { + + public static final String GWT_ID = "org.sonar.plugins.design.ui.page.DesignPage"; + private Dsm matrix; + + @Override + protected Widget doOnResourceLoad(Resource resource) { + String dependencyId = Configuration.getRequestParameter("depId"); + if (dependencyId != null) { + DependencyInfo.getInstance().setPopupMode(true).show(dependencyId); + return DependencyInfo.getInstance(); + } + VerticalPanel layout = new VerticalPanel(); + layout.setWidth("100%"); + Panel hPanel = new VerticalPanel(); + matrix = new Dsm(); + hPanel.add(matrix); + hPanel.add(DependencyInfo.getInstance()); + layout.add(hPanel); + loadMatrix(resource); + return layout; + } + + private void loadMatrix(Resource resource) { + Sonar.getInstance().find(ResourceQuery.createForMetrics(resource.getId().toString(), "dsm"), new AbstractCallback<Resource>() { + + @Override + protected void doOnResponse(Resource resource) { + if (resource == null || resource.getMeasure(Metrics.DEPENDENCY_MATRIX) == null) { + matrix.displayNoData(); + + } else { + Measure dsm = resource.getMeasure(Metrics.DEPENDENCY_MATRIX); + matrix.display(DsmData.parse(dsm.getData())); + } + } + }); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/Dsm.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/Dsm.java new file mode 100644 index 00000000000..2b7dba5bd01 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/Dsm.java @@ -0,0 +1,366 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page.client; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.DoubleClickEvent; +import com.google.gwt.event.dom.client.DoubleClickHandler; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.*; +import org.sonar.gwt.Links; +import org.sonar.gwt.ui.Icons; + +import java.util.LinkedList; +import java.util.List; + +public class Dsm extends Composite { + + /* STYLES */ + public static final String DSM = "dsm"; + + public static final String HEADER = "htable"; + public static final String HEADER_TITLE = "ht"; + public static final String HEADER_SELECTED_SUFFIX = "s"; + public static final String HEADER_INDICATOR = "hi"; + public static final String HEADER_HIGHER_INDICATOR_SUFFIX = "h"; + public static final String HEADER_LOWER_INDICATOR_SUFFIX = "l"; + + public static final String GRID = "gtable"; + public static final String GRID_CELL_BOTTOM_LEFT = "cbl"; + public static final String GRID_CELL_TOP_RIGHT = "ctr"; + public static final String GRID_CELL_DIAGONAL = "cd"; + public static final String GRID_CELL_SELECTION1_SUFFIX = "s1"; + public static final String GRID_CELL_SELECTION2_SUFFIX = "s2"; + public static final String GRID_CELL_COMB1_SUFFIX = "c1"; + public static final String GRID_CELL_COMB2_SUFFIX = "c2"; + public static final String[] GRID_SUFFIXES = {GRID_CELL_SELECTION1_SUFFIX, GRID_CELL_SELECTION2_SUFFIX, GRID_CELL_COMB1_SUFFIX, GRID_CELL_COMB2_SUFFIX}; + + + private VerticalPanel dsm = new VerticalPanel(); + private DsmData.Rows data; + private Label[][] cells; + private Label[] titles; + private Label[] indicators; + private List<Label> highlightedCells = new LinkedList<Label>(); + + public Dsm() { + dsm.setStylePrimaryName(DSM); + initWidget(dsm); + } + + private Widget createLegend() { + HorizontalPanel legend = new HorizontalPanel(); + legend.getElement().setId("dsmlegend"); + legend.add(new HTML("<div class='square gray'> </div>")); + legend.add(new Label(I18nConstants.INSTANCE.legendDependencies())); + legend.add(new HTML("<div class='space'></div>")); + legend.add(new HTML("<div class='square red'> </div> ")); + legend.add(new Label(I18nConstants.INSTANCE.legendCycles())); + legend.add(new HTML(" <div class='space'></div> ")); + legend.add(new HTML("<div class='square green'></div> ")); + legend.add(new Label(I18nConstants.INSTANCE.legendUses())); + legend.add(new HTML("<div class='square blue'></div> ")); + legend.add(new Label(I18nConstants.INSTANCE.legendUses())); + legend.add(new HTML(" <div class='square yellow'></div>")); + return legend; + } + + public void displayNoData() { + dsm.clear(); + dsm.add(new Label(I18nConstants.INSTANCE.noData())); + } + + public void display(DsmData.Rows data) { + if (data == null) { + displayNoData(); + + } else { + this.data = data; + dsm.clear(); + dsm.add(createHelp()); + dsm.add(createLegend()); + HorizontalPanel matrix = new HorizontalPanel(); + matrix.add(createRowHeader()); + matrix.add(createGrid()); + dsm.add(matrix); + } + } + + private Widget createHelp() { + HorizontalPanel help = new HorizontalPanel(); + help.getElement().setId("dsmhelp"); + Anchor link = new Anchor(I18nConstants.INSTANCE.linkToHelp(), "http://docs.codehaus.org/x/QQFhC", "docsonar"); + help.add(Icons.get().help().createImage()); + help.add(link); + return help; + } + + private Grid createRowHeader() { + Grid header = new Grid(data.size(), 2); + header.setCellPadding(0); + header.setCellSpacing(0); + header.setStylePrimaryName(HEADER); + + titles = new Label[data.size()]; + indicators = new Label[data.size()]; + for (int indexRow = 0; indexRow < data.size(); indexRow++) { + DsmData.Row row = data.get(indexRow); + + HTML title = buildRowTitle(indexRow, row); + titles[indexRow] = title; + header.setWidget(indexRow, 0, title); + + Label indicator = buildLabel("", HEADER_INDICATOR); + header.setWidget(indexRow, 1, indicator); + indicators[indexRow] = indicator; + } + return header; + } + + private Grid createGrid() { + int rowsCount = data.size(); + Grid grid = new Grid(rowsCount, rowsCount); + grid.setCellPadding(0); + grid.setCellSpacing(0); + grid.setStylePrimaryName(GRID); + + return loadGridCells(grid, data); + } + + private Grid loadGridCells(Grid grid, DsmData.Rows data) { + int size = data.size(); + cells = new Label[size][size]; + for (int row = 0; row < size; row++) { + DsmData.Row resource = data.get(row); + for (int col = 0; col < resource.size(); col++) { + Label cell = createGridCell(row, col, resource.getWeight(col)); + grid.setWidget(row, col, cell); + cells[row][col] = cell; + } + } + return grid; + } + + + /* ---------------- ACTIONS -------------------- */ + + public void onCellClicked(int row, int col) { + cancelHighlighting(); + + highlightTitle(row); + highlightTitle(col); + highlightIndicator(row); + highlightIndicator(col); + + for (int i = 0; i < cells.length; i++) { + for (int j = 0; j < cells.length; j++) { + Label cell = cells[i][j]; + if (i == row && j == col) { + highlightCell(cell, GRID_CELL_SELECTION1_SUFFIX); + + } else if (j == row && i == col) { + // opposite + highlightCell(cell, GRID_CELL_SELECTION1_SUFFIX); + + } else if (j == col || i == col) { + highlightCell(cell, GRID_CELL_COMB1_SUFFIX); + + } else if (i == row || j == row) { + highlightCell(cell, GRID_CELL_COMB2_SUFFIX); + } + } + } + } + + private void displayDependencyInfo(int row, int col) { + DsmData.Cell cell = data.get(row).getCell(col); + DependencyInfo.getInstance().showOrPopup(cell.getDependencyId()); + } + + public void onTitleClicked(int row) { + cancelHighlighting(); + highlightTitle(row); + highlightIndicator(row); + + // highlight row + for (int col = 0; col < cells[row].length; col++) { + highlightCell(cells[row][col], GRID_CELL_SELECTION2_SUFFIX); + if (col < row && hasWeight(cells[row][col])) { + highlightIndicator(col, true); + } + } + + // highlight column + for (int i = 0; i < cells.length; i++) { + if (i != row) { + highlightCell(cells[i][row], GRID_CELL_SELECTION2_SUFFIX); + if (i > row && hasWeight(cells[i][row])) { + highlightIndicator(i, false); + } + } + } + } + + private boolean hasWeight(Label label) { + return label.getText().length() > 0; + } + + + /*--------- EFFECTS ----------*/ + private void cancelHighlighting() { + cancelGridHighlighting(); + cancelIndicatorsHighlighting(); + cancelTitlesHighlighting(); + } + + private void cancelGridHighlighting() { + for (Label cell : highlightedCells) { + for (String suffix : GRID_SUFFIXES) { + cell.removeStyleDependentName(suffix); + } + } + highlightedCells.clear(); + } + + private void highlightCell(Label cell, String style) { + cell.addStyleDependentName(style); + highlightedCells.add(cell); + } + + private void highlightTitle(int row) { + titles[row].addStyleDependentName(HEADER_SELECTED_SUFFIX); + } + + private void cancelTitlesHighlighting() { + for (Label title : titles) { + title.removeStyleDependentName(HEADER_SELECTED_SUFFIX); + } + } + + private void cancelIndicatorsHighlighting() { + for (Label indicator : indicators) { + indicator.removeStyleDependentName(HEADER_HIGHER_INDICATOR_SUFFIX); + indicator.removeStyleDependentName(HEADER_LOWER_INDICATOR_SUFFIX); + indicator.removeStyleDependentName(HEADER_SELECTED_SUFFIX); + } + } + + private void highlightIndicator(int row) { + indicators[row].addStyleDependentName(HEADER_SELECTED_SUFFIX); + } + + private void highlightIndicator(int row, boolean higher) { + indicators[row].addStyleDependentName(higher ? HEADER_HIGHER_INDICATOR_SUFFIX : HEADER_LOWER_INDICATOR_SUFFIX); + } + + + /* ---------- COMPONENTS ------------ */ + private Label createGridCell(final int row, final int col, final int weight) { + Label cell; + if (row == col) { + cell = createDiagonalCell(row); + + } else { + cell = createNonDiagonalCell(row, col, weight); + } + return cell; + } + + private Label createNonDiagonalCell(final int row, final int col, int weight) { + Label cell; + cell = buildCell(row, col, weight, (col > row ? GRID_CELL_TOP_RIGHT : GRID_CELL_BOTTOM_LEFT)); + + if (weight > 0) { + String tooltip = data.get(col).getName() + " -> " + data.get(row).getName() + " (" + weight + "). " + I18nConstants.INSTANCE.cellTooltip(); + cell.setTitle(tooltip); + } + return cell; + } + + private Label createDiagonalCell(final int row) { + Label cell; + cell = buildLabel("-", GRID_CELL_DIAGONAL); + cell.addClickHandler(new ClickHandler() { + public void onClick(final ClickEvent event) { + onTitleClicked(row); + } + }); + return cell; + } + + private HTML buildRowTitle(final int indexRow, final DsmData.Row row) { + HTML title = new HTML(Icons.forQualifier(row.getQualifier()).getHTML() + " " + row.getName()) { + { + addDomHandler(new DoubleClickHandler() { + public void onDoubleClick(DoubleClickEvent pEvent) { + if (row.getId() != null) { + if (!"FIL".equals(row.getQualifier()) && !"CLA".equals(row.getQualifier())) { + Window.Location.assign(Links.urlForResourcePage(row.getId(), DesignPage.GWT_ID, null)); + } else { + Links.openMeasurePopup(row.getId(), null); + } + } + } + }, DoubleClickEvent.getType()); + } + }; + title.setStylePrimaryName(HEADER_TITLE); + title.setTitle(I18nConstants.INSTANCE.rowTooltip()); + final int finalIndexRow = indexRow; + title.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + onTitleClicked(finalIndexRow); + } + }); + return title; + } + + private static Label buildLabel(String text, String primaryStyle) { + Label label = new Label(text); + label.setStylePrimaryName(primaryStyle); + return label; + } + + private Label buildCell(final int row, final int col, int weight, String primaryStyle) { + String text = ""; + if (weight > 0) { + text = "<span>" + Integer.toString(weight) + "</span>"; + } + + HTML cell = new HTML(text) { + { + addDomHandler(new DoubleClickHandler() { + public void onDoubleClick(DoubleClickEvent pEvent) { + displayDependencyInfo(row, col); + } + }, DoubleClickEvent.getType()); + } + }; + cell.addClickHandler(new ClickHandler() { + public void onClick(final ClickEvent event) { + onCellClicked(row, col); + } + }); + cell.setStylePrimaryName(primaryStyle); + return cell; + } + +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DsmData.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DsmData.java new file mode 100644 index 00000000000..42c362f268e --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/DsmData.java @@ -0,0 +1,65 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page.client; + +import com.google.gwt.core.client.JavaScriptObject; + +public final class DsmData { + + public static class Row extends JavaScriptObject { + + // Overlay types always have protected, zero-arg ctors + protected Row() { + } + + public final native String getId() /*-{ return this.i; }-*/; + public final native String getName() /*-{ return this.n; }-*/; + public final native String getQualifier() /*-{ return this.q; }-*/; + public final native Cell getCell(final int col) /*-{ return this.v[col]; }-*/; + public final native int size() /*-{ return this.v.length; }-*/; + public final int getWeight(final int col) { + Cell cell = getCell(col); + return (cell==null) ? 0 : cell.getWeight(); + } + } + + public static class Cell extends JavaScriptObject { + + // Overlay types always have protected, zero-arg ctors + protected Cell() { + } + + public final native String getDependencyId() /*-{ if(this.i) {return this.i;} else { return null;} }-*/; + public final native int getWeight() /*-{ return this.w || 0; }-*/; + } + + + public static class Rows extends JavaScriptObject { + protected Rows() { + } + public final native int size() /*-{ return this.length; }-*/; + public final native Row get(int i) /*-{ return this[i]; }-*/; + } + + public static native Rows parse(String json) /*-{ + return eval('(' + json + ')') + }-*/; + +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/I18nConstants.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/I18nConstants.java new file mode 100644 index 00000000000..63423385f23 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/page/client/I18nConstants.java @@ -0,0 +1,51 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.page.client; + +import com.google.gwt.core.client.GWT; + +public interface I18nConstants extends com.google.gwt.i18n.client.Constants { + + static I18nConstants INSTANCE = GWT.create(I18nConstants.class); + + @DefaultStringValue("Dependency") + String legendDependencies(); + + @DefaultStringValue("Suspect dependency (cycle)") + String legendCycles(); + + @DefaultStringValue("- uses >") + String legendUses(); + + @DefaultStringValue("No data") + String noData(); + + @DefaultStringValue("New window") + String newWindow(); + + @DefaultStringValue("Click to highlight, double-click to display more details.") + String cellTooltip(); + + @DefaultStringValue("Click to highlight, double-click to zoom.") + String rowTooltip(); + + @DefaultStringValue("Help") + String linkToHelp(); +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/ChidamberKemererWidget.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/ChidamberKemererWidget.java new file mode 100644 index 00000000000..d05806e1a34 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/ChidamberKemererWidget.java @@ -0,0 +1,40 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.widgets; + +import org.sonar.api.web.AbstractRubyTemplate; +import org.sonar.api.web.RubyRailsWidget; +import org.sonar.api.web.UserRole; + +@UserRole(UserRole.USER) +public final class ChidamberKemererWidget extends AbstractRubyTemplate implements RubyRailsWidget { + public String getId() { + return "ckjm"; + } + + public String getTitle() { + return "2_Chidamber & Kemerer"; + } + + @Override + protected String getTemplatePath() { + return "/org/sonar/plugins/design/ui/widgets/chidamber_kemerer.html.erb"; + } +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/FileDesignWidget.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/FileDesignWidget.java new file mode 100644 index 00000000000..fc946c5c19b --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/FileDesignWidget.java @@ -0,0 +1,40 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.widgets; + +import org.sonar.api.web.AbstractRubyTemplate; +import org.sonar.api.web.RubyRailsWidget; +import org.sonar.api.web.UserRole; + +@UserRole(UserRole.USER) +public final class FileDesignWidget extends AbstractRubyTemplate implements RubyRailsWidget { + public String getId() { + return "file-design"; + } + + public String getTitle() { + return "1_File design"; + } + + @Override + protected String getTemplatePath() { + return "/org/sonar/plugins/design/ui/widgets/file_design.html.erb"; + } +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/PackageDesignWidget.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/PackageDesignWidget.java new file mode 100644 index 00000000000..807cb5b5329 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/PackageDesignWidget.java @@ -0,0 +1,40 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.ui.widgets; + +import org.sonar.api.web.AbstractRubyTemplate; +import org.sonar.api.web.RubyRailsWidget; +import org.sonar.api.web.UserRole; + +@UserRole(UserRole.USER) +public final class PackageDesignWidget extends AbstractRubyTemplate implements RubyRailsWidget { + public String getId() { + return "package-design"; + } + + public String getTitle() { + return "1_Package design"; + } + + @Override + protected String getTemplatePath() { + return "/org/sonar/plugins/design/ui/widgets/package_design.html.erb"; + } +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/DependenciesTab.gwt.xml b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/DependenciesTab.gwt.xml new file mode 100644 index 00000000000..c20b988ba44 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/DependenciesTab.gwt.xml @@ -0,0 +1,13 @@ +<module> + <inherits name="com.google.gwt.user.User"/> + <inherits name="com.google.gwt.json.JSON"/> + <inherits name="com.google.gwt.http.HTTP"/> + <inherits name="org.sonar.Sonar"/> + + <stylesheet src='dependencies-tab.css'/> + <entry-point class="org.sonar.plugins.design.ui.dependencies.client.DependenciesTab"/> + + <extend-property name="locale" values="en"/> + <extend-property name="locale" values="fr"/> + +</module> diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/client/I18nConstants_fr.properties b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/client/I18nConstants_fr.properties new file mode 100644 index 00000000000..ab2e9eab623 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/client/I18nConstants_fr.properties @@ -0,0 +1,7 @@ +afferentCouplings= Dépendances entrantes +efferentCouplings= Dépendances sortantes +classes=Classes +dit=Profondeur d'héritage +noc=Nombre d'enfants +lcom4=Manque de cohésion des méthodes +noData=Aucune information
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/dependencies-tab.css b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/dependencies-tab.css new file mode 100644 index 00000000000..4bee7667fb1 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/dependencies-tab.css @@ -0,0 +1,23 @@ +#deps { + padding: 10px; +} + +#deps .data { + min-width: 380px; +} +#deps .col { + margin: 0 10px 0 0; + border-right: 1px solid #ccc; + border-left: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} +#deps .col td { + padding: 3px 5px; +} + +#deps .coltitle { + background-color: #efefef; + padding: 3px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/test.html b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/test.html new file mode 100644 index 00000000000..55cbc551234 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/dependencies/public/test.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <title>Sources</title> + <link href="http://localhost:9000/stylesheets/sonar.css" media="all" rel="Stylesheet" type="text/css" /> + <script src="http://localhost:9000/javascripts/sonar.js" type="text/javascript"></script> +</head> + +<body> +<script type="text/javascript"> +var registeredTabs = []; +var config = { + "sonar_url": "http://localhost:9000", + "viewer_resource_key" : "org.apache.struts:struts-core:org.apache.struts.action.ActionServlet" +}; +</script> +<div class="error" id="error" style="display:none"><span id="errormsg"></span> [<a href="test.html#" onclick="javascript:$('error').hide();return false;">hide</a>]</div> +<div class="warning" id="warning" style="display:none"><span id="warningmsg"></span> [<a href="test.html#" onclick="javascript:$('warning').hide();return false;">hide</a>]</div> +<div class="notice" id="info" style="display:none"><span id="infomsg"></span> [<a href="test.html#" onclick="javascript:$('info').hide();return false;">hide</a>]</div> + +<div id="resource_viewers"> + <div id='loading'></div> +</div> +<script type="text/javascript" language="javascript" src="org.sonar.plugins.design.ui.dependencies.DependenciesTab.nocache.js"></script> + +<a href="test.html#" onclick="load_org_sonar_plugins_design_ui_dependencies_DependenciesTab();">load</a> +</body> +</html>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/Lcom4Tab.gwt.xml b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/Lcom4Tab.gwt.xml new file mode 100644 index 00000000000..2de9ebb7965 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/Lcom4Tab.gwt.xml @@ -0,0 +1,13 @@ +<module> + <inherits name="com.google.gwt.user.User"/> + <inherits name="com.google.gwt.json.JSON"/> + <inherits name="com.google.gwt.http.HTTP"/> + <inherits name="org.sonar.Sonar"/> + + <stylesheet src="lcom4.css"/> + <entry-point class="org.sonar.plugins.design.ui.lcom4.client.Lcom4Tab"/> + + <extend-property name="locale" values="en"/> + <extend-property name="locale" values="fr"/> + +</module> diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.css b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.css new file mode 100644 index 00000000000..bbd35eb6237 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.css @@ -0,0 +1,23 @@ +.lcom4blocks { + width: 100%; + margin-top: 10px; +} +.lcom4blocks td { + vertical-align: top; +} +.lcom4blocks .index { + font-size: 130%; + text-align: center; + width: 2em; + margin-top: 3px; +} +.lcom4block { + width: 100%; + border: 1px solid #ccc; + margin-bottom: 15px; + background-color: #eee; +} +.lcom4row { + padding: 2px 5px; + word-wrap:break-word; +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.html b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.html new file mode 100644 index 00000000000..8ae47cdd1c0 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/lcom4/public/lcom4.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <meta name="gwt:property" content="locale=fr_CH"> + + <title>LCOM4</title> + <link href="http://localhost:9000/stylesheets/sonar.css" media="all" rel="Stylesheet" type="text/css" /> + <script src="http://localhost:9000/javascripts/sonar.js" type="text/javascript"></script> +</head> + +<body> +<h1>LCOM4</h1> +<div id="gwtpage"> +</div> +<script type="text/javascript"> +var config = { + "sonar_url": "http://localhost:9000", + "metric":"lcom4", + "resource":[{"id":11, "key":"org.apache.struts:struts-core:org.apache.struts.action.Action","scope": "FIL", "qualifier": "CLA", "name": "ActionServlet", "lang":"java"}] +}; + var modules = {}; +</script> +<script type="text/javascript" language="javascript" src="org.sonar.plugins.design.ui.lcom4.Lcom4Tab.nocache.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/LibrariesPage.gwt.xml b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/LibrariesPage.gwt.xml new file mode 100644 index 00000000000..f19861a3644 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/LibrariesPage.gwt.xml @@ -0,0 +1,13 @@ +<module> + <inherits name="com.google.gwt.user.User"/> + <inherits name="com.google.gwt.json.JSON"/> + <inherits name="com.google.gwt.http.HTTP"/> + <inherits name="org.sonar.Sonar"/> + <stylesheet src="libraries.css"/> + + <entry-point class="org.sonar.plugins.design.ui.libraries.client.LibrariesPage"/> + + <extend-property name="locale" values="en"/> + <extend-property name="locale" values="fr"/> + +</module> diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/client/I18nConstants_fr.properties b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/client/I18nConstants_fr.properties new file mode 100644 index 00000000000..52e1a94be75 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/client/I18nConstants_fr.properties @@ -0,0 +1,6 @@ +filter: Filtre: +displayTests: Afficher les librairies de test +expand: Développer +collapse: Réduire +noLibraries: Aucune librairie +usageLink: Utilisations
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/libraries.css b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/libraries.css new file mode 100644 index 00000000000..191ade42a86 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/libraries.css @@ -0,0 +1,22 @@ +.libs { + border: 1px solid #ccc; + padding: 5px 10px; + margin-top: 5px; +} +.libs .gwt-Tree img { + /* hack to align rows */ + margin-left: 6px; +} +.libFilter input { + margin-right: 3px; +} +.libFilter { + +} +.libFilter td { + padding-right: 15px; +} +.nolibs { + padding: 0 0 0 20px; + font-size: 93%; +}
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/test.html b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/test.html new file mode 100644 index 00000000000..1f5af2b1bbc --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/libraries/public/test.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <meta name="gwt:property" content="locale=fr_CH"> + + <title>Libraries</title> + <link href="http://localhost:9000/stylesheets/sonar.css" media="all" rel="Stylesheet" type="text/css" /> + <script src="http://localhost:9000/javascripts/sonar.js" type="text/javascript"></script> +</head> + +<body> +<h1>Libraries</h1> +<div id="gwtpage"> +</div> +<script type="text/javascript"> +var config = { + "sonar_url": "http://localhost:9000", + "resource":[{"id":1141, "key":"org.apache.struts:struts-parent","scope": "PRJ", "qualifier": "TRK", "name": "Struts Core", "lang":"java"}] +}; + var modules = {}; + +var rp = { + "page":"org.sonar.plugins.design.ui.libraries.LibrariesPage" + ,"filter2":"commons" + }; + +</script> +<script type="text/javascript" language="javascript" src="org.sonar.plugins.design.ui.libraries.LibrariesPage.nocache.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/DesignPage.gwt.xml b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/DesignPage.gwt.xml new file mode 100644 index 00000000000..7655704d886 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/DesignPage.gwt.xml @@ -0,0 +1,12 @@ +<module> + <inherits name="com.google.gwt.user.User"/> + <inherits name="com.google.gwt.json.JSON"/> + <inherits name="com.google.gwt.http.HTTP"/> + <inherits name="org.sonar.Sonar"/> + <stylesheet src="design.css"/> + + <entry-point class="org.sonar.plugins.design.ui.page.client.DesignPage"/> + + <extend-property name="locale" values="en"/> + <extend-property name="locale" values="fr"/> +</module> diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/client/I18nConstants_fr.properties b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/client/I18nConstants_fr.properties new file mode 100644 index 00000000000..b2e15b28ca0 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/client/I18nConstants_fr.properties @@ -0,0 +1,8 @@ +legendDependencies=Dépendance +legendCycles=Dépendance suspecte (cycle) +legendUses=- dépend de > +noData=Aucune information +noWindow=Nouvelle fenêtre +cellTooltip=Cliquez pour sélectionner, double-cliquez pour afficher plus de détails. +rowTooltip=Cliquez pour sélectionner, double-cliquez pour zoomer. +linkToHelp=Aide
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/design.css b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/design.css new file mode 100644 index 00000000000..a5a8be74221 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/design.css @@ -0,0 +1,227 @@ +.dsm { + border-collapse: separate; + background-color: #fff; + font-family: sans-serif; + font-size: 9pt; + color: #222; + margin-bottom: 10px; + padding: 5px 10px; +} + +/*------- LEGEND */ + +#dsmlegend { + padding: 5px; + margin: 0 0 5px 5px; +} +#dsmlegend td { + white-space: nowrap; +} +#dsmlegend .square { + width: 11px; + height: 14px; + display: inline-block; + vertical-align: bottom; + padding-left: 3px; + margin-bottom: 1px; + margin-right: 5px; +} +#dsmlegend .gwt-Label { + padding-right: 5px; +} +#dsmhelp { + margin: 0 0 5px 5px; +} +#dsmhelp img { + margin-right: 4px; +} + +.dsm .gray { + background-color: #ddd; +} +.dsm .red { + background-color: #c13333; +} +.dsm .green { + background-color: #46c557; + background-image:url('green-stripes.png'); +} +.dsm .blue { + background-color: #4B9FD5; +} +.dsm .yellow { + background-color: #d49e37; +} +.dsm .space { + display: inline-block; + width: 12px; +} + + + +/*------- LEFT HEADER */ + +/* header table */ +.dsm .htable { + padding: 1px; + border-top: 1px solid #676b9a; + border-right: 1px solid #676b9a; +} + +/* header title */ +.dsm .ht { + background-color: #CAE3F2; + color: #434343; + height: 16px; + padding: 2px 0 3px 5px; + border-bottom: 1px solid #676b9a; + border-left: 1px solid #676b9a; + cursor: pointer; + white-space: nowrap; +} +.dsm .ht-s { + background-color: #4B9FD5; + color: #efefef; +} +.dsm .ht img { + vertical-align: text-bottom; +} + +/* header indicator */ +.dsm .hi { + background-color: #CAE3F2; + width: 8px; + height: 21px; + border-bottom: 1px solid #676b9a; +} +.dsm .hi-s { + background-color: #4B9FD5; +} +.dsm .hi-h { + background-color: #46c557; + background-image:url('green-stripes.png'); +} +.dsm .hi-l { + background-color: #d49e37; +} + + + +/*------- GRID */ + +.dsm .gtable { + padding: 1px; + border-top: 1px solid #ccc; + +} + +/* cell on bottom left */ +.dsm .cbl { + height: 16px; + width: 23px; + padding-top: 5px; + background-color: #fff; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + color: #434343; + text-align: center; + cursor: pointer; +} +.dsm .cbl span { + background-color: #ddd; + padding: 2px 2px 0 2px; +} + +/* + cell on top right : has feedback edge + total height: height + padding-top + 2*border = 25px +*/ +.dsm .ctr { + height: 16px; + width: 23px; + padding-top: 5px; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + font-weight: normal; + text-align: center; + cursor: pointer; +} +.dsm .ctr span { + background-color: #c13333; + color: #fff; + padding: 2px 2px 0 2px; +} + +/* cell on diagonal */ +.dsm .cd { + height: 16px; + width: 23px; + padding-top: 5px; + background-color: #fff; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + color: #434343; + text-align: center; + cursor: pointer; +} + +/* selected cell, mode 1 */ +.dsm .cbl-s1, .dsm .ctr-s1, .dsm .cd-s1 { + background-color: #b580c9; +} + +/* selected cell, mode 2 */ +.dsm .cbl-s2 { + background-color: #CAE3F2; +} +.dsm .ctr-s2 { + background-color: #CAE3F2; +} +.dsm .cd-s2 { + background-color: #4B9FD5; + color: #efefef; +} + +/* comb 1 */ +.dsm .cbl-c1, .dsm .ctr-c1, .dsm .cd-c1 { + background-color: #46c557; + background-image:url('green-stripes.png'); +} + +/* comb 2 */ +.dsm .cbl-c2, .dsm .ctr-c2, .dsm .cd-c2 { + background-color: #d49e37; +} + + +/*---------- DEPENDENCY INFO */ +.depInfo { + background-color: #fff; + border-top-width: 0; + border-bottom: 2px solid #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + width: 100%; +} +.depInfo td { + padding: 3px 2px; +} +.link { + text-decoration:underline; + cursor: pointer; +} +.newwindow { + text-decoration:underline; + cursor: pointer; + padding: 3px; + color: #777; +} +.depInfoHeader { + background-color: #efefef; + border-top: 2px solid #ccc; + border-bottom: 2px solid #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + padding: 5px; + width: 100%; +} diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/green-stripes.png b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/green-stripes.png Binary files differnew file mode 100644 index 00000000000..56509c4dab2 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/green-stripes.png diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/test.html b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/test.html new file mode 100644 index 00000000000..daf6bdeef7e --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/test.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <meta name="gwt:property" content="locale=fr_CH"> + + <title>DSM</title> + <link href="http://localhost:9000/stylesheets/sonar.css" media="all" rel="Stylesheet" type="text/css" /> + <script src="http://localhost:9000/javascripts/sonar.js" type="text/javascript"></script> +</head> + +<body> +<h1>Design Structure Matrix</h1> +<div id="gwtpage"> +</div> +<script type="text/javascript"> +var config = { + "sonar_url": "http://localhost:9000", + "resource":[{"id":1, "key":"org.apache.struts:struts-parent","scope": "PRJ", "qualifier": "BRC", "name": "Struts Core", "lang":"java"}] +}; + var modules = {}; +</script> +<script type="text/javascript" language="javascript" src="org.sonar.plugins.design.ui.page.DesignPage.nocache.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/yellow-stripes.png b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/yellow-stripes.png Binary files differnew file mode 100644 index 00000000000..fb4cccc1605 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/page/public/yellow-stripes.png diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/chidamber_kemerer.html.erb b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/chidamber_kemerer.html.erb new file mode 100644 index 00000000000..2f772d05ce7 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/chidamber_kemerer.html.erb @@ -0,0 +1,50 @@ +<% +lcom=measure('lcom4') +rfc=measure('rfc') +if lcom || rfc + lcom_distribution=measure('lcom4_distribution') + rfc_distribution=measure('rfc_distribution') + suspect_lcom4_density=measure('suspect_lcom4_density') + %> +<table width="100%"> + <tbody> + <tr> + <% if lcom %> + <td width="50%" valign="top"> + <div class="dashbox"> + <h3>LCOM4</h3> + <p><span class="big"><%= format_measure(lcom, :suffix => '', :default => '-', :url => url_for_drilldown('lcom4')) %> <%= tendency_icon(lcom, false) %></span> /class</p> + <p><%= format_measure(suspect_lcom4_density, :suffix => ' files having LCOM4>1', :url => url_for_drilldown('lcom4')) %> <%= tendency_icon(suspect_lcom4_density) %></p> + </div> + </td> + <% end %> + <% if rfc %> + <td width="50%" valign="top"> + <div class="dashbox"> + <h3>RFC</h3> + <p><span class="big"><%= format_measure(rfc, :suffix => '', :default => '-', :url => url_for_drilldown('rfc')) %> <%= tendency_icon(rfc, false) %></span> /class</p> + </div> + </td> + <% end %> + </tr> + <tr> + <td> + <% + if suspect_lcom4_density && suspect_lcom4_density.value>1.0 && lcom_distribution && !lcom_distribution.data.blank? + query="ck=distbar&c=777777&w=180&h=100&fs=8&bgc=ffffff&v=" + u(lcom_distribution.data) + %> + <a href="<%= url_for_drilldown('lcom4') -%>"><%= chart(query, :id => 'lcom4_distribution', :alt => '') -%></a> + <% end %> + </td> + <td> + <% + if rfc_distribution && !rfc_distribution.data.blank? + query="ck=distbar&c=777777&w=180&h=100&fs=8&bgc=ffffff&v=" + u(rfc_distribution.data) + %> + <a href="<%= url_for_drilldown('rfc') -%>"><%= chart(query, :id => 'rfc_distribution', :alt => '') -%></a> + <% end %> + </td> + </tr> + </tbody> +</table> +<% end %> diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/file_design.html.erb b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/file_design.html.erb new file mode 100644 index 00000000000..70041753975 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/file_design.html.erb @@ -0,0 +1,32 @@ +<% + file_tangle_index=measure('file_tangle_index') + if file_tangle_index + file_cycles=measure('file_cycles') + file_feedback_edges=measure('file_feedback_edges') +%> +<table width="100%"> + <tbody> + <tr> + <td valign="top"> + <div class="dashbox"> + <p class="title">File tangle index</p> + <p><span class="big"><%= format_measure(file_tangle_index, :suffix => '', :default => '-', :url => url_for_drilldown('file_tangle_index')) %> <%= tendency_icon(file_tangle_index, false) %></span></p> + <% if file_cycles %> + <p>> <%= format_measure(file_cycles, :suffix => ' cycles', :url => url_for_drilldown('file_cycles')) %></p> + <% end %> + </div> + </td> + <td valign="top"> + <% if file_feedback_edges %> + <div class="dashbox"> + <p class="title">Suspect file dependencies</p> + <p><span class="big"><%= format_measure(file_feedback_edges, :url => url_for_drilldown('file_feedback_edges')) %> <%= tendency_icon(file_feedback_edges) %></span></p> + </div> + <% end %> + </td> + </tr> + </tbody> +</table> +<% + end +%>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/package_design.html.erb b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/package_design.html.erb new file mode 100644 index 00000000000..59136259ee1 --- /dev/null +++ b/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/package_design.html.erb @@ -0,0 +1,38 @@ +<% + package_tangle_index=measure('package_tangle_index') + if package_tangle_index +%> +<table width="100%"> + <tbody> + <tr> + <% + if package_tangle_index + package_cycles=measure('package_cycles') + package_feedback_edges=measure('package_feedback_edges') + package_tangles=measure('package_tangles') + %> + <td valign="top"> + <div class="dashbox"> + <p class="title">Package tangle index</p> + <p><span class="big"><%= format_measure(package_tangle_index, :suffix => '', :default => '-', :url => url_for_drilldown('package_tangle_index')) %> <%= tendency_icon(package_tangle_index, false) %></span></p> + <% if package_cycles %> + <p>> <%= format_measure(package_cycles, :suffix => ' cycles', :url => url_for_drilldown('package_cycles')) %></p> + <% end %> + </div> + </td> + <td valign="top"> + <% if package_feedback_edges || package_tangles %> + <div class="dashbox"> + <p class="title">Dependencies to cut</p> + <p><%= format_measure(package_feedback_edges, :suffix => ' between packages', :url => url_for_drilldown('package_feedback_edges')) %> <%= tendency_icon(package_feedback_edges) %></p> + <p><%= format_measure(package_tangles, :suffix => ' between files', :url => url_for_drilldown('package_tangles')) %> <%= tendency_icon(package_tangles) %></p> + </div> + <% end %> + </td> + <% end %> + </tr> + </tbody> +</table> +<% + end +%>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/DsmSerializerTest.java b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/DsmSerializerTest.java new file mode 100644 index 00000000000..8b42373ccad --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/DsmSerializerTest.java @@ -0,0 +1,60 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.sonar.api.design.Dependency; +import org.sonar.api.resources.JavaPackage; +import org.sonar.api.resources.Resource; +import org.sonar.graph.DirectedGraph; +import org.sonar.graph.Dsm; +import org.sonar.graph.DsmManualSorter; + +import java.io.IOException; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class DsmSerializerTest { + @Test + public void serializeEmptyDsm() throws IOException { + Dsm dsm = new Dsm(new DirectedGraph()); + assertThat(DsmSerializer.serialize(dsm), is("[]")); + } + + @Test + public void serialize() throws IOException { + Resource foo = new JavaPackage("org.foo").setId(7); + Resource bar = new JavaPackage("org.bar").setId(8); + Dependency dep = new Dependency(foo, bar).setId(30l).setWeight(1); + + DirectedGraph<Resource, Dependency> graph = new DirectedGraph<Resource, Dependency>(); + graph.addVertex(foo); + graph.addVertex(bar); + graph.addEdge(dep); + + + Dsm<Resource> dsm = new Dsm<Resource>(graph); + DsmManualSorter.sort(dsm, bar, foo); // for test reproductibility + String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json")); + assertThat(DsmSerializer.serialize(dsm), is(json)); + } +} diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/MavenDependenciesSensorTest.java b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/MavenDependenciesSensorTest.java new file mode 100644 index 00000000000..3ab99fbc620 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/MavenDependenciesSensorTest.java @@ -0,0 +1,27 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.junit.Ignore; + +@Ignore +public class MavenDependenciesSensorTest { + +} diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/OldDependenciesPurgeTest.java b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/OldDependenciesPurgeTest.java new file mode 100644 index 00000000000..300139b78e3 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/OldDependenciesPurgeTest.java @@ -0,0 +1,40 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.junit.Test; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import java.sql.SQLException; + +public class OldDependenciesPurgeTest extends AbstractDbUnitTestCase { + + @Test + public void purgeOldDependencies() throws SQLException { + assertPurge("purgeOldDependencies"); + } + + private void assertPurge(String testName) { + setupData(testName); + new OldDependenciesPurge(getSession()).purge(null); + checkTables(testName, "dependencies"); + } + +} diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecoratorTest.java b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecoratorTest.java new file mode 100644 index 00000000000..28636be3167 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/SuspectLcom4DensityDecoratorTest.java @@ -0,0 +1,62 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.design.batch; + +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.JavaPackage; + +import java.util.Arrays; + +import static org.mockito.Mockito.*; + +public class SuspectLcom4DensityDecoratorTest { + + @Test + public void doNotDecorateFiles() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.FILES)).thenReturn(new Measure(CoreMetrics.FILES, 1.0)); + when(context.getMeasure(CoreMetrics.LCOM4)).thenReturn(newLcom4(3)); + + SuspectLcom4DensityDecorator decorator = new SuspectLcom4DensityDecorator(); + decorator.decorate(new JavaFile("org.foo.Bar"), context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.SUSPECT_LCOM4_DENSITY), anyDouble()); + } + + @Test + public void decoratePackages() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.FILES)).thenReturn(new Measure(CoreMetrics.FILES, 4.0)); + when(context.getChildrenMeasures(CoreMetrics.LCOM4)).thenReturn(Arrays.asList(newLcom4(1), newLcom4(3), newLcom4(5), newLcom4(1))); + + SuspectLcom4DensityDecorator decorator = new SuspectLcom4DensityDecorator(); + decorator.decorate(new JavaPackage("org.foo"), context); + + verify(context).saveMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY, 50.0); + } + + private Measure newLcom4(int lcom4) { + return new Measure(CoreMetrics.LCOM4, (double)lcom4); + } +} diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json new file mode 100644 index 00000000000..d0b8861b439 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json @@ -0,0 +1 @@ +[{"i":8,"n":"org.bar","q":"PAC","v":[{},{"i":30,"w":1}]},{"i":7,"n":"org.foo","q":"PAC","v":[{},{}]}]
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml new file mode 100644 index 00000000000..1ff8aa38516 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml @@ -0,0 +1,29 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>fake.group</groupId> + <artifactId>fake-artifact</artifactId> + <version>0.1-SNAPSHOT</version> + <name>Fake</name> + <dependencies> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.4</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>1.4</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.7</version> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies-result.xml b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies-result.xml new file mode 100644 index 00000000000..6b0bf1b88c4 --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies-result.xml @@ -0,0 +1,102 @@ +<dataset> + <!-- first project with one package --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="project" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="mygroup:myartifact:my.package" name="package" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <!-- second project with two packages --> + <projects long_name="[null]" id="3" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact2" name="project2" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="4" scope="DIR" qualifier="PAC" kee="mygroup:myartifact2:my.package" name="package" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="5" scope="DIR" qualifier="PAC" kee="mygroup:myartifact2:my.package2" name="package2" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + + <!-- old snapshots --> + <snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="1" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="2" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="3" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="3" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="4" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="4" + parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="3" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="5" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="5" + parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="3" status="P" islast="false" + path="[null]"/> + + <!-- last snapshots --> + <snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="1" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="7" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="6" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="8" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="3" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="9" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="8" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="10" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="8" status="P" islast="true" + path="[null]"/> + + + <!-- old dependencies --> + <!--<dependencies id="1" from_resource_id="3" from_snapshot_id="3" to_resource_id="1" to_snapshot_id="1"--> + <!--parent_dependency_id="[null]" project_snapshot_id="3"--> + <!--dep_usage="compile" dep_weight="1" from_scope="PRJ" to_scope="PRJ"/>--> + + <!--<dependencies id="2" from_resource_id="4" from_snapshot_id="4" to_resource_id="5" to_snapshot_id="5"--> + <!--parent_dependency_id="[null]" project_snapshot_id="3"--> + <!--dep_usage="uses" dep_weight="3" from_scope="DIR" to_scope="DIR"/>--> + + + <!-- last dependencies --> + <dependencies id="3" from_resource_id="3" from_snapshot_id="8" to_resource_id="1" to_snapshot_id="6" + parent_dependency_id="[null]" project_snapshot_id="8" + dep_usage="compile" dep_weight="1" from_scope="PRJ" to_scope="PRJ"/> + + <dependencies id="4" from_resource_id="4" from_snapshot_id="9" to_resource_id="5" to_snapshot_id="10" + parent_dependency_id="[null]" project_snapshot_id="8" + dep_usage="uses" dep_weight="3" from_scope="DIR" to_scope="DIR"/> + +</dataset>
\ No newline at end of file diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies.xml b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies.xml new file mode 100644 index 00000000000..5ffbb85ac9f --- /dev/null +++ b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/OldDependenciesPurgeTest/purgeOldDependencies.xml @@ -0,0 +1,102 @@ +<dataset> + <!-- first project with one package --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="project" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="mygroup:myartifact:my.package" name="package" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <!-- second project with two packages --> + <projects long_name="[null]" id="3" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact2" name="project2" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="4" scope="DIR" qualifier="PAC" kee="mygroup:myartifact2:my.package" name="package" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + <projects long_name="[null]" id="5" scope="DIR" qualifier="PAC" kee="mygroup:myartifact2:my.package2" name="package2" + root_id="[null]" + description="[null]" + enabled="true" language="java" copy_resource_id="[null]"/> + + + <!-- old snapshots --> + <snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="1" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="2" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="3" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="3" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="4" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="4" + parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="3" status="P" islast="false" + path="[null]"/> + + <snapshots depth="[null]" id="5" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="5" + parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="3" status="P" islast="false" + path="[null]"/> + + <!-- last snapshots --> + <snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="1" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="7" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="6" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="8" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="3" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="9" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="8" status="P" islast="true" + path="[null]"/> + + <snapshots depth="[null]" id="10" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]" + project_id="2" + parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="8" status="P" islast="true" + path="[null]"/> + + + <!-- old dependencies --> + <dependencies id="1" from_resource_id="3" from_snapshot_id="3" to_resource_id="1" to_snapshot_id="1" + parent_dependency_id="[null]" project_snapshot_id="3" + dep_usage="compile" dep_weight="1" from_scope="PRJ" to_scope="PRJ"/> + + <dependencies id="2" from_resource_id="4" from_snapshot_id="4" to_resource_id="5" to_snapshot_id="5" + parent_dependency_id="[null]" project_snapshot_id="3" + dep_usage="uses" dep_weight="3" from_scope="DIR" to_scope="DIR"/> + + + <!-- last dependencies --> + <dependencies id="3" from_resource_id="3" from_snapshot_id="8" to_resource_id="1" to_snapshot_id="6" + parent_dependency_id="[null]" project_snapshot_id="8" + dep_usage="compile" dep_weight="1" from_scope="PRJ" to_scope="PRJ"/> + + <dependencies id="4" from_resource_id="4" from_snapshot_id="9" to_resource_id="5" to_snapshot_id="10" + parent_dependency_id="[null]" project_snapshot_id="8" + dep_usage="uses" dep_weight="3" from_scope="DIR" to_scope="DIR"/> + +</dataset>
\ No newline at end of file |