+ try {
+ // write DOT file to disk
+ final PrintWriter out = new PrintWriter(dotFile, "UTF-8");
+ out.write(getDot());
+ out.close();
+
+ // execute GraphViz to visualize graph
+ try {
+ Runtime.getRuntime()
+ .exec(new String[]{"dot",
+ "-T" + targetImageType.fileExtension,
+ dotFile.getAbsolutePath(),
+ "-o",
+ imageFile.getAbsolutePath()}).waitFor();
+ } catch (final InterruptedException ignored) {
+ }
+
+ if (!keepDotFile)
+ // delete dot file
+ if (!dotFile.delete())
+ throw new RuntimeException("Cannot delete file: " + dotFile.getAbsolutePath());
+
+ } catch (final IOException e) {
+ throw new RuntimeException("Unable to generate graph: " + e.getMessage(), e);
+ }
+
+ }
+
+ private String getDot() {
+ final StringBuilder result = new StringBuilder();
+
+ result.append("digraph Java {\n");
+ result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n");
+
+ for (final Map.Entry<String, ClassDescriptor> entry : fullyQualifiedNameToClassMap
+ .entrySet())
+ result.append(entry.getValue().getDot());
+
+ result.append("}\n");
+
+ return result.toString();
+ }
+
+ /**
+ * @param clazz class that shall be added to graph
+ * @return {@link ClassDescriptor} corresponding to given {@link Class}
+ */
+ 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
+ *
+ * @return this {@link ClassGraph}
+ */
+ public ClassGraph hideOrphanedClasses() {
+
+ for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap
+ .values())
+ classDescriptor.hideClassIfNoReferences();
+
+ return this;
+ }
+
+ protected boolean isClassShown(final String className) {
+ for (final String pattern : blacklistClassGlobs)
+ if (GlobMatcher.match(className, pattern))
+ return false;
+
+ if (!whitelistClassGlobs.isEmpty()) {
+ for (final String pattern : whitelistClassGlobs)
+ if (GlobMatcher.match(className, pattern))
+ return true;
+ return false;
+ }