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 public ClassGraph add(final Object... objects) {
51 for (final Object object : objects)
57 private void addObject(final Object object) {
58 if (object instanceof Class)
59 getOrCreateClassDescriptor((Class) object);
61 getOrCreateClassDescriptor(object.getClass());
66 * path to recursively scan for java source code could be
67 * relative to current project or absolute
69 public void addProject(final String path) {
70 final ProjectScanner projectScanner = new ProjectScanner(new File(path));
71 for (final Clazz clazz : projectScanner.getAllClasses())
73 System.out.println("Class full name: " + clazz.getFullName());
74 final Class c = this.getClass().forName(clazz.getFullName());
76 } catch (final Exception exception) {
77 System.out.println("cannot add class: "
78 + exception.getMessage());
82 public void blacklistClassPattern(final String pattern) {
83 blacklistClassPatterns.add(pattern);
87 * @param targetDirectory
88 * target directory name
90 * @param resultFileName
91 * file name for the generated graph. File extension will be
92 * added automatically. Existing file with the same name will be
96 * if set to <code>true</code> then intermediary GraphViz DOT
100 public void generateGraph(final String resultFileName) {
102 final String dotFilePath = targetDirectory + resultFileName + ".dot";
103 final String imageFilePath = targetDirectory + resultFileName + ".png";
105 System.out.println("Dot file path:" + dotFilePath);
108 // write DOT file to disk
109 final PrintWriter out = new PrintWriter(dotFilePath);
113 // execute GraphViz to visualize graph
116 .exec(new String[] { "dot", "-Tpng", dotFilePath, "-o",
117 imageFilePath }).waitFor();
118 } catch (final InterruptedException e) {
124 new File(dotFilePath).delete();
126 } catch (final IOException e) {
127 System.err.println(e);
132 private String getDot() {
133 final StringBuffer result = new StringBuffer();
135 result.append("digraph Java {\n");
136 result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
138 for (final Map.Entry<String, ClassDescriptor> entry : fullyQualifiedNameToClassMap
140 result.append(entry.getValue().getDot());
142 result.append("}\n");
144 final String resultStr = result.toString();
150 * class that shall be added to graph
152 protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) {
157 final String classFullyQualifiedName = clazz.getName();
159 // reuse existing instance if possible
160 if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName))
161 return fullyQualifiedNameToClassMap.get(classFullyQualifiedName);
163 // create new class descriptor
164 final ClassDescriptor newClassDescriptor = new ClassDescriptor(this);
165 fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
168 newClassDescriptor.analyzeClass(clazz);
170 return newClassDescriptor;
174 * Hide orphaned class that have no references
176 public void hideOrphanedClasses() {
178 for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap
180 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);