diff options
7 files changed, 179 insertions, 6 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java b/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java index feef7ac8dfa..2e7cef03a6a 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java +++ b/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java @@ -19,6 +19,8 @@ */ package org.sonar.core.component; +import com.tinkerpop.blueprints.Graph; +import com.tinkerpop.blueprints.Vertex; import org.sonar.api.BatchComponent; import org.sonar.api.ServerComponent; import org.sonar.api.component.Perspective; @@ -48,4 +50,6 @@ public abstract class PerspectiveBuilder<T extends Perspective> implements Batch public abstract T create(ComponentVertex component); + public abstract Object[] path(); + } diff --git a/sonar-core/src/main/java/org/sonar/core/component/ScanGraphStore.java b/sonar-core/src/main/java/org/sonar/core/component/ScanGraphStore.java index 2baaddc271c..3ed2220d7fd 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/ScanGraphStore.java +++ b/sonar-core/src/main/java/org/sonar/core/component/ScanGraphStore.java @@ -19,10 +19,11 @@ */ package org.sonar.core.component; -import com.tinkerpop.blueprints.impls.tg.TinkerGraph; +import com.tinkerpop.blueprints.Graph; import org.slf4j.LoggerFactory; import org.sonar.api.component.Perspective; import org.sonar.core.graph.GraphWriter; +import org.sonar.core.graph.SubGraph; import org.sonar.core.graph.jdbc.GraphDto; import org.sonar.core.graph.jdbc.GraphDtoMapper; import org.sonar.core.persistence.BatchSession; @@ -44,7 +45,6 @@ public class ScanGraphStore { BatchSession session = myBatis.openBatchSession(); GraphDtoMapper mapper = session.getMapper(GraphDtoMapper.class); try { - TinkerGraph subGraph = new TinkerGraph(); GraphWriter writer = new GraphWriter(); for (ComponentVertex component : projectGraph.getComponents()) { Long snapshotId = (Long) component.element().getProperty("sid"); @@ -52,7 +52,8 @@ public class ScanGraphStore { for (PerspectiveBuilder builder : builders) { Perspective perspective = builder.load(component); if (perspective != null) { - String data = writer.write(projectGraph.getUnderlyingGraph()); + Graph subGraph = SubGraph.extract(component.element(), builder.path()); + String data = writer.write(subGraph); mapper.insert(new GraphDto() .setData(data) .setFormat("graphson") @@ -62,7 +63,6 @@ public class ScanGraphStore { .setSnapshotId(snapshotId) .setRootVertexId(component.element().getId().toString()) ); - subGraph.clear(); } } } diff --git a/sonar-core/src/main/java/org/sonar/core/graph/SubGraph.java b/sonar-core/src/main/java/org/sonar/core/graph/SubGraph.java new file mode 100644 index 00000000000..530b13155ed --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/graph/SubGraph.java @@ -0,0 +1,78 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * 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.core.graph; + +import com.google.common.collect.Lists; +import com.tinkerpop.blueprints.Direction; +import com.tinkerpop.blueprints.Edge; +import com.tinkerpop.blueprints.Graph; +import com.tinkerpop.blueprints.Vertex; +import com.tinkerpop.blueprints.impls.tg.TinkerGraph; +import com.tinkerpop.blueprints.util.ElementHelper; + +import java.util.List; + +/** + * Not thread-safe + */ +public class SubGraph { + + private TinkerGraph sub = new TinkerGraph(); + private List<Edge> edgesToCopy = Lists.newArrayList(); + + private SubGraph() { + } + + private Graph process(Vertex start, Object... edgePath) { + browse(start, 0, edgePath); + for (Edge edge : edgesToCopy) { + Vertex from = edge.getVertex(Direction.IN); + Vertex to = edge.getVertex(Direction.OUT); + Edge copyEdge = sub.addEdge(edge.getId(), sub.getVertex(from.getId()), sub.getVertex(to.getId()), edge.getLabel()); + ElementHelper.copyProperties(edge, copyEdge); + } + return sub; + } + + public static Graph extract(Vertex start, Object... edgePath) { + return new SubGraph().process(start, edgePath); + } + + private void browse(Vertex vertex, int cursor, Object... edgePath) { + if (vertex != null) { + copy(vertex); + if (cursor < edgePath.length) { + String edgeLabel = (String) edgePath[cursor]; + Direction edgeDirection = (Direction) edgePath[cursor + 1]; + Iterable<Edge> edges = vertex.getEdges(edgeDirection, edgeLabel); + for (Edge edge : edges) { + edgesToCopy.add(edge); + browse(edge.getVertex(edgeDirection.opposite()), cursor + 2, edgePath); + } + } + } + } + + private Vertex copy(Vertex v) { + Vertex to = sub.addVertex(v.getId()); + ElementHelper.copyProperties(v, to); + return to; + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/test/TestPlanBuilder.java b/sonar-core/src/main/java/org/sonar/core/test/TestPlanBuilder.java index 07a5d0e117e..5d3cbf207a6 100644 --- a/sonar-core/src/main/java/org/sonar/core/test/TestPlanBuilder.java +++ b/sonar-core/src/main/java/org/sonar/core/test/TestPlanBuilder.java @@ -22,7 +22,6 @@ package org.sonar.core.test; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Vertex; import org.sonar.api.test.MutableTestPlan; -import org.sonar.api.test.TestPlan; import org.sonar.core.component.ComponentVertex; import org.sonar.core.component.PerspectiveBuilder; import org.sonar.core.graph.GraphUtil; @@ -31,6 +30,13 @@ public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> { static final String PERSPECTIVE_KEY = "testplan"; + private static final Object[] PATH = new Object[]{ + "testplan", Direction.OUT, + "testcase", Direction.OUT, + "covers", Direction.OUT, + "testable", Direction.IN + }; + public TestPlanBuilder() { super(PERSPECTIVE_KEY, MutableTestPlan.class); } @@ -48,4 +54,9 @@ public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> { public MutableTestPlan create(ComponentVertex component) { return component.beanGraph().createAdjacentVertex(component, DefaultTestPlan.class, PERSPECTIVE_KEY); } + + @Override + public Object[] path() { + return PATH; + } } diff --git a/sonar-core/src/main/java/org/sonar/core/test/TestableBuilder.java b/sonar-core/src/main/java/org/sonar/core/test/TestableBuilder.java index 6954a0932ff..009773ea117 100644 --- a/sonar-core/src/main/java/org/sonar/core/test/TestableBuilder.java +++ b/sonar-core/src/main/java/org/sonar/core/test/TestableBuilder.java @@ -30,6 +30,13 @@ public class TestableBuilder extends PerspectiveBuilder<MutableTestable> { static final String PERSPECTIVE_KEY = "testable"; + private static final Object[] PATH = new Object[]{ + "testable", Direction.OUT, + "covers", Direction.IN, + "testcase", Direction.IN, + "testplan", Direction.IN + }; + public TestableBuilder() { super(PERSPECTIVE_KEY, MutableTestable.class); } @@ -47,4 +54,9 @@ public class TestableBuilder extends PerspectiveBuilder<MutableTestable> { public MutableTestable create(ComponentVertex component) { return component.beanGraph().createAdjacentVertex(component, DefaultTestable.class, PERSPECTIVE_KEY); } + + @Override + public Object[] path() { + return PATH; + } } diff --git a/sonar-core/src/test/java/org/sonar/core/graph/SubGraphTest.java b/sonar-core/src/test/java/org/sonar/core/graph/SubGraphTest.java new file mode 100644 index 00000000000..7c46193fbdc --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/graph/SubGraphTest.java @@ -0,0 +1,68 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * 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.core.graph; + +import com.tinkerpop.blueprints.Direction; +import com.tinkerpop.blueprints.Edge; +import com.tinkerpop.blueprints.Graph; +import com.tinkerpop.blueprints.Vertex; +import com.tinkerpop.blueprints.impls.tg.TinkerGraph; +import com.tinkerpop.blueprints.util.GraphHelper; +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class SubGraphTest { + @Test + public void extract_acyclic_graph() { + TinkerGraph graph = new TinkerGraph(); + Vertex a = GraphHelper.addVertex(graph, null, "key", "a"); + Vertex b = GraphHelper.addVertex(graph, null, "key", "b"); + Vertex c = GraphHelper.addVertex(graph, null, "key", "c"); + Vertex d = GraphHelper.addVertex(graph, null, "key", "d"); + Vertex e = GraphHelper.addVertex(graph, null, "key", "e"); + + Edge ab = GraphHelper.addEdge(graph, null, a, b, "uses"); + Edge bc = GraphHelper.addEdge(graph, null, b, c, "inherits"); + Edge ad = GraphHelper.addEdge(graph, null, a, d, "uses"); + Edge de = GraphHelper.addEdge(graph, null, d, e, "implements"); + + // a -uses-> b -inherits -> c + // a -uses-> d -implements-> e + + Graph sub = SubGraph.extract(a, "uses", Direction.OUT, "implements", Direction.OUT); + + // a -uses-> b + // a -uses-> d -implements-> e + assertThat(sub.getVertices()).hasSize(4); + assertThat(sub.getVertex(a.getId()).getProperty("key")).isEqualTo("a"); + assertThat(sub.getVertex(b.getId()).getProperty("key")).isEqualTo("b"); + assertThat(sub.getVertex(c.getId())).isNull(); + assertThat(sub.getVertex(d.getId()).getProperty("key")).isEqualTo("d"); + assertThat(sub.getVertex(e.getId()).getProperty("key")).isEqualTo("e"); + + assertThat(sub.getEdges()).hasSize(3); + assertThat(sub.getEdge(ab.getId()).getLabel()).isEqualTo("uses"); + assertThat(sub.getEdge(ab.getId()).getId()).isEqualTo(ab.getId()); + assertThat(sub.getEdge(bc.getId())).isNull(); + assertThat(sub.getEdge(ad.getId()).getId()).isEqualTo(ad.getId()); + assertThat(sub.getEdge(de.getId()).getId()).isEqualTo(de.getId()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java index 190cab0c055..4fb387ba070 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java @@ -23,7 +23,7 @@ import java.util.Collection; public interface TestCase { String TYPE_UNIT = "unit"; - String TYPE_INTEGRATION = "integ"; + String TYPE_INTEGRATION = "integration"; String STATUS_PASS = "pass"; String STATUS_FAIL = "fail"; |