+public class ClassDescriptor implements GraphElement, Comparable<ClassDescriptor> {
+
+ private static final int MAX_REFERECNES_COUNT = 10;
+ final List<ClassDescriptor> interfaces = new ArrayList<>();
+ private final Map<String, FieldDescriptor> nameToFieldMap = new TreeMap<>();
+ private final SortedSet<MethodDescriptor> methods = new TreeSet<>();
+ private final ClassGraph classGraph;
+ boolean isEnum;
+ boolean isInterface;
+ boolean isArray;
+ ClassDescriptor superClass;
+ private String fullyQualifiedName;
+ /**
+ * Incoming arrows will have this color.
+ */
+ private String distinctiveReferenceColor;
+ private String interfaceColor;
+ private String superClassColor;
+ private boolean isShown = true;
+ /**
+ * Amount of field and method references pointing to this class.
+ */
+ private int referencesCount = 0;
+
+ // for interface, counts amount of found implementations
+ private int implementationsCount = 0;
+
+ // counts amount of times this class is extended
+ private int extensionsCount = 0;
+
+ private ClassDescriptor arrayComponent;
+
+ public ClassDescriptor(final ClassGraph classGraph) {
+ this.classGraph = classGraph;
+ }
+
+ protected void analyzeClass(final Class<?> clazz) {
+
+ fullyQualifiedName = clazz.getName();
+
+ isArray = clazz.isArray();
+
+ if (isArray) {
+ final Class<?> componentType = clazz.getComponentType();
+ arrayComponent = getClassGraph().getOrCreateClassDescriptor(
+ componentType);
+ }
+
+ // System.out.println("class: " + fullyQualifiedName);
+
+ isEnum = clazz.isEnum();
+
+ isInterface = clazz.isInterface();
+
+ if (!isVisible())
+ return;
+
+ try {
+ indexFields(clazz.getDeclaredFields());
+ indexFields(clazz.getFields());
+ } catch (NoClassDefFoundError error) {
+ // TODO: better logging of this error
+ System.out.println(error.toString());
+ }
+
+ indexMethods(clazz);
+
+ for (final Class interfaceClass : clazz.getInterfaces()) {
+ final ClassDescriptor interfaceClassDescriptor = getClassGraph()
+ .getOrCreateClassDescriptor(interfaceClass);
+ interfaceClassDescriptor.registerImplementation();
+ interfaces.add(interfaceClassDescriptor);
+ }
+
+ superClass = getClassGraph().getOrCreateClassDescriptor(
+ clazz.getSuperclass());
+ if (superClass != null)
+ superClass.registerExtension();
+
+ }
+
+ protected boolean areReferencesShown() {
+ return referencesCount <= MAX_REFERECNES_COUNT;
+ }
+
+ private void enlistFieldReferences(final StringBuffer result) {
+ if (nameToFieldMap.isEmpty())
+ return;
+
+ result.append("\n");
+ result.append(" // field references to other classes\n");
+ nameToFieldMap.forEach((fieldName, field) -> result.append(field.getDot()));
+ }
+
+ private void enlistFields(final StringBuffer result) {
+ if (nameToFieldMap.isEmpty())
+ return;
+
+ result.append("\n");
+ result.append(" // fields:\n");
+
+ // enlist fields
+ for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
+ .entrySet())
+ result.append(entry.getValue().getEmbeddedDot());
+ }
+
+ private void enlistImplementedInterfaces(final StringBuffer result) {
+ if (interfaces.isEmpty())
+ return;