/*
* JavaInspect - Utility to visualize java software
- * Copyright (C) 2013, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- *
+ * Copyright (C) 2013-2015, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
*/
package eu.svjatoslav.inspector.java.structure;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import eu.svjatoslav.commons.file.CommonPathResolver;
+import eu.svjatoslav.commons.string.WildCardMatcher;
import eu.svjatoslav.inspector.java.methods.Clazz;
import eu.svjatoslav.inspector.java.methods.ProjectScanner;
public class ClassGraph {
- public static void render(final String graphName, final Class... classes) {
- final ClassGraph classGraph = new ClassGraph(classes);
-
- classGraph.generateGraph(graphName);
- }
-
/**
* Maps class fully qualified names to class descriptors.
*/
- Map<String, ClassDescriptor> nameToClassMap = new HashMap<String, ClassDescriptor>();
+ private final Map<String, ClassDescriptor> fullyQualifiedNameToClassMap = new HashMap<String, ClassDescriptor>();
- private Filter filter = new Filter();
+ private final List<String> blacklistClassPatterns = new ArrayList<String>();
- public ClassGraph() {
- }
+ private final List<String> whitelistClassPatterns = new ArrayList<String>();
- /**
- * @param classes
- * classes that shall be added to graph
- */
- public ClassGraph(final Class<? extends Object>... classes) {
- for (final Class<? extends Object> clazz : classes)
- addClass(clazz);
+ private String targetDirectory = CommonPathResolver.getDesktopDirectory()
+ .getAbsolutePath() + "/";
+
+ private boolean keepDotFile;
+
+ public ClassGraph() {
}
/**
* @param objects
* objects that shall be added to graph
*/
- public ClassGraph(final Object... objects) {
- for (Object object : objects)
- addClass(object.getClass());
- }
+ public ClassGraph add(final Object... objects) {
- /**
- * @param clazz
- * class that shall be added to graph
- */
- public ClassDescriptor addClass(final Class<? extends Object> clazz) {
-
- if (clazz == null)
- return null;
+ if (objects != null)
+ for (final Object object : objects)
+ addObject(object);
- final String className = clazz.getName();
-
- if (nameToClassMap.containsKey(className))
- return nameToClassMap.get(className);
-
- return new ClassDescriptor(clazz, this);
+ return this;
}
- /**
- * @param object
- * object that shall be added to graph
- */
- public ClassDescriptor addObject(final Object object) {
- return addClass(object.getClass());
+ private void addObject(final Object object) {
+ if (object instanceof Class)
+ getOrCreateClassDescriptor((Class) object);
+ else
+ getOrCreateClassDescriptor(object.getClass());
}
/**
try {
System.out.println("Class full name: " + clazz.getFullName());
final Class c = this.getClass().forName(clazz.getFullName());
- addClass(c);
+ addObject(c);
} catch (final Exception exception) {
System.out.println("cannot add class: "
+ exception.getMessage());
}
}
- /**
- * @param resultFileName
- * file name for the generated graph. Existing file with the same
- * name will be overwritten.
- */
- public void generateGraph(final String resultFileName) {
- generateGraph(resultFileName, false);
+ public void blacklistClassPattern(final String pattern) {
+ blacklistClassPatterns.add(pattern);
}
/**
+ * @param targetDirectory
+ * target directory name
+ *
* @param resultFileName
* file name for the generated graph. File extension will be
* added automatically. Existing file with the same name will be
* overwritten.
- *
+ *
* @param keepDotFile
* if set to <code>true</code> then intermediary GraphViz DOT
* file will be kept.
*/
- public void generateGraph(final String resultFileName,
- final boolean keepDotFile) {
-
- final String desktopPath = CommonPathResolver.getDesktopDirectory()
- .getAbsolutePath() + "/";
+ public void generateGraph(final String resultFileName) {
- final String dotFilePath = desktopPath + resultFileName + ".dot";
- final String imageFilePath = desktopPath + resultFileName + ".png";
+ final String dotFilePath = targetDirectory + resultFileName + ".dot";
+ final String imageFilePath = targetDirectory + resultFileName + ".png";
System.out.println("Dot file path:" + dotFilePath);
if (!keepDotFile) {
// delete dot file
- final File dotFile = new File(dotFilePath);
- dotFile.delete();
+ new File(dotFilePath).delete();
}
} catch (final IOException e) {
System.err.println(e);
}
+
}
private String getDot() {
result.append("digraph Java {\n");
result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
- for (final Map.Entry<String, ClassDescriptor> entry : nameToClassMap
+ for (final Map.Entry<String, ClassDescriptor> entry : fullyQualifiedNameToClassMap
.entrySet())
result.append(entry.getValue().getDot());
return resultStr;
}
+ /**
+ * @param clazz
+ * class that shall be added to graph
+ */
+ protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) {
+
+ if (clazz == null)
+ return null;
+
+ final String classFullyQualifiedName = clazz.getName();
+
+ // reuse existing instance if possible
+ if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName))
+ return fullyQualifiedNameToClassMap.get(classFullyQualifiedName);
+
+ // create new class descriptor
+ final ClassDescriptor newClassDescriptor = new ClassDescriptor(this);
+ fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
+ newClassDescriptor);
+
+ newClassDescriptor.analyzeClass(clazz);
+
+ return newClassDescriptor;
+ }
+
/**
* Hide orphaned class that have no references
*/
public void hideOrphanedClasses() {
- for (final ClassDescriptor classDescriptor : nameToClassMap.values())
+ for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap
+ .values())
classDescriptor.hideClassIfNoReferences();
}
- public Filter getFilter() {
- return filter;
+ protected boolean isClassShown(final String className) {
+ for (final String pattern : blacklistClassPatterns)
+ if (WildCardMatcher.match(className, pattern))
+ return false;
+
+ if (!whitelistClassPatterns.isEmpty()) {
+ for (final String pattern : whitelistClassPatterns)
+ if (WildCardMatcher.match(className, pattern))
+ return true;
+ return false;
+ }
+
+ return true;
}
- public void setFilter(Filter filter) {
- this.filter = filter;
+ public ClassGraph setKeepDotFile(final boolean keepDotFile) {
+ this.keepDotFile = keepDotFile;
+
+ return this;
+ }
+
+ public ClassGraph setTargetDirectory(String directoryPath) {
+ if (!directoryPath.endsWith("/"))
+ directoryPath += "/";
+
+ targetDirectory = directoryPath;
+
+ return this;
+ }
+
+ public ClassGraph whitelistClassPattern(final String pattern) {
+ whitelistClassPatterns.add(pattern);
+
+ return this;
}
}