2 * JavaInspect - Utility to visualize java software
3 * Copyright (C) 2013-2015, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 3 of the GNU Lesser General Public License
7 * or later as published by the Free Software Foundation.
10 package eu.svjatoslav.inspector.java.structure;
12 import eu.svjatoslav.commons.file.CommonPathResolver;
13 import eu.svjatoslav.commons.string.WildCardMatcher;
14 import eu.svjatoslav.inspector.java.methods.Clazz;
15 import eu.svjatoslav.inspector.java.methods.ProjectScanner;
18 import java.io.IOException;
19 import java.io.PrintWriter;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
25 import static eu.svjatoslav.inspector.java.methods.JavaFile.UTF_8;
27 public class ClassGraph {
30 * Maps class fully qualified names to class descriptors.
32 private final Map<String, ClassDescriptor> fullyQualifiedNameToClassMap = new HashMap<String, ClassDescriptor>();
34 private final List<String> blacklistClassPatterns = new ArrayList<String>();
36 private final List<String> whitelistClassPatterns = new ArrayList<String>();
38 private String targetDirectory = CommonPathResolver.getDesktopDirectory()
39 .getAbsolutePath() + "/";
41 private boolean keepDotFile;
47 * @param objects objects that shall be added to graph
48 * @return this {@link ClassGraph}
50 public ClassGraph add(final Object... objects) {
53 for (final Object object : objects)
59 private void addObject(final Object object) {
60 if (object instanceof Class)
61 getOrCreateClassDescriptor((Class) object);
63 getOrCreateClassDescriptor(object.getClass());
67 * @param path path to recursively scan for java source code could be
68 * relative to current project or absolute
70 public void addProject(final String path) {
71 final ProjectScanner projectScanner = new ProjectScanner(new File(path));
72 for (final Clazz clazz : projectScanner.getAllClasses())
74 System.out.println("Class full name: " + clazz.getFullName());
75 final Class c = this.getClass().forName(clazz.getFullName());
77 } catch (final Exception exception) {
78 System.out.println("cannot add class: "
79 + exception.getMessage());
83 public void blacklistClassPattern(final String pattern) {
84 blacklistClassPatterns.add(pattern);
88 * @param resultFileName file name for the generated graph. File extension will be
89 * added automatically. Existing file with the same name will be
93 public void generateGraph(final String resultFileName) {
95 final String dotFilePath = targetDirectory + resultFileName + ".dot";
96 final String imageFilePath = targetDirectory + resultFileName + ".png";
98 System.out.println("Dot file path:" + dotFilePath);
101 // write DOT file to disk
102 final PrintWriter out = new PrintWriter(dotFilePath, UTF_8);
106 // execute GraphViz to visualize graph
109 .exec(new String[]{"dot", "-Tpng", dotFilePath, "-o",
110 imageFilePath}).waitFor();
111 } catch (final InterruptedException ignored) {
116 if (!new File(dotFilePath).delete()) throw new RuntimeException("Cannot delete file: " + dotFilePath);
117 } catch (final IOException e) {
118 System.err.println(e);
123 private String getDot() {
124 final StringBuffer result = new StringBuffer();
126 result.append("digraph Java {\n");
127 result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
129 for (final Map.Entry<String, ClassDescriptor> entry : fullyQualifiedNameToClassMap
131 result.append(entry.getValue().getDot());
133 result.append("}\n");
135 final String resultStr = result.toString();
140 * @param clazz class that shall be added to graph
141 * @return {@link ClassDescriptor} corresponding to given {@link Class}
143 protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) {
148 final String classFullyQualifiedName = clazz.getName();
150 // reuse existing instance if possible
151 if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName))
152 return fullyQualifiedNameToClassMap.get(classFullyQualifiedName);
154 // create new class descriptor
155 final ClassDescriptor newClassDescriptor = new ClassDescriptor(this);
156 fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
159 newClassDescriptor.analyzeClass(clazz);
161 return newClassDescriptor;
165 * Hide orphaned class that have no references
167 * @return this {@link ClassGraph}
169 public ClassGraph hideOrphanedClasses() {
171 for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap
173 classDescriptor.hideClassIfNoReferences();
178 protected boolean isClassShown(final String className) {
179 for (final String pattern : blacklistClassPatterns)
180 if (WildCardMatcher.match(className, pattern))
183 if (!whitelistClassPatterns.isEmpty()) {
184 for (final String pattern : whitelistClassPatterns)
185 if (WildCardMatcher.match(className, pattern))
193 public ClassGraph setKeepDotFile(final boolean keepDotFile) {
194 this.keepDotFile = keepDotFile;
199 public ClassGraph setTargetDirectory(String directoryPath) {
200 if (!directoryPath.endsWith("/"))
201 directoryPath += "/";
203 targetDirectory = directoryPath;
208 public ClassGraph whitelistClassPattern(final String pattern) {
209 whitelistClassPatterns.add(pattern);