reduced fields and methods visibility
[javainspect.git] / src / main / java / eu / svjatoslav / inspector / java / structure / ClassDescriptor.java
index 2247a77..e43fe8d 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * JavaInspect - Utility to visualize java software
- * Copyright (C) 2013-2014, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- * 
+ * 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.
@@ -25,11 +25,11 @@ public class ClassDescriptor implements GraphElement {
 
        private static final int MAX_REFERECNES_COUNT = 10;
 
-       public final String fullyQualifiedName;
+       private String fullyQualifiedName;
 
-       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.
@@ -65,18 +65,22 @@ public class ClassDescriptor implements GraphElement {
        // counts amount of times this class is extended
        private int extensionsCount = 0;
 
-       public ClassDescriptor(final Class<? extends Object> clazz,
-                       final ClassGraph dump) {
-               classGraph = dump;
+       private ClassDescriptor arrayComponent;
+
+       public ClassDescriptor(final ClassGraph classGraph) {
+               this.classGraph = classGraph;
+       }
+
+       protected void analyzeClass(final Class<? extends Object> clazz) {
 
                fullyQualifiedName = clazz.getName();
-               dump.nameToClassMap.put(fullyQualifiedName, this);
 
                isArray = clazz.isArray();
 
                if (isArray) {
                        final Class<?> componentType = clazz.getComponentType();
-                       dump.addClass(componentType);
+                       arrayComponent = getClassGraph().getOrCreateClassDescriptor(
+                                       componentType);
                }
 
                // System.out.println("class: " + fullyQualifiedName);
@@ -94,23 +98,24 @@ public class ClassDescriptor implements GraphElement {
                indexMethods(clazz);
 
                for (final Class interfaceClass : clazz.getInterfaces()) {
-                       final ClassDescriptor classDescriptor = dump
-                                       .addClass(interfaceClass);
-                       classDescriptor.registerImplementation();
-                       interfaces.add(classDescriptor);
+                       final ClassDescriptor interfaceClassDescriptor = getClassGraph()
+                                       .getOrCreateClassDescriptor(interfaceClass);
+                       interfaceClassDescriptor.registerImplementation();
+                       interfaces.add(interfaceClassDescriptor);
                }
 
-               superClass = dump.addClass(clazz.getSuperclass());
+               superClass = getClassGraph().getOrCreateClassDescriptor(
+                               clazz.getSuperclass());
                if (superClass != null)
                        superClass.registerExtension();
 
-       }
+       };
 
-       public boolean areReferencesShown() {
+       protected boolean areReferencesShown() {
                return referencesCount <= MAX_REFERECNES_COUNT;
        }
 
-       public void enlistFieldReferences(final StringBuffer result) {
+       private void enlistFieldReferences(final StringBuffer result) {
                if (nameToFieldMap.isEmpty())
                        return;
 
@@ -121,7 +126,7 @@ public class ClassDescriptor implements GraphElement {
                        result.append(entry.getValue().getDot());
        }
 
-       public void enlistFields(final StringBuffer result) {
+       private void enlistFields(final StringBuffer result) {
                if (nameToFieldMap.isEmpty())
                        return;
 
@@ -134,7 +139,7 @@ public class ClassDescriptor implements GraphElement {
                        result.append(entry.getValue().getEmbeddedDot());
        }
 
-       public void enlistImplementedInterfaces(final StringBuffer result) {
+       private void enlistImplementedInterfaces(final StringBuffer result) {
                if (interfaces.isEmpty())
                        return;
 
@@ -146,14 +151,17 @@ public class ClassDescriptor implements GraphElement {
                        if (!interfaceDescriptor.isVisible())
                                continue;
 
+                       if (!interfaceDescriptor.areReferencesShown())
+                               continue;
+
                        result.append("    " + interfaceDescriptor.getGraphId() + " -> "
-                                       + getGraphId() + "[style=\"dotted, tapered\", color=\""
+                                       + getGraphId() + "[style=\"dotted\", color=\""
                                        + interfaceDescriptor.getInterfaceColor()
-                                       + "\", penwidth=20, dir=\"forward\"];\n");
+                                       + "\", penwidth=10, dir=\"forward\"];\n");
                }
        }
 
-       public void enlistMethodReferences(final StringBuffer result) {
+       private void enlistMethodReferences(final StringBuffer result) {
                if (methods.isEmpty())
                        return;
 
@@ -163,7 +171,7 @@ public class ClassDescriptor implements GraphElement {
                        result.append(methodDescriptor.getDot());
        }
 
-       public void enlistMethods(final StringBuffer result) {
+       private void enlistMethods(final StringBuffer result) {
                if (methods.isEmpty())
                        return;
 
@@ -175,23 +183,25 @@ public class ClassDescriptor implements GraphElement {
                        result.append(methodDescriptor.getEmbeddedDot());
        }
 
-       public void enlistSuperClass(final StringBuffer result) {
+       private void enlistSuperClass(final StringBuffer result) {
                if (superClass == null)
                        return;
 
                if (!superClass.isVisible())
                        return;
 
+               if (!superClass.areReferencesShown())
+                       return;
+
                result.append("\n");
                result.append("    // super class for: " + fullyQualifiedName + "\n");
 
                result.append("    " + superClass.getGraphId() + " -> " + getGraphId()
-                               + "[style=\"tapered\", color=\""
-                               + superClass.getSuperClassColor()
+                               + "[ color=\"" + superClass.getSuperClassColor()
                                + "\", penwidth=10, dir=\"forward\"];\n");
        }
 
-       public void generateDotHeader(final StringBuffer result) {
+       private void generateDotHeader(final StringBuffer result) {
                result.append("\n");
                result.append("// Class: " + fullyQualifiedName + "\n");
 
@@ -214,17 +224,7 @@ public class ClassDescriptor implements GraphElement {
                                + "</B></FONT>" + "</TD></TR>\n");
        }
 
-       public List<FieldDescriptor> getAllFields() {
-               final List<FieldDescriptor> result = new ArrayList<FieldDescriptor>();
-
-               for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
-                               .entrySet())
-                       result.add(entry.getValue());
-
-               return result;
-       }
-
-       public String getBackgroundColor() {
+       private String getBackgroundColor() {
                String bgColor = "";
 
                if (isEnum)
@@ -236,23 +236,33 @@ public class ClassDescriptor implements GraphElement {
                return bgColor;
        }
 
-       public String getBorderWidth() {
+       private String getBorderWidth() {
 
                if (!areReferencesShown())
                        return "4";
                return "1";
        }
 
-       public String getClassName(final boolean differentiateArray) {
+       protected ClassGraph getClassGraph() {
+               return classGraph;
+       }
+
+       protected String getClassName(final boolean differentiateArray) {
                // this is needed for nested classes
                final String actualClassName = fullyQualifiedName.replace('$', '.');
 
-               final int i = actualClassName.lastIndexOf('.');
-
-               String result = actualClassName.substring(i + 1);
-
-               if (isArray)
-                       result = result.substring(0, result.length() - 1);
+               String result;
+               if (isArray) {
+                       // for arrays use array component instead of array class name
+                       result = arrayComponent.fullyQualifiedName;
+                       if (result.contains(".")) {
+                               final int i = result.lastIndexOf('.');
+                               result = result.substring(i + 1);
+                       }
+               } else {
+                       final int i = actualClassName.lastIndexOf('.');
+                       result = actualClassName.substring(i + 1);
+               }
 
                if (differentiateArray)
                        if (isArray)
@@ -263,14 +273,10 @@ public class ClassDescriptor implements GraphElement {
                return result;
        }
 
-       public String getColor() {
-               if (getDistinctiveColor() == null)
-                       setDistinctiveColor(Utils.getNextDarkColor());
+       protected String getColor() {
+               if (distinctiveReferenceColor == null)
+                       distinctiveReferenceColor = Utils.getNextDarkColor();
 
-               return getDistinctiveColor();
-       }
-
-       public String getDistinctiveColor() {
                return distinctiveReferenceColor;
        }
 
@@ -312,7 +318,7 @@ public class ClassDescriptor implements GraphElement {
         * Returns field with given name (case is ignored). Or <code>null</code> if
         * field is not found.
         */
-       public FieldDescriptor getFieldIgnoreCase(final String fieldToSearch) {
+       protected FieldDescriptor getFieldIgnoreCase(final String fieldToSearch) {
 
                for (final String fieldName : nameToFieldMap.keySet())
                        if (fieldToSearch.equalsIgnoreCase(fieldName))
@@ -321,21 +327,40 @@ public class ClassDescriptor implements GraphElement {
                return null;
        }
 
+       protected String getFullyQualifiedName() {
+               return fullyQualifiedName;
+       }
+
        @Override
        public String getGraphId() {
                final String result = "class_"
                                + fullyQualifiedName.replace('.', '_').replace(";", "")
-                                               .replace("[L", "").replace('$', '_');
+                               .replace("[L", "").replace('$', '_');
                return result;
        }
 
-       public String getInterfaceColor() {
+       private String getInterfaceColor() {
                if (interfaceColor == null)
-                       interfaceColor = Utils.getNextLightColor();
+                       interfaceColor = Utils.getNextDarkColor();
 
                return interfaceColor;
        }
 
+       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;
 
@@ -360,21 +385,7 @@ public class ClassDescriptor implements GraphElement {
                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() {
+       private String getPackageName() {
 
                final int i = fullyQualifiedName.lastIndexOf('.');
 
@@ -384,7 +395,7 @@ public class ClassDescriptor implements GraphElement {
                return fullyQualifiedName.substring(0, i).replace("[L", "");
        }
 
-       public String getParentClassesName() {
+       private String getParentClassesName() {
                int i = fullyQualifiedName.lastIndexOf('.');
                final String fullClassName = fullyQualifiedName.substring(i + 1);
 
@@ -395,7 +406,7 @@ public class ClassDescriptor implements GraphElement {
                return parentClassesName.replace('$', '.');
        }
 
-       public String getSuperClassColor() {
+       private String getSuperClassColor() {
                if (superClassColor == null)
                        superClassColor = Utils.getNextLightColor();
 
@@ -406,7 +417,7 @@ public class ClassDescriptor implements GraphElement {
         * Checks if class has field with given name (case is ignored). Returns
         * <code>true</code> if such field is found.
         */
-       public boolean hasFieldIgnoreCase(final String fieldToSearch) {
+       protected boolean hasFieldIgnoreCase(final String fieldToSearch) {
 
                for (final String fieldName : nameToFieldMap.keySet())
                        if (fieldToSearch.equalsIgnoreCase(fieldName))
@@ -415,11 +426,11 @@ public class ClassDescriptor implements GraphElement {
                return false;
        }
 
-       public void hide() {
+       private void hide() {
                isShown = false;
        }
 
-       public void hideClassIfNoReferences() {
+       protected void hideClassIfNoReferences() {
                if (!isVisible())
                        return;
 
@@ -434,22 +445,20 @@ public class ClassDescriptor implements GraphElement {
                return;
        }
 
-       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);
-
-               }
+       private void indexFields(final Field[] fields) {
+               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);
+               }
 
        }
 
@@ -462,28 +471,33 @@ public class ClassDescriptor implements GraphElement {
                if (Utils.isSystemPackage(fullyQualifiedName))
                        return false;
 
-               if (!classGraph.getFilter().isClassShown(fullyQualifiedName))
+               if (!getClassGraph().getFilter().isClassShown(fullyQualifiedName))
                        return false;
 
+               if (isArray)
+                       if (arrayComponent != null)
+                               if (Utils.isSystemDataType(arrayComponent.fullyQualifiedName))
+                                       // Do not show references to primitive data types in arrays.
+                                       // That is: there is no point to show reference to byte when
+                                       // we have class with byte array field.
+                                       return false;
+
                return isShown;
        }
 
        /**
         * Register event when another class is extending this one.
         */
-       public void registerExtension() {
+       protected void registerExtension() {
                extensionsCount++;
        }
 
-       public void registerImplementation() {
+       protected void registerImplementation() {
                implementationsCount++;
        }
 
-       public void registerReference() {
+       protected void registerReference() {
                referencesCount++;
        }
 
-       public void setDistinctiveColor(final String distinctiveColor) {
-               distinctiveReferenceColor = distinctiveColor;
-       }
 }