package com.vaadin.tests.util; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.List; import java.util.Set; import com.vaadin.tests.VaadinClasses; public class GraphVizClassHierarchyCreator { public static void main(String[] args) { String gv = getGraphVizHierarchy((List) VaadinClasses.getComponents(), "com.vaadin"); System.out.println(gv); } private static String getGraphVizHierarchy(List<Class> classes, String packageToInclude) { boolean includeInterfaces = false; StringBuilder header = new StringBuilder(); header.append("digraph finite_state_machine {\n" + " rankdir=BT;\n" + " dpi=\"150\";\n" + " ratio=\"0.25\";\n"); StringBuilder sb = new StringBuilder(); Set<Class> classesAndParents = new HashSet<>(); for (Class<?> cls : classes) { addClassAndParents(classesAndParents, cls, packageToInclude); } Set<Class> interfaces = new HashSet<>(); for (Object cls : classesAndParents.toArray()) { for (Class<?> c : ((Class) cls).getInterfaces()) { addClassAndParentInterfaces(classesAndParents, c, packageToInclude); } } for (Class<?> c : classesAndParents) { appendClass(sb, c, c.getSuperclass(), packageToInclude, includeInterfaces); for (Class ci : c.getInterfaces()) { appendClass(sb, c, ci, packageToInclude, includeInterfaces); } } header.append(" node [shape = ellipse, style=\"dotted\"] "); for (Class c : classesAndParents) { if (!c.isInterface() && Modifier.isAbstract(c.getModifiers())) { header.append(c.getSimpleName()).append(" "); } } if (includeInterfaces) { System.out.print(" node [shape = ellipse, style=\"solid\"] "); for (Class c : classesAndParents) { if (c.isInterface()) { header.append(c.getSimpleName()).append(" "); } } header.append(";\n"); } header.append(";\n"); header.append(" node [shape = rectangle, style=\"solid\"];\n"); return header.toString() + sb.toString() + "}"; } private static void addClassAndParents(Set<Class> classesAndParents, Class<?> cls, String packageToInclude) { if (cls == null) { return; } if (classesAndParents.contains(cls)) { return; } if (!cls.getPackage().getName().startsWith(packageToInclude)) { return; } classesAndParents.add(cls); addClassAndParents(classesAndParents, cls.getSuperclass(), packageToInclude); } private static void addClassAndParentInterfaces( Set<Class> classesAndParents, Class<?> cls, String packageToInclude) { if (cls == null) { return; } if (classesAndParents.contains(cls)) { return; } if (!cls.getPackage().getName().startsWith(packageToInclude)) { return; } classesAndParents.add(cls); for (Class iClass : cls.getInterfaces()) { addClassAndParentInterfaces(classesAndParents, iClass, packageToInclude); } } private static void appendClass(StringBuilder sb, Class<?> c, Class<?> superClass, String packageToInclude, boolean includeInterfaces) { if (superClass == null) { return; } if (!c.getPackage().getName().startsWith(packageToInclude)) { return; } if (!superClass.getPackage().getName().startsWith(packageToInclude)) { return; } if (!includeInterfaces && (c.isInterface() || superClass.isInterface())) { return; } sb.append(c.getSimpleName()).append(" -> ") .append(superClass.getSimpleName()).append("\n"); } private static void addInterfaces(Set<Class> interfaces, Class<?> cls) { if (interfaces.contains(cls)) { return; } if (cls.isInterface()) { interfaces.add(cls); } for (Class c : cls.getInterfaces()) { addInterfaces(interfaces, c); } } }