private static final int MAX_REFERECNES_COUNT = 10;
- public final String classFullyQualifiedName;
+ public String classFullyQualifiedName;
- Map<String, FieldDescriptor> nameToFieldMap = new TreeMap<String, FieldDescriptor>();
+ private final Map<String, FieldDescriptor> nameToFieldMap = new TreeMap<String, FieldDescriptor>();
- public SortedSet<MethodDescriptor> methods = new TreeSet<MethodDescriptor>();
+ private final SortedSet<MethodDescriptor> methods = new TreeSet<MethodDescriptor>();
/**
* Incoming arrows will have this color.
private ClassDescriptor arrayComponent;
- public ClassDescriptor(final Class<? extends Object> clazz,
- final ClassGraph classGraph) {
+ public ClassDescriptor(final ClassGraph classGraph) {
this.classGraph = classGraph;
+ }
- classFullyQualifiedName = clazz.getName();
+ public void analyzeClass(final Class<? extends Object> clazz) {
- classGraph.registerClass(classFullyQualifiedName, this);
+ classFullyQualifiedName = clazz.getName();
isArray = clazz.isArray();
if (isArray) {
final Class<?> componentType = clazz.getComponentType();
- arrayComponent = classGraph.addClass(componentType);
+ arrayComponent = getClassGraph().getOrCreateClassDescriptor(
+ componentType);
}
// System.out.println("class: " + fullyQualifiedName);
indexMethods(clazz);
for (final Class interfaceClass : clazz.getInterfaces()) {
- final ClassDescriptor classDescriptor = classGraph
- .addClass(interfaceClass);
- classDescriptor.registerImplementation();
- interfaces.add(classDescriptor);
+ final ClassDescriptor interfaceClassDescriptor = getClassGraph()
+ .getOrCreateClassDescriptor(interfaceClass);
+ interfaceClassDescriptor.registerImplementation();
+ interfaces.add(interfaceClassDescriptor);
}
- superClass = classGraph.addClass(clazz.getSuperclass());
+ superClass = getClassGraph().getOrCreateClassDescriptor(
+ clazz.getSuperclass());
if (superClass != null)
superClass.registerExtension();
- }
+ };
public boolean areReferencesShown() {
return referencesCount <= MAX_REFERECNES_COUNT;
return "1";
}
+ public ClassGraph getClassGraph() {
+ return classGraph;
+ }
+
public String getClassName(final boolean differentiateArray) {
// this is needed for nested classes
final String actualClassName = classFullyQualifiedName
public String getGraphId() {
final String result = "class_"
+ classFullyQualifiedName.replace('.', '_').replace(";", "")
- .replace("[L", "").replace('$', '_');
+ .replace("[L", "").replace('$', '_');
return result;
}
return interfaceColor;
}
+ // public String getReadableName() {
+ //
+ // // do not print full class name for well known system classes
+ // final String packageName = getPackageName();
+ //
+ // if (packageName.equals("java.util"))
+ // return getClassName();
+ //
+ // if (packageName.equals("java.lang"))
+ // return getClassName();
+ //
+ // return fullyQualifiedName;
+ // }
+
+ private FieldDescriptor getOrCreateFieldDescriptor(final Field field) {
+
+ final String fieldName = field.getName();
+
+ if (nameToFieldMap.containsKey(fieldName))
+ return nameToFieldMap.get(fieldName);
+
+ final FieldDescriptor newFieldDescriptor = new FieldDescriptor(this);
+ nameToFieldMap.put(fieldName, newFieldDescriptor);
+
+ newFieldDescriptor.analyzeField(field);
+
+ return newFieldDescriptor;
+ }
+
private int getOutgoingReferencesCount() {
int result = 0;
return result;
}
- // public String getReadableName() {
- //
- // // do not print full class name for well known system classes
- // final String packageName = getPackageName();
- //
- // if (packageName.equals("java.util"))
- // return getClassName();
- //
- // if (packageName.equals("java.lang"))
- // return getClassName();
- //
- // return fullyQualifiedName;
- // }
-
public String getPackageName() {
final int i = classFullyQualifiedName.lastIndexOf('.');
}
public void indexFields(final Field[] fields) {
- for (final Field field : fields) {
- if (nameToFieldMap.containsKey(field.getName()))
- continue;
-
- final FieldDescriptor fieldDescriptor = new FieldDescriptor(field,
- this, classGraph);
-
- }
+ for (final Field field : fields)
+ getOrCreateFieldDescriptor(field);
}
private void indexMethods(final Class<? extends Object> clazz) {
- final Method[] methods = clazz.getMethods();
+ for (final Method method : clazz.getMethods()) {
+ final MethodDescriptor methodDescriptor = new MethodDescriptor(
+ this, method.getName());
- for (final Method method : methods)
- new MethodDescriptor(method, this, classGraph);
+ methods.add(methodDescriptor);
+
+ methodDescriptor.analyze(method);
+ }
}
if (Utils.isSystemPackage(classFullyQualifiedName))
return false;
- if (!classGraph.getFilter().isClassShown(classFullyQualifiedName))
+ if (!getClassGraph().getFilter().isClassShown(classFullyQualifiedName))
return false;
if (isArray)
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.
*/
private final Map<String, ClassDescriptor> fullyQualifiedNameToClassMap = new HashMap<String, ClassDescriptor>();
- private Filter filter = new Filter();
+ private final Filter filter = new Filter();
public ClassGraph() {
}
- /**
- * @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);
- }
-
/**
* @param objects
* objects that shall be added to graph
*/
- public ClassGraph(final Object... objects) {
- for (final Object object : objects)
- addClass(object.getClass());
- }
-
- /**
- * @param clazz
- * class that shall be added to graph
- */
- public ClassDescriptor addClass(final Class<? extends Object> clazz) {
-
- if (clazz == null)
- return null;
-
- final String className = clazz.getName();
+ public ClassGraph add(final Object... objects) {
- if (fullyQualifiedNameToClassMap.containsKey(className))
- return fullyQualifiedNameToClassMap.get(className);
+ if (objects != null)
+ for (final Object object : objects)
+ addObject(object);
- 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());
return filter;
}
+ /**
+ * @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 registerClass(final String classFullyQualifiedName,
- final ClassDescriptor classDescriptor) {
- fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
- classDescriptor);
- }
-
- public void setFilter(final Filter filter) {
- this.filter = filter;
- }
-
}
/*
* JavaInspect - Utility to visualize java software
* 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 3 of the GNU Lesser General Public License
* or later as published by the Free Software Foundation.
public String name;
private ClassDescriptor type;
- private ClassDescriptor parentClass;
+ private final ClassDescriptor parentClass;
List<ClassDescriptor> typeArguments = new ArrayList<ClassDescriptor>();
- public FieldDescriptor(final Field field, final ClassDescriptor parent,
- final ClassGraph classGraph) {
+ public boolean isInherited;
+ public FieldDescriptor(final ClassDescriptor parent) {
parentClass = parent;
+ }
+
+ public void analyzeField(final Field field) {
if (!field.getDeclaringClass().getName()
- .equals(parent.classFullyQualifiedName))
- // if field is inherited, do not index it
- return;
+ .equals(parentClass.classFullyQualifiedName))
+ isInherited = true;
// if (field.getType().isArray())
// System.out.println("field name: " + field.getName());
- parent.nameToFieldMap.put(field.getName(), this);
-
name = field.getName();
- type = classGraph.addClass(field.getType());
+ type = parentClass.getClassGraph().getOrCreateClassDescriptor(
+ field.getType());
type.registerReference();
final Type genericType = field.getGenericType();
for (final Type t : pt.getActualTypeArguments())
if (t instanceof Class) {
final Class cl = (Class) t;
- final ClassDescriptor genericTypeDescriptor = classGraph
- .addClass(cl);
+ final ClassDescriptor genericTypeDescriptor = parentClass
+ .getClassGraph().getOrCreateClassDescriptor(cl);
genericTypeDescriptor.registerReference();
typeArguments.add(genericTypeDescriptor);
}
@Override
public boolean isVisible() {
+ if (isInherited)
+ return false;
+
if (name.contains("$"))
return false;
/*
* JavaInspect - Utility to visualize java software
* 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 3 of the GNU Lesser General Public License
* or later as published by the Free Software Foundation.
List<ClassDescriptor> argumentTypes = new ArrayList<ClassDescriptor>();
- public MethodDescriptor(final Method method, final ClassDescriptor parent,
- final ClassGraph dump) {
+ boolean isInherited;
+ public MethodDescriptor(final ClassDescriptor parent,
+ final String methodName) {
parentClass = parent;
+ this.methodName = methodName;
+ }
- methodName = method.getName();
+ public void analyze(final Method method) {
if (!method.getDeclaringClass().getName()
- .equals(parent.classFullyQualifiedName))
- // do not index inherited methods
- return;
-
- parent.methods.add(this);
+ .equals(parentClass.classFullyQualifiedName))
+ isInherited = true;
- returnType = dump.addClass(method.getReturnType());
+ returnType = parentClass.getClassGraph().getOrCreateClassDescriptor(
+ method.getReturnType());
returnType.registerReference();
final Type genericType = method.getGenericReturnType();
for (final Type t : pt.getActualTypeArguments())
if (t instanceof Class) {
final Class cl = (Class) t;
- final ClassDescriptor classDescriptor = dump.addClass(cl);
+ final ClassDescriptor classDescriptor = parentClass
+ .getClassGraph().getOrCreateClassDescriptor(cl);
classDescriptor.registerReference();
argumentTypes.add(classDescriptor);
}
if (classDescriptor.isVisible())
if (classDescriptor.areReferencesShown())
result.append(" " + getGraphId() + " -> "
- + classDescriptor.getGraphId() + "[label=\"" + methodName
- + "\", color=\"" + classDescriptor.getColor()
+ + classDescriptor.getGraphId() + "[label=\""
+ + methodName + "\", color=\""
+ + classDescriptor.getColor()
+ "\", style=\"dotted, bold\"];\n");
if (!returnType.isVisible())
// main type
if (returnType.areReferencesShown())
result.append(" " + getGraphId() + " -> "
- + returnType.getGraphId() + "[label=\"" + methodName + "\","
- + " color=\"" + returnType.getColor()
+ + returnType.getGraphId() + "[label=\"" + methodName
+ + "\"," + " color=\"" + returnType.getColor()
+ "\", style=\"dotted, bold\"];\n");
return result.toString();
@Override
public boolean isVisible() {
+ // hide inherited methods
+ if (isInherited)
+ return false;
+
// hide common object methods
if (Utils.isCommonObjectMethod(methodName))
return false;
// hide is methods for the boolean field of the same name
if (methodName.startsWith("is")) {
- final FieldDescriptor field = parentClass.getFieldIgnoreCase(methodName
- .substring(2));
+ final FieldDescriptor field = parentClass
+ .getFieldIgnoreCase(methodName.substring(2));
if (field != null)
if ("boolean".equals(field.getType().classFullyQualifiedName))
return false;
public class RenderDemoClasses {
public static void main(final String[] args) {
- final ClassGraph graph = new ClassGraph();
- graph.addClass(SampleClass.class);
- graph.addClass(SampleClass2.class);
-
- graph.generateGraph("example", false);
+ new ClassGraph().add(SampleClass.class, SampleClass2.class)
+ .generateGraph("example", false);
}
}
/*
* JavaInspect - Utility to visualize java software
* 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 3 of the GNU Lesser General Public License
* or later as published by the Free Software Foundation.
// as in the following example.
// Add some object to the graph.
- graph.addObject(graph);
+ graph.add(graph);
// Add some class to the graph.
- graph.addClass(Utils.class);
+ graph.add(Utils.class);
// Produce bitmap image titled "JavaInspect.png" to the user Desktop
// directory and keep intermediary GraphViz DOT file for reference.