import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
import org.sonar.api.component.Perspective;
+import org.sonar.core.graph.EdgePath;
import javax.annotation.CheckForNull;
public abstract T create(ComponentVertex component);
- public abstract Object[] storagePath();
+ public abstract EdgePath path();
}
package org.sonar.core.component;
import com.tinkerpop.blueprints.Graph;
+import org.apache.commons.io.IOUtils;
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.graphson.GraphsonMode;
+import org.sonar.core.graph.graphson.GraphsonWriter;
import org.sonar.core.graph.jdbc.GraphDto;
import org.sonar.core.graph.jdbc.GraphDtoMapper;
import org.sonar.core.persistence.BatchSession;
import org.sonar.core.persistence.MyBatis;
+import java.io.StringWriter;
+
public class ScanGraphStore {
private final MyBatis myBatis;
private final ScanGraph projectGraph;
BatchSession session = myBatis.openBatchSession();
GraphDtoMapper mapper = session.getMapper(GraphDtoMapper.class);
try {
- GraphWriter writer = new GraphWriter();
for (ComponentVertex component : projectGraph.getComponents()) {
Long snapshotId = (Long) component.element().getProperty("sid");
if (snapshotId != null) {
for (PerspectiveBuilder builder : builders) {
Perspective perspective = builder.load(component);
if (perspective != null) {
- Graph subGraph = SubGraph.extract(component.element(), builder.storagePath());
- String data = writer.write(subGraph);
+ Graph subGraph = SubGraph.extract(component.element(), builder.path());
+ String data = write(subGraph);
mapper.insert(new GraphDto()
.setData(data)
.setFormat("graphson")
session.close();
}
}
+
+ private String write(Graph graph) {
+ StringWriter output = new StringWriter();
+ try {
+ new GraphsonWriter().write(graph, output, GraphsonMode.EXTENDED);
+ return output.toString();
+ } finally {
+ IOUtils.closeQuietly(output);
+ }
+ }
}
--- /dev/null
+/*
+ * 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.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.tinkerpop.blueprints.Direction;
+
+import java.util.List;
+
+public class EdgePath {
+ private List<Object> elements;
+
+ private EdgePath(Object[] elements) {
+ Preconditions.checkArgument(elements != null && elements.length > 0, "Elements can't be null or empty");
+ Preconditions.checkArgument(elements.length % 2 == 0, "Odd number of elements (" + elements.length + ")");
+
+ for (int i = 0; i < elements.length; i++) {
+ if (i % 2 == 0) {
+ Preconditions.checkArgument(elements[i] instanceof Direction,
+ "Element " + i + " must be a " + Direction.class.getName() + " (got " + elements[i].getClass().getName() + ")");
+ } else {
+ Preconditions.checkArgument(elements[i] instanceof String,
+ "Element " + i + " must be a String" + " (got " + elements[i].getClass().getName() + ")");
+ }
+ }
+
+ this.elements = ImmutableList.copyOf(elements);
+ }
+
+ public List<Object> getElements() {
+ return elements;
+ }
+
+ public static EdgePath create(Object... elements) {
+ return new EdgePath(elements);
+ }
+}
+++ /dev/null
-/*
- * 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.Graph;
-import org.apache.commons.io.IOUtils;
-import org.sonar.core.graph.graphson.GraphsonMode;
-import org.sonar.core.graph.graphson.GraphsonWriter;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-public class GraphWriter {
-
- public String write(Graph graph) {
- StringWriter output = new StringWriter();
- try {
- new GraphsonWriter().write(graph, output, GraphsonMode.EXTENDED);
- System.out.println("------------------------------------------------");
- System.out.println(output.toString());
- System.out.println("------------------------------------------------");
- return output.toString();
- } finally {
- IOUtils.closeQuietly(output);
- }
- }
-}
import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
import com.tinkerpop.blueprints.util.ElementHelper;
+import java.util.List;
import java.util.Set;
/**
private SubGraph() {
}
- public static Graph extract(Vertex start, Object... edgePath) {
+ public static Graph extract(Vertex start, EdgePath edgePath) {
return new SubGraph().process(start, edgePath);
}
- private Graph process(Vertex start, Object... edgePath) {
+ private Graph process(Vertex start, EdgePath edgePath) {
copy(start);
- browse(start, 0, edgePath);
+ browse(start, 0, edgePath.getElements());
for (Edge edge : edgesToCopy) {
Vertex from = edge.getVertex(Direction.OUT);
Vertex to = edge.getVertex(Direction.IN);
return sub;
}
- private void browse(Vertex from, int cursor, Object... edgePath) {
+ private void browse(Vertex from, int cursor, List<Object> edgePath) {
if (from != null) {
- if (cursor < edgePath.length) {
- String edgeLabel = (String) edgePath[cursor];
- Direction edgeDirection = (Direction) edgePath[cursor + 1];
+ if (cursor < edgePath.size()) {
+ Direction edgeDirection = (Direction) edgePath.get(cursor);
+ String edgeLabel = (String) edgePath.get(cursor + 1);
Iterable<Edge> edges = from.getEdges(edgeDirection, edgeLabel);
for (Edge edge : edges) {
edgesToCopy.add(edge);
import org.sonar.api.test.MutableTestPlan;
import org.sonar.core.component.ComponentVertex;
import org.sonar.core.component.PerspectiveBuilder;
+import org.sonar.core.graph.EdgePath;
import org.sonar.core.graph.GraphUtil;
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
- };
+ private static final EdgePath PATH = EdgePath.create(
+ Direction.OUT, "testplan",
+ Direction.OUT, "testcase",
+ Direction.OUT, "covers",
+ Direction.IN, "testable"
+ );
public TestPlanBuilder() {
super(PERSPECTIVE_KEY, MutableTestPlan.class);
}
@Override
- public Object[] storagePath() {
+ public EdgePath path() {
return PATH;
}
}
import com.tinkerpop.blueprints.Vertex;
import org.sonar.api.test.MutableTestable;
import org.sonar.core.component.ComponentVertex;
+import org.sonar.core.graph.EdgePath;
import org.sonar.core.component.PerspectiveBuilder;
import org.sonar.core.graph.GraphUtil;
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
- };
+ private static final EdgePath PATH = EdgePath.create(
+ Direction.OUT, "testable",
+ Direction.IN,"covers",
+ Direction.IN,"testcase",
+ Direction.IN,"testplan"
+ );
public TestableBuilder() {
super(PERSPECTIVE_KEY, MutableTestable.class);
}
@Override
- public Object[] storagePath() {
+ public EdgePath path() {
return PATH;
}
}
@Test
public void should_create_bean_vertex() {
- TinkerGraph graph = new TinkerGraph();
- BeanGraph beanGraph = new BeanGraph(graph);
+ BeanGraph beanGraph = BeanGraph.createInMemory();
Person person = beanGraph.createVertex(Person.class);
assertThat(person).isNotNull();
@Test
public void should_create_adjacent_bean_vertex() {
- TinkerGraph graph = new TinkerGraph();
- BeanGraph beanGraph = new BeanGraph(graph);
+ BeanGraph beanGraph = BeanGraph.createInMemory();
Person person = beanGraph.createVertex(Person.class);
Person adjacent = beanGraph.createAdjacentVertex(person, Person.class, "knows", "type", "family");
--- /dev/null
+/*
+ * 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class EdgePathTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void create_valid_edge_path() {
+ EdgePath path = EdgePath.create(Direction.OUT, "knows", Direction.OUT, "has");
+
+ assertThat(path).isNotNull();
+ assertThat(path.getElements()).hasSize(4);
+ assertThat(path.getElements().get(0)).isEqualTo(Direction.OUT);
+ assertThat(path.getElements().get(1)).isEqualTo("knows");
+ assertThat(path.getElements().get(2)).isEqualTo(Direction.OUT);
+ assertThat(path.getElements().get(3)).isEqualTo("has");
+ }
+
+ @Test
+ public void should_have_even_number_of_elements() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Odd number of elements (3)");
+ EdgePath.create(Direction.OUT, "knows", Direction.OUT);
+ }
+
+ @Test
+ public void should_have_sequence_of_directions_and_strings_1() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Element 0 must be a com.tinkerpop.blueprints.Direction (got java.lang.String)");
+
+ EdgePath.create("knows", Direction.OUT);
+ }
+
+ @Test
+ public void should_have_sequence_of_directions_and_strings_2() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Element 1 must be a String (got com.tinkerpop.blueprints.Direction)");
+
+ EdgePath.create(Direction.OUT, Direction.OUT);
+ }
+}
// a -uses-> b -inherits -> c
// a -uses-> d -implements-> e
- Graph sub = SubGraph.extract(a, "uses", Direction.OUT, "implements", Direction.OUT);
+ Graph sub = SubGraph.extract(a, EdgePath.create(Direction.OUT, "uses", Direction.OUT, "implements"));
// a -uses-> b
// a -uses-> d -implements-> e
// a -uses-> b -implements-> c -package-> e
// a -uses-> d -implements-> c -package-> e
- Graph sub = SubGraph.extract(a, "uses", Direction.OUT, "implements", Direction.OUT, "package", Direction.OUT);
+ Graph sub = SubGraph.extract(a, EdgePath.create(Direction.OUT, "uses", Direction.OUT, "implements", Direction.OUT, "package"));
// same graph
assertThat(sub.getVertices()).hasSize(5);
// a -uses-> b -inherits -> c
// a -uses-> d -implements-> e
- Graph sub = SubGraph.extract(a, "uses", Direction.IN /* instead of out */, "implements", Direction.OUT);
+ Graph sub = SubGraph.extract(a, EdgePath.create(Direction.IN /* instead of out */, "uses", Direction.OUT, "implements"));
assertThat(sub.getVertices()).hasSize(1);
assertThat(sub.getVertex(a.getId())).isNotNull();
*/
package org.sonar.core.test;
+import com.google.common.collect.Iterables;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.test.exception.IllegalDurationException;
+import org.sonar.api.test.Cover;
import org.sonar.api.test.TestCase;
+import org.sonar.api.test.exception.IllegalDurationException;
import org.sonar.core.graph.BeanGraph;
import java.util.Arrays;
}
@Test
- public void should_cover_testables() {
+ public void should_cover_testable() {
+ BeanGraph beanGraph = BeanGraph.createInMemory();
+ DefaultTestable testable = beanGraph.createVertex(DefaultTestable.class);
+ DefaultTestCase testCase = beanGraph.createVertex(DefaultTestCase.class);
+ testCase.setCover(testable, Arrays.asList(10, 11, 12));
+
+ assertThat(testCase.doesCover()).isTrue();
+ assertThat(testCase.countCoveredLines()).isEqualTo(3);
+ assertThat(testCase.covers()).hasSize(1);
+
+ Cover cover = Iterables.<Cover>getFirst(testCase.covers(), null);
+ assertThat(cover.testCase()).isEqualTo(testCase);
+ assertThat(cover.testable()).isSameAs(testable);
+ assertThat(cover.lines()).containsExactly(10, 11, 12);
+ }
+
+ @Test
+ public void should_cover_multiple_testables() {
BeanGraph beanGraph = BeanGraph.createInMemory();
DefaultTestable testable1 = beanGraph.createVertex(DefaultTestable.class);
DefaultTestable testable2 = beanGraph.createVertex(DefaultTestable.class);
plan.addTestCase("T2");
assertThat(plan.testCases()).hasSize(2);
- assertThat(Iterables.<MutableTestCase>get(plan.testCases(), 0).key()).isEqualTo("T1");
- assertThat(Iterables.<MutableTestCase>get(plan.testCases(), 1).key()).isEqualTo("T2");
+ MutableTestCase firstTestCase = Iterables.get(plan.testCases(), 0);
+ assertThat(firstTestCase.key()).isEqualTo("T1");
+ assertThat(firstTestCase.testPlan()).isSameAs(plan);
+
+ MutableTestCase secondTestCase = Iterables.get(plan.testCases(), 1);
+ assertThat(secondTestCase.key()).isEqualTo("T2");
+ assertThat(secondTestCase.testPlan()).isSameAs(plan);
}
@Test
testCase2.setCover(testable, Arrays.asList(12, 48, 49));
assertThat(testable.testedLines()).containsOnly(10, 11, 12, 48, 49);
+ assertThat(testable.countTestCasesOfLine(2)).isEqualTo(0);
+ assertThat(testable.countTestCasesOfLine(10)).isEqualTo(1);
+ assertThat(testable.countTestCasesOfLine(12)).isEqualTo(2);
}
@Test
--- /dev/null
+/*
+ * 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.test;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class TestableBuilderTest {
+ @Test
+ public void storagePath() {
+ TestableBuilder builder = new TestableBuilder();
+
+ assertThat(builder.path().getElements()).isNotEmpty();
+ }
+}