2 * JavaInspect - Utility to visualize java software
3 * Copyright (C) 2013, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public License
7 * as published by the Free Software Foundation.
10 package eu.svjatoslav.javainspect.structure;
12 import java.lang.reflect.Field;
13 import java.lang.reflect.Method;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
20 * Describes single class instance
22 public class ClassDescriptor implements GraphElement {
24 private static final int MAX_REFERECNES_COUNT = 10;
26 public final String fullyQualifiedName;
28 Map<String, FieldDescriptor> nameToFieldMap = new HashMap<String, FieldDescriptor>();
30 public List<MethodDescriptor> methods = new ArrayList<MethodDescriptor>();
33 * Incoming arrows will have this color.
35 private String distinctiveReferenceColor;
37 private String interfaceColor;
39 private String superClassColor;
47 private final ClassGraph dump;
49 List<ClassDescriptor> interfaces = new ArrayList<ClassDescriptor>();
51 ClassDescriptor superClass;
54 * Amount of field and method references pointing to this class.
56 private int referenceCount = 0;
58 public ClassDescriptor(final Class<? extends Object> clazz, final ClassGraph dump) {
61 fullyQualifiedName = clazz.getName();
62 dump.nameToClassMap.put(fullyQualifiedName, this);
64 isArray = clazz.isArray();
67 final Class<?> componentType = clazz.getComponentType();
68 dump.addClass(componentType);
71 // System.out.println("class: " + fullyQualifiedName);
73 isEnum = clazz.isEnum();
75 isInterface = clazz.isInterface();
80 indexFields(clazz.getDeclaredFields());
81 indexFields(clazz.getFields());
85 for (final Class interfaceClass : clazz.getInterfaces())
86 interfaces.add(dump.addClass(interfaceClass));
88 superClass = dump.addClass(clazz.getSuperclass());
91 public boolean areReferencesShown() {
92 return referenceCount <= MAX_REFERECNES_COUNT;
95 public void enlistFieldReferences(final StringBuffer result) {
96 if (nameToFieldMap.isEmpty())
100 result.append(" // field references to other classes\n");
101 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
103 result.append(entry.getValue().getDot());
106 public void enlistFields(final StringBuffer result) {
107 if (nameToFieldMap.isEmpty())
111 result.append(" // fields:\n");
114 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
116 result.append(entry.getValue().getEmbeddedDot());
119 public void enlistImplementedInterfaces(final StringBuffer result) {
120 if (interfaces.isEmpty())
124 result.append(" // interfaces implemented by class: "
125 + fullyQualifiedName + "\n");
127 for (final ClassDescriptor interfaceDescriptor : interfaces) {
128 if (!interfaceDescriptor.isVisible())
131 result.append(" " + interfaceDescriptor.getGraphId() + " -> "
132 + getGraphId() + "[style=\"dotted, tapered\", color=\""
133 + interfaceDescriptor.getInterfaceColor()
134 + "\", penwidth=20, dir=\"forward\"];\n");
138 public void enlistMethodReferences(final StringBuffer result) {
139 if (methods.isEmpty())
143 result.append(" // method references to other classes\n");
144 for (final MethodDescriptor methodDescriptor : methods)
145 result.append(methodDescriptor.getDot());
148 public void enlistMethods(final StringBuffer result) {
149 if (methods.isEmpty())
153 result.append(" // methods:\n");
156 for (final MethodDescriptor methodDescriptor : methods)
157 result.append(methodDescriptor.getEmbeddedDot());
160 public void enlistSuperClass(final StringBuffer result) {
161 if (superClass == null)
164 if (!superClass.isVisible())
168 result.append(" // super class for: " + fullyQualifiedName + "\n");
170 result.append(" " + superClass.getGraphId() + " -> " + getGraphId()
171 + "[style=\"tapered\", color=\""
172 + superClass.getSuperClassColor()
173 + "\", penwidth=10, dir=\"forward\"];\n");
176 public void generateDotHeader(final StringBuffer result) {
178 result.append("// Class: " + fullyQualifiedName + "\n");
180 result.append(" " + getGraphId() + "[label=<<TABLE "
181 + getBackgroundColor() + " BORDER=\"" + getBorderWidth()
182 + "\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n");
185 result.append(" // class descriptor header\n");
186 result.append(" <TR><TD colspan=\"2\" PORT=\"f0\">"
187 + "<FONT POINT-SIZE=\"8.0\" >" + getPackageName()
188 + "</FONT><br/>" + "<FONT POINT-SIZE=\"25.0\"><B>"
189 + getClassName(false) + "</B></FONT>" + "</TD></TR>\n");
192 public List<FieldDescriptor> getAllFields() {
193 final List<FieldDescriptor> result = new ArrayList<FieldDescriptor>();
195 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
197 result.add(entry.getValue());
202 public String getBackgroundColor() {
206 bgColor = "bgcolor=\"navajowhite2\"";
209 bgColor = "bgcolor=\"darkslategray1\"";
214 public String getBorderWidth() {
216 if (!areReferencesShown())
221 public String getClassName(final boolean differentiateArray) {
223 final int i = fullyQualifiedName.lastIndexOf('.');
225 String result = fullyQualifiedName.substring(i + 1);
228 result = result.substring(0, result.length() - 1);
230 if (differentiateArray)
237 public String getColor() {
238 if (getDistinctiveColor() == null)
239 setDistinctiveColor(Utils.getNextDarkColor());
241 return getDistinctiveColor();
244 public String getDistinctiveColor() {
245 return distinctiveReferenceColor;
249 public String getDot() {
256 final StringBuffer result = new StringBuffer();
258 generateDotHeader(result);
260 enlistFields(result);
262 enlistMethods(result);
264 result.append(" </TABLE>>, shape=\"none\"];\n");
266 enlistFieldReferences(result);
268 enlistMethodReferences(result);
270 enlistImplementedInterfaces(result);
272 enlistSuperClass(result);
274 return result.toString();
278 public String getEmbeddedDot() {
283 public String getGraphId() {
284 final String result = "class_"
285 + fullyQualifiedName.replace('.', '_').replace(";", "")
290 public String getInterfaceColor() {
291 if (interfaceColor == null)
292 interfaceColor = Utils.getNextLightColor();
294 return interfaceColor;
297 public String getPackageName() {
299 final int i = fullyQualifiedName.lastIndexOf('.');
304 return fullyQualifiedName.substring(0, i).replace("[L", "");
307 // public String getReadableName() {
309 // // do not print full class name for well known system classes
310 // final String packageName = getPackageName();
312 // if (packageName.equals("java.util"))
313 // return getClassName();
315 // if (packageName.equals("java.lang"))
316 // return getClassName();
318 // return fullyQualifiedName;
321 public String getSuperClassColor() {
322 if (superClassColor == null)
323 superClassColor = Utils.getNextLightColor();
325 return superClassColor;
328 public void indexFields(final Field[] fields) {
329 for (final Field field : fields) {
330 if (nameToFieldMap.containsKey(field.getName()))
333 final FieldDescriptor fieldDescriptor = new FieldDescriptor(field,
339 private void indexMethods(final Class<? extends Object> clazz) {
340 final Method[] methods = clazz.getMethods();
342 for (final Method method : methods)
343 new MethodDescriptor(method, this, dump);
348 public boolean isVisible() {
350 if (Utils.isSystemDataType(fullyQualifiedName))
353 if (Utils.isSystemPackage(fullyQualifiedName))
359 public void registerReference() {
363 public void setDistinctiveColor(final String distinctiveColor) {
364 distinctiveReferenceColor = distinctiveColor;