bugfix: fields shall not be static
[javainspect.git] / src / main / java / eu / svjatoslav / inspector / java / structure / ClassGraph.java
1 /*
2  * JavaInspect - Utility to visualize java software
3  * Copyright (C) 2013, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License
7  * as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.inspector.java.structure;
11
12 import java.io.File;
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import eu.svjatoslav.commons.file.CommonPathResolver;
19 import eu.svjatoslav.inspector.java.methods.Clazz;
20 import eu.svjatoslav.inspector.java.methods.ProjectScanner;
21
22 public class ClassGraph {
23
24         public static void render(final String graphName, final Class... classes) {
25                 final ClassGraph classGraph = new ClassGraph(classes);
26
27                 classGraph.generateGraph(graphName);
28         }
29
30         /**
31          * Maps class fully qualified names to class descriptors.
32          */
33         Map<String, ClassDescriptor> nameToClassMap = new HashMap<String, ClassDescriptor>();
34
35         private Filter filter = new Filter();
36
37         public ClassGraph() {
38         }
39
40         /**
41          * @param classes
42          *            classes that shall be added to graph
43          */
44         public ClassGraph(final Class<? extends Object>... classes) {
45                 for (final Class<? extends Object> clazz : classes)
46                         addClass(clazz);
47         }
48
49         /**
50          * @param objects
51          *            objects that shall be added to graph
52          */
53         public ClassGraph(final Object... objects) {
54                 for (Object object : objects)
55                         addClass(object.getClass());
56         }
57
58         /**
59          * @param clazz
60          *            class that shall be added to graph
61          */
62         public ClassDescriptor addClass(final Class<? extends Object> clazz) {
63
64                 if (clazz == null)
65                         return null;
66
67                 final String className = clazz.getName();
68
69                 if (nameToClassMap.containsKey(className))
70                         return nameToClassMap.get(className);
71
72                 return new ClassDescriptor(clazz, this);
73         }
74
75         /**
76          * @param object
77          *            object that shall be added to graph
78          */
79         public ClassDescriptor addObject(final Object object) {
80                 return addClass(object.getClass());
81         }
82
83         /**
84          * @param path
85          *            path to recursively scan for java source code could be
86          *            relative to current project or absolute
87          */
88         public void addProject(final String path) {
89                 final ProjectScanner projectScanner = new ProjectScanner(new File(path));
90                 for (final Clazz clazz : projectScanner.getAllClasses())
91                         try {
92                                 System.out.println("Class full name: " + clazz.getFullName());
93                                 final Class c = this.getClass().forName(clazz.getFullName());
94                                 addClass(c);
95                         } catch (final Exception exception) {
96                                 System.out.println("cannot add class: "
97                                                 + exception.getMessage());
98                         }
99         }
100
101         /**
102          * @param resultFileName
103          *            file name for the generated graph. Existing file with the same
104          *            name will be overwritten.
105          */
106         public void generateGraph(final String resultFileName) {
107                 generateGraph(resultFileName, false);
108         }
109
110         /**
111          * @param resultFileName
112          *            file name for the generated graph. File extension will be
113          *            added automatically. Existing file with the same name will be
114          *            overwritten.
115          * 
116          * @param keepDotFile
117          *            if set to <code>true</code> then intermediary GraphViz DOT
118          *            file will be kept.
119          */
120
121         public void generateGraph(final String resultFileName,
122                         final boolean keepDotFile) {
123
124                 final String desktopPath = CommonPathResolver.getDesktopDirectory()
125                                 .getAbsolutePath() + "/";
126
127                 final String dotFilePath = desktopPath + resultFileName + ".dot";
128                 final String imageFilePath = desktopPath + resultFileName + ".png";
129
130                 System.out.println("Dot file path:" + dotFilePath);
131
132                 try {
133                         // write DOT file to disk
134                         final PrintWriter out = new PrintWriter(dotFilePath);
135                         out.write(getDot());
136                         out.close();
137
138                         // execute GraphViz to visualize graph
139                         try {
140                                 Runtime.getRuntime()
141                                 .exec(new String[] { "dot", "-Tpng", dotFilePath, "-o",
142                                                 imageFilePath }).waitFor();
143                         } catch (final InterruptedException e) {
144                         } finally {
145                         }
146
147                         if (!keepDotFile) {
148                                 // delete dot file
149                                 final File dotFile = new File(dotFilePath);
150                                 dotFile.delete();
151                         }
152                 } catch (final IOException e) {
153                         System.err.println(e);
154                 }
155         }
156
157         private String getDot() {
158                 final StringBuffer result = new StringBuffer();
159
160                 result.append("digraph Java {\n");
161                 result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
162
163                 for (final Map.Entry<String, ClassDescriptor> entry : nameToClassMap
164                                 .entrySet())
165                         result.append(entry.getValue().getDot());
166
167                 result.append("}\n");
168
169                 final String resultStr = result.toString();
170                 return resultStr;
171         }
172
173         /**
174          * Hide orphaned class that have no references
175          */
176         public void hideOrphanedClasses() {
177
178                 for (final ClassDescriptor classDescriptor : nameToClassMap.values())
179                         classDescriptor.hideClassIfNoReferences();
180
181         }
182
183         public Filter getFilter() {
184                 return filter;
185         }
186
187         public void setFilter(Filter filter) {
188                 this.filter = filter;
189         }
190
191 }