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;
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
20 import eu.svjatoslav.commons.file.CommonPathResolver;
21 import eu.svjatoslav.commons.string.WildCardMatcher;
22 import eu.svjatoslav.inspector.java.methods.Clazz;
23 import eu.svjatoslav.inspector.java.methods.ProjectScanner;
25 public class ClassGraph {
28 * Maps class fully qualified names to class descriptors.
30 private final Map<String, ClassDescriptor> fullyQualifiedNameToClassMap = new HashMap<String, ClassDescriptor>();
32 private final List<String> blacklistClassPatterns = new ArrayList<String>();
34 private final List<String> whitelistClassPatterns = new ArrayList<String>();
36 private String targetDirectory = CommonPathResolver.getDesktopDirectory()
37 .getAbsolutePath() + "/";
39 private boolean keepDotFile;
46 * 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());
68 * path to recursively scan for java source code could be
69 * relative to current project or absolute
71 public void addProject(final String path) {
72 final ProjectScanner projectScanner = new ProjectScanner(new File(path));
73 for (final Clazz clazz : projectScanner.getAllClasses())
75 System.out.println("Class full name: " + clazz.getFullName());
76 final Class c = this.getClass().forName(clazz.getFullName());
78 } catch (final Exception exception) {
79 System.out.println("cannot add class: "
80 + exception.getMessage());
84 public void blacklistClassPattern(final String pattern) {
85 blacklistClassPatterns.add(pattern);
89 * @param resultFileName
90 * file name for the generated graph. File extension will be
91 * added automatically. Existing file with the same name will be
96 public void generateGraph(final String resultFileName) {
98 final String dotFilePath = targetDirectory + resultFileName + ".dot";
99 final String imageFilePath = targetDirectory + resultFileName + ".png";
101 System.out.println("Dot file path:" + dotFilePath);
104 // write DOT file to disk
105 final PrintWriter out = new PrintWriter(dotFilePath);
109 // execute GraphViz to visualize graph
112 .exec(new String[] { "dot", "-Tpng", dotFilePath, "-o",
113 imageFilePath }).waitFor();
114 } catch (final InterruptedException e) {
120 new File(dotFilePath).delete();
121 } catch (final IOException e) {
122 System.err.println(e);
127 private String getDot() {
128 final StringBuffer result = new StringBuffer();
130 result.append("digraph Java {\n");
131 result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
133 for (final Map.Entry<String, ClassDescriptor> entry : fullyQualifiedNameToClassMap
135 result.append(entry.getValue().getDot());
137 result.append("}\n");
139 final String resultStr = result.toString();
145 * class that shall be added to graph
147 * @return {@link ClassDescriptor} corresponding to given {@link Class}
149 protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) {
154 final String classFullyQualifiedName = clazz.getName();
156 // reuse existing instance if possible
157 if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName))
158 return fullyQualifiedNameToClassMap.get(classFullyQualifiedName);
160 // create new class descriptor
161 final ClassDescriptor newClassDescriptor = new ClassDescriptor(this);
162 fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
165 newClassDescriptor.analyzeClass(clazz);
167 return newClassDescriptor;
171 * Hide orphaned class that have no references
173 * @return this {@link ClassGraph}
175 public ClassGraph hideOrphanedClasses() {
177 for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap
179 classDescriptor.hideClassIfNoReferences();
184 protected boolean isClassShown(final String className) {
185 for (final String pattern : blacklistClassPatterns)
186 if (WildCardMatcher.match(className, pattern))
189 if (!whitelistClassPatterns.isEmpty()) {
190 for (final String pattern : whitelistClassPatterns)
191 if (WildCardMatcher.match(className, pattern))
199 public ClassGraph setKeepDotFile(final boolean keepDotFile) {
200 this.keepDotFile = keepDotFile;
205 public ClassGraph setTargetDirectory(String directoryPath) {
206 if (!directoryPath.endsWith("/"))
207 directoryPath += "/";
209 targetDirectory = directoryPath;
214 public ClassGraph whitelistClassPattern(final String pattern) {
215 whitelistClassPatterns.add(pattern);