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.inspector.java.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 boolean isShown = true;
49 private final ClassGraph dump;
51 List<ClassDescriptor> interfaces = new ArrayList<ClassDescriptor>();
53 ClassDescriptor superClass;
56 * Amount of field and method references pointing to this class.
58 private int referenceCount = 0;
60 public ClassDescriptor(final Class<? extends Object> clazz,
61 final ClassGraph dump) {
64 fullyQualifiedName = clazz.getName();
65 dump.nameToClassMap.put(fullyQualifiedName, this);
67 isArray = clazz.isArray();
70 final Class<?> componentType = clazz.getComponentType();
71 dump.addClass(componentType);
74 // System.out.println("class: " + fullyQualifiedName);
76 isEnum = clazz.isEnum();
78 isInterface = clazz.isInterface();
83 indexFields(clazz.getDeclaredFields());
84 indexFields(clazz.getFields());
88 for (final Class interfaceClass : clazz.getInterfaces())
89 interfaces.add(dump.addClass(interfaceClass));
91 superClass = dump.addClass(clazz.getSuperclass());
94 public boolean areReferencesShown() {
95 return referenceCount <= MAX_REFERECNES_COUNT;
98 public void enlistFieldReferences(final StringBuffer result) {
99 if (nameToFieldMap.isEmpty())
103 result.append(" // field references to other classes\n");
104 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
106 result.append(entry.getValue().getDot());
109 public void enlistFields(final StringBuffer result) {
110 if (nameToFieldMap.isEmpty())
114 result.append(" // fields:\n");
117 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
119 result.append(entry.getValue().getEmbeddedDot());
122 public void enlistImplementedInterfaces(final StringBuffer result) {
123 if (interfaces.isEmpty())
127 result.append(" // interfaces implemented by class: "
128 + fullyQualifiedName + "\n");
130 for (final ClassDescriptor interfaceDescriptor : interfaces) {
131 if (!interfaceDescriptor.isVisible())
134 result.append(" " + interfaceDescriptor.getGraphId() + " -> "
135 + getGraphId() + "[style=\"dotted, tapered\", color=\""
136 + interfaceDescriptor.getInterfaceColor()
137 + "\", penwidth=20, dir=\"forward\"];\n");
141 public void enlistMethodReferences(final StringBuffer result) {
142 if (methods.isEmpty())
146 result.append(" // method references to other classes\n");
147 for (final MethodDescriptor methodDescriptor : methods)
148 result.append(methodDescriptor.getDot());
151 public void enlistMethods(final StringBuffer result) {
152 if (methods.isEmpty())
156 result.append(" // methods:\n");
159 for (final MethodDescriptor methodDescriptor : methods)
160 result.append(methodDescriptor.getEmbeddedDot());
163 public void enlistSuperClass(final StringBuffer result) {
164 if (superClass == null)
167 if (!superClass.isVisible())
171 result.append(" // super class for: " + fullyQualifiedName + "\n");
173 result.append(" " + superClass.getGraphId() + " -> " + getGraphId()
174 + "[style=\"tapered\", color=\""
175 + superClass.getSuperClassColor()
176 + "\", penwidth=10, dir=\"forward\"];\n");
179 public void generateDotHeader(final StringBuffer result) {
181 result.append("// Class: " + fullyQualifiedName + "\n");
183 result.append(" " + getGraphId() + "[label=<<TABLE "
184 + getBackgroundColor() + " BORDER=\"" + getBorderWidth()
185 + "\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n");
188 result.append(" // class descriptor header\n");
189 result.append(" <TR><TD colspan=\"2\" PORT=\"f0\">"
190 + "<FONT POINT-SIZE=\"8.0\" >" + getPackageName()
193 final String parentClassesName = getParentClassesName();
194 if (parentClassesName.length() > 0)
195 result.append("<FONT POINT-SIZE=\"12.0\"><B>" + parentClassesName
196 + "</B></FONT><br/>\n");
198 result.append("<FONT POINT-SIZE=\"25.0\"><B>" + getClassName(false)
199 + "</B></FONT>" + "</TD></TR>\n");
202 public List<FieldDescriptor> getAllFields() {
203 final List<FieldDescriptor> result = new ArrayList<FieldDescriptor>();
205 for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
207 result.add(entry.getValue());
212 public String getBackgroundColor() {
216 bgColor = "bgcolor=\"navajowhite2\"";
219 bgColor = "bgcolor=\"darkslategray1\"";
224 public String getBorderWidth() {
226 if (!areReferencesShown())
231 public String getClassName(final boolean differentiateArray) {
232 // this is needed for nested classes
233 final String actualClassName = fullyQualifiedName.replace('$', '.');
235 final int i = actualClassName.lastIndexOf('.');
237 String result = actualClassName.substring(i + 1);
240 result = result.substring(0, result.length() - 1);
242 if (differentiateArray)
246 // this is needed for nested classes
247 // result = result.replace('$', '.');
251 public String getColor() {
252 if (getDistinctiveColor() == null)
253 setDistinctiveColor(Utils.getNextDarkColor());
255 return getDistinctiveColor();
258 public String getDistinctiveColor() {
259 return distinctiveReferenceColor;
263 public String getDot() {
270 final StringBuffer result = new StringBuffer();
272 generateDotHeader(result);
274 enlistFields(result);
276 enlistMethods(result);
278 result.append(" </TABLE>>, shape=\"none\"];\n");
280 enlistFieldReferences(result);
282 enlistMethodReferences(result);
284 enlistImplementedInterfaces(result);
286 enlistSuperClass(result);
288 return result.toString();
292 public String getEmbeddedDot() {
297 public String getGraphId() {
298 final String result = "class_"
299 + fullyQualifiedName.replace('.', '_').replace(";", "")
300 .replace("[L", "").replace('$', '_');
304 public String getInterfaceColor() {
305 if (interfaceColor == null)
306 interfaceColor = Utils.getNextLightColor();
308 return interfaceColor;
311 public String getPackageName() {
313 final int i = fullyQualifiedName.lastIndexOf('.');
318 return fullyQualifiedName.substring(0, i).replace("[L", "");
321 public String getParentClassesName() {
322 int i = fullyQualifiedName.lastIndexOf('.');
323 final String fullClassName = fullyQualifiedName.substring(i + 1);
325 i = fullClassName.lastIndexOf('$');
328 final String parentClassesName = fullClassName.substring(0, i);
329 return parentClassesName.replace('$', '.');
332 // public String getReadableName() {
334 // // do not print full class name for well known system classes
335 // final String packageName = getPackageName();
337 // if (packageName.equals("java.util"))
338 // return getClassName();
340 // if (packageName.equals("java.lang"))
341 // return getClassName();
343 // return fullyQualifiedName;
346 public String getSuperClassColor() {
347 if (superClassColor == null)
348 superClassColor = Utils.getNextLightColor();
350 return superClassColor;
357 public void indexFields(final Field[] fields) {
358 for (final Field field : fields) {
359 if (nameToFieldMap.containsKey(field.getName()))
362 final FieldDescriptor fieldDescriptor = new FieldDescriptor(field,
368 private void indexMethods(final Class<? extends Object> clazz) {
369 final Method[] methods = clazz.getMethods();
371 for (final Method method : methods)
372 new MethodDescriptor(method, this, dump);
377 public boolean isVisible() {
379 if (Utils.isSystemDataType(fullyQualifiedName))
382 if (Utils.isSystemPackage(fullyQualifiedName))
388 public void registerReference() {
392 public void setDistinctiveColor(final String distinctiveColor) {
393 distinctiveReferenceColor = distinctiveColor;