Skip to content

Commit 6e0c086

Browse files
committed
very first version of ModelVisualizer
1 parent 807fdb1 commit 6e0c086

File tree

4 files changed

+176
-1
lines changed

4 files changed

+176
-1
lines changed

code-assert/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<dependency>
9090
<groupId>guru.nidi</groupId>
9191
<artifactId>graphviz-java</artifactId>
92-
<version>0.8.2</version>
92+
<version>0.8.3</version>
9393
</dependency>
9494
<dependency>
9595
<groupId>org.hamcrest</groupId>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright © 2015 Stefan Niederhauser ([email protected])
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package guru.nidi.codeassert.io;
17+
18+
import guru.nidi.codeassert.config.For;
19+
import guru.nidi.codeassert.jacoco.*;
20+
import guru.nidi.codeassert.model.*;
21+
import guru.nidi.graphviz.attribute.*;
22+
import guru.nidi.graphviz.engine.Graphviz;
23+
import guru.nidi.graphviz.model.*;
24+
25+
import java.util.Map;
26+
import java.util.function.Function;
27+
28+
import static guru.nidi.codeassert.config.CollectorConfig.just;
29+
import static guru.nidi.graphviz.model.Factory.mutGraph;
30+
import static guru.nidi.graphviz.model.Factory.mutNode;
31+
import static java.util.stream.Collectors.toMap;
32+
33+
public class ModelVisualizer {
34+
private final Model model;
35+
private final Function<CodePackage, String> labelFunc;
36+
37+
public ModelVisualizer(Model model) {
38+
this(model, CodePackage::getName);
39+
}
40+
41+
public ModelVisualizer(Model model, Function<CodePackage, String> labelFunc) {
42+
this.model = model;
43+
this.labelFunc = labelFunc;
44+
}
45+
46+
public ModelVisualizer labelFunc(Function<CodePackage, String> labelFunc) {
47+
return new ModelVisualizer(model, labelFunc);
48+
}
49+
50+
public Visualized visualize() {
51+
final Map<String, Double> coverage = new JacocoAnalyzer(new CoverageCollector(CoverageType.LINE)
52+
.config(just(For.allPackages().setMinima(100))))
53+
.analyze()
54+
.findings().stream()
55+
.collect(toMap(f -> f.getPack(), f -> f.getValues()[0]));
56+
final MutableGraph graph = CreationContext.use(ctx -> {
57+
final MutableGraph g = mutGraph().setDirected(true)
58+
.graphAttrs().add(RankDir.LEFT_TO_RIGHT);
59+
for (CodePackage pack : model.getPackages()) {
60+
final MutableNode source = mutNode(labelFunc.apply(pack)).add(Shape.ELLIPSE);
61+
if (model.isOwnPackage(pack)) {
62+
final Double cover = coverage.getOrDefault(pack.getName(), 1D);
63+
final int codeSize = pack.getClasses().stream().mapToInt(CodeClass::getTotalSize).sum();
64+
source.add(Shape.RECTANGLE)
65+
.add(Size.mode(Size.Mode.FIXED))
66+
.add("height", .5 + pack.getClasses().size() / 10.0)
67+
.add("width", 1 + codeSize / 20000.0)
68+
.add(Color.rgb(255 - (int) (2.55 * cover), (int) (2.55 * cover) - 255, 0).fill())
69+
.add(Style.FILLED);
70+
}
71+
g.add(source);
72+
for (CodePackage dep : pack.uses()) {
73+
source.addLink(labelFunc.apply(dep));
74+
}
75+
}
76+
return g;
77+
});
78+
return new Visualized(Graphviz.fromGraph(graph));
79+
}
80+
81+
public static Function<CodePackage, String> replaceFunc(String... replacements) {
82+
if (replacements.length % 2 != 0) {
83+
throw new IllegalArgumentException("An even number of replacement parameters expected.");
84+
}
85+
return codePackage -> {
86+
final String name = codePackage.getName();
87+
for (int i = 0; i < replacements.length; i += 2) {
88+
if (name.startsWith(replacements[i])) {
89+
return replacements[i + 1] + name.substring(replacements[i].length());
90+
}
91+
}
92+
return name;
93+
};
94+
}
95+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright © 2015 Stefan Niederhauser ([email protected])
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package guru.nidi.codeassert.io;
17+
18+
import guru.nidi.graphviz.engine.Format;
19+
import guru.nidi.graphviz.engine.Graphviz;
20+
21+
import java.awt.image.BufferedImage;
22+
import java.io.File;
23+
import java.io.IOException;
24+
25+
public class Visualized {
26+
private final Graphviz graphviz;
27+
28+
Visualized(Graphviz graphviz) {
29+
this.graphviz = graphviz;
30+
}
31+
32+
public void toFile(File target) throws IOException {
33+
graphviz.render(Format.PNG).toFile(target);
34+
}
35+
36+
public BufferedImage asImage() {
37+
return graphviz.render(Format.PNG).toImage();
38+
}
39+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright © 2015 Stefan Niederhauser ([email protected])
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package guru.nidi.codeassert.io;
17+
18+
import guru.nidi.codeassert.config.AnalyzerConfig;
19+
import guru.nidi.codeassert.model.Model;
20+
import org.junit.jupiter.api.Test;
21+
22+
import java.io.File;
23+
import java.io.IOException;
24+
25+
import static guru.nidi.codeassert.io.ModelVisualizer.replaceFunc;
26+
import static org.junit.jupiter.api.Assertions.assertTrue;
27+
28+
class ModelVisualizerTest {
29+
@Test
30+
void myself() throws IOException {
31+
final Model model = Model
32+
.from(AnalyzerConfig.maven().main().getClasses())
33+
.ignoringPackages("java", "org.hamcrest", "org.slf4j", "org.apache")
34+
.mergingPackages("edu.umd.cs.findbugs", "net.sourceforge.pmd", "io.gitlab.arturbosch.detekt", "com.puppycrawl.tools.checkstyle", "com.github.shyiko.ktlint", "kotlin", "org.junit", "guru.nidi.graphviz")
35+
.read();
36+
final ModelVisualizer visualizer = new ModelVisualizer(model).labelFunc(replaceFunc("guru.nidi.codeassert", ""));
37+
final File target = new File("target/out.png");
38+
visualizer.visualize().toFile(target);
39+
assertTrue(target.exists());
40+
}
41+
}

0 commit comments

Comments
 (0)