Code refactoring. Simplified API.
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 3 Mar 2015 16:11:40 +0000 (18:11 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 3 Mar 2015 16:11:40 +0000 (18:11 +0200)
src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java
src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java
src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java
src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java
src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderDemoClasses.java
src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderJavaInspect.java

index 5283007..2b775cb 100755 (executable)
@@ -25,11 +25,11 @@ public class ClassDescriptor implements GraphElement {
 
        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.
@@ -67,19 +67,20 @@ public class ClassDescriptor implements GraphElement {
 
        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);
@@ -97,17 +98,18 @@ public class ClassDescriptor implements GraphElement {
                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;
@@ -252,6 +254,10 @@ public class ClassDescriptor implements GraphElement {
                return "1";
        }
 
+       public ClassGraph getClassGraph() {
+               return classGraph;
+       }
+
        public String getClassName(final boolean differentiateArray) {
                // this is needed for nested classes
                final String actualClassName = classFullyQualifiedName
@@ -341,7 +347,7 @@ public class ClassDescriptor implements GraphElement {
        public String getGraphId() {
                final String result = "class_"
                                + classFullyQualifiedName.replace('.', '_').replace(";", "")
-                               .replace("[L", "").replace('$', '_');
+                                               .replace("[L", "").replace('$', '_');
                return result;
        }
 
@@ -352,6 +358,35 @@ public class ClassDescriptor implements GraphElement {
                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;
 
@@ -376,20 +411,6 @@ 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() {
 
                final int i = classFullyQualifiedName.lastIndexOf('.');
@@ -451,21 +472,19 @@ public class ClassDescriptor implements GraphElement {
        }
 
        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);
+               }
 
        }
 
@@ -478,7 +497,7 @@ public class ClassDescriptor implements GraphElement {
                if (Utils.isSystemPackage(classFullyQualifiedName))
                        return false;
 
-               if (!classGraph.getFilter().isClassShown(classFullyQualifiedName))
+               if (!getClassGraph().getFilter().isClassShown(classFullyQualifiedName))
                        return false;
 
                if (isArray)
index a2ce8a2..27eff03 100755 (executable)
@@ -21,63 +21,34 @@ import eu.svjatoslav.inspector.java.methods.ProjectScanner;
 
 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());
        }
 
        /**
@@ -91,7 +62,7 @@ public class ClassGraph {
                        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());
@@ -198,6 +169,31 @@ public class ClassGraph {
                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
         */
@@ -209,14 +205,4 @@ public class ClassGraph {
 
        }
 
-       public void registerClass(final String classFullyQualifiedName,
-                       final ClassDescriptor classDescriptor) {
-               fullyQualifiedNameToClassMap.put(classFullyQualifiedName,
-                               classDescriptor);
-       }
-
-       public void setFilter(final Filter filter) {
-               this.filter = filter;
-       }
-
 }
index 902d415..d0a607b 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -23,26 +23,27 @@ public class FieldDescriptor implements GraphElement {
 
        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();
@@ -51,8 +52,8 @@ public class FieldDescriptor implements GraphElement {
                        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);
                                }
@@ -144,6 +145,9 @@ public class FieldDescriptor implements GraphElement {
 
        @Override
        public boolean isVisible() {
+               if (isInherited)
+                       return false;
+
                if (name.contains("$"))
                        return false;
 
index 2e5d61f..8eca361 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -28,21 +28,22 @@ public class MethodDescriptor implements GraphElement,
 
        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();
@@ -51,7 +52,8 @@ public class MethodDescriptor implements GraphElement,
                        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);
                                }
@@ -82,8 +84,9 @@ public class MethodDescriptor implements GraphElement,
                        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())
@@ -92,8 +95,8 @@ public class MethodDescriptor implements GraphElement,
                // 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();
@@ -142,6 +145,10 @@ public class MethodDescriptor implements GraphElement,
        @Override
        public boolean isVisible() {
 
+               // hide inherited methods
+               if (isInherited)
+                       return false;
+
                // hide common object methods
                if (Utils.isCommonObjectMethod(methodName))
                        return false;
@@ -157,8 +164,8 @@ public class MethodDescriptor implements GraphElement,
 
                // 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;
index b5a24a8..50f9c7e 100755 (executable)
@@ -16,12 +16,9 @@ import eu.svjatoslav.inspector.java.structure.example.structure.SampleClass2;
 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);
        }
 
 }
index 93dead5..7d9eb80 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -49,10 +49,10 @@ public class RenderJavaInspect {
                // 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.