Debugging utility that reports, in a brute force manner, any internal data of a class instance : Debug « Development Class « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Class
8. Collections Data Structure
9. Data Type
10. Database SQL JDBC
11. Design Pattern
12. Development Class
13. EJB3
14. Email
15. Event
16. File Input Output
17. Game
18. Generics
19. GWT
20. Hibernate
21. I18N
22. J2EE
23. J2ME
24. JDK 6
25. JNDI LDAP
26. JPA
27. JSP
28. JSTL
29. Language Basics
30. Network Protocol
31. PDF RTF
32. Reflection
33. Regular Expressions
34. Scripting
35. Security
36. Servlets
37. Spring
38. Swing Components
39. Swing JFC
40. SWT JFace Eclipse
41. Threads
42. Tiny Application
43. Velocity
44. Web Services SOA
45. XML
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java » Development Class » DebugScreenshots 
Debugging utility that reports, in a brute force manner, any internal data of a class instance
   
//----------------------------------------------------------------------------//
//                                                                            //
//                                D u m p e r                                 //
//                                                                            //
//  Copyright (C) Herve Bitteur 2000-2009. All rights reserved.               //
//  This software is released under the GNU General Public License.           //
//  Please contact users@audiveris.dev.java.net to report bugs & suggestions. //
//----------------------------------------------------------------------------//
//

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;

/**
 * Class <code>Dumper</code> is a debugging utility that reports, in a brute
 * force manner, any internal data of a class instance.
 *
 * <p> When used on a class instance, all class internal fields which are
 * considered as "relevant" are printed using their toString() method, then we
 * walk up the inheritance tree and repeat the same actions, until there is no
 * more superclass or until the superclass we have reached is considered as
 * non-relevant. </p>
 *
 * <p> A (super)class is considered "relevant" if the static method
 * <code>isClassRelevant(class)</code> returns true. This method can be
 * overridden in a subclass of Dumper to adapt to local needs. </p>
 *
 * <p> A field is considered "relevant" if the following condition if the method
 * <code>isFieldRelevant(field)</code> returns true. Similarly, the behavior of
 * this predicate can be customized by subclassing the Dumper class. </p>
 *
 * <p> There are several kinds of print outs available through subclassing. Each
 * of them export two public methods: <code>dump()</code> which prints the
 * result on default output stream, and <code>dumpOf()</code> which simply
 * returns the generated dump string.
 *
 * <ul> <li> <b>Column</b> a dump with one line per field </li>
 *
 * <li> <b>Row</b> a dump with all information on one row </li>
 *
 * <li> <b>Html</b> an Html stream with fields arranged in tables </li>
 *
 * </ul>
 *
 * Here are some examples of use:
 * <pre>
 * // Using the predefined static helper methods
 * Dumper.dump(myinstance);
 * Dumper.dump(myinstance, "My Title");
 * Dumper.dump(myinstance, "My Title", 2);
 * System.out.println(Dumper.dumpOf(myinstance));
 * System.out.println(Dumper.htmlDumpOf(myinstance));
 *
 *  // Using directly the Dumper subclasses
 * new Dumper.Column(myinstance).print();
 * System.out.println(new Dumper.Row(myinstance).toString());
 * display(new Dumper.Html(myinstance).toString());
 * </pre>
 *
 @author Herv&eacute; Bitteur
 @version $Id: Dumper.java,v 1.15 2009/03/03 19:45:51 hbitteur Exp $
 */
public abstract class Dumper
{
    //~ Instance fields --------------------------------------------------------

    /**
     * The object to be dumped
     */
    protected final Object obj;

    /**
     * The string buffer used as output
     */
    protected final StringBuffer sb;

    /**
     * Can we use HTML directives?
     */
    protected final boolean useHtml;

    /** Maximum number of collection items printed */
    private final int MAX_COLLECTION_INDEX = 9;

    /**
     * Class (beware, this variable is updated as we walk up the inheritance
     * tree)
     */
    protected Class cl;

    //~ Constructors -----------------------------------------------------------

    /**
     * Creates a new Dumper.
     *
     @param obj the object instance to be dumped.
     */
    private Dumper (Object  obj,
                    boolean useHtml)
    {
        // (re)Allocate the string buffer
        sb = new StringBuffer(1024);

        // Cache the object & the related class
        this.obj = obj;
        this.useHtml = useHtml;
        cl = obj.getClass();
    }

    //~ Methods ----------------------------------------------------------------

    //-----------------//
    // isClassRelevant //
    //-----------------//
    /**
     * Predicate to determine if a given class is worth being printed. This
     * method could be overridden to reflect customized policy. Note that when
     * walking up the inheritance tree, the browsing is stopped as soon as a
     * non-relevant class is encountered.
     *
     @param cl the class at stake
     *
     @return true if found relevant
     */
    public static boolean isClassRelevant (Class cl)
    {
        //        return (cl != null) && !cl.getName()
        //                                  .startsWith("java.") &&
        //               !cl.getName()
        //                  .startsWith("javax.");
        return (cl != null&& cl.getName()
                                 .startsWith("omr.");
    }

    //-----------------//
    // isFieldRelevant //
    //-----------------//
    /**
     * Predicate to determine if a given field is worth being printed. This
     * method could be overridden to reflect customized policy.
     *
     @param field the field at stake
     *
     @return true if found relevant
     */
    public static boolean isFieldRelevant (Field field)
    {
        // We don't print static field since the Dumper is meant for instances
        if (Modifier.isStatic(field.getModifiers())) {
            return false;
        }

        // We don't print non-user visible entities
        if (field.getName()
                 .indexOf('$'!= -1) {
            return false;
        }

        return true;
    }

    //------//
    // dump //
    //------//
    /**
     * Helper function that prints the internal data of an object onto the
     * standard output.
     *
     @param obj the instance to dump
     */
    public static void dump (Object obj)
    {
        dump(obj, null, 0);
    }

    //------//
    // dump //
    //------//
    /**
     * Helper function that prints the internal data of an object onto the
     * standard output, with a specified left indentation level.
     *
     @param obj   the instance to dump
     @param level the indentation level (0 means no indentation)
     */
    public static void dump (Object obj,
                             int    level)
    {
        dump(obj, null, level);
    }

    //------//
    // dump //
    //------//
    /**
     * Helper function that prints the internal data of an object onto the
     * standard output, with the ability to print a related title
     *
     @param obj   the object to dump
     @param title the title to print beforehand
     */
    public static void dump (Object obj,
                             String title)
    {
        dump(obj, title, 0);
    }

    //------//
    // dump //
    //------//
    /**
     * Helper function that prints the internal data of an object onto the
     * standard output, with room for a title and left indentation.
     *
     @param obj   the object to dump
     @param title the title to print beforehand
     @param level the indentation level (0 for no indent)
     */
    public static void dump (Object obj,
                             String title,
                             int    level)
    {
        new Column(obj, title, level).print();
    }

    //--------//
    // dumpOf //
    //--------//
    /**
     * Helper function that returns a line which contains the whole set of
     * internal data
     *
     @param obj the object whose data is to be printed
     *
     @return the string of data values
     */
    public static String dumpOf (Object obj)
    {
        return new Row(obj).toString();
    }

    //------------//
    // htmlDumpOf //
    //------------//
    /**
     * Helper function that prints a special kind of information string, using
     * HTML tags so that an html editor can easily render this.
     *
     @param obj the object to dump
     *
     @return the HTML string
     */
    public static String htmlDumpOf (Object obj)
    {
        return new Html(obj).toString();
    }

    //-------//
    // print //
    //-------//
    /**
     * Print the dump string onto the standard output
     */
    public void print ()
    {
        System.out.println(toString());
    }

    //----------//
    // toString //
    //----------//
    /**
     * Return the string buffer content
     *
     @return the dump of the object as a string
     */
    @Override
    public String toString ()
    {
        // Do the processing
        processObject();

        // Return the final content of string buffer
        return sb.toString();
    }

    //------------------//
    // printClassEpilog //
    //------------------//
    /**
     * To be overridden so as to print the epilog of class data
     */
    protected void printClassEpilog ()
    {
    }

    //------------------//
    // printClassProlog //
    //------------------//
    /**
     * To be overridden so as to print the prolog of class data
     */
    protected void printClassProlog ()
    {
    }

    //----------------------//
    // printCollectionValue //
    //----------------------//
    protected void printCollectionValue (Collection col)
    {
        sb.append("[");

        int i = 0;

        for (Object obj : col) {
            if (i++ > 0) {
                sb.append(useHtml ? ",<br/>" ",");
            }

            // Safeguard action when the object is a big collection
            if (i > MAX_COLLECTION_INDEX) {
                sb.append(" ... " + col.size() " items");

                break;
            else {
                sb.append(obj);
            }
        }

        sb.append("]");
    }

    //------------//
    // printField //
    //------------//
    /**
     * Basic printing of field name and value. The method can of course be
     * overridden.
     *
     @param name  the field name
     @param value the field value, which may be null
     */
    protected void printField (String name,
                               Object value)
    {
        if (value == null) {
            sb.append("null");
        else {
            if (value instanceof Collection) {
                printCollectionValue((Collectionvalue);
            else if (value instanceof Map) {
                printCollectionValue(((Mapvalue).entrySet());
            else {
                sb.append(value.toString());
            }
        }
    }

    //--------------//
    // processClass //
    //--------------//
    private void processClass ()
    {
        // Class Prolog
        printClassProlog();

        // Process the class Fields
        for (Field field : cl.getDeclaredFields()) {
            processField(field);
        }

        // Class Epilog
        printClassEpilog();
    }

    //--------------//
    // processField //
    //--------------//
    private void processField (Field field)
    {
        // Check that we are really interested in printing this field out
        if (isFieldRelevant(field)) {
            // Override any access limitation
            field.setAccessible(true);

            try {
                // Retrieve field value in the object instance
                Object value = field.get(obj);

                // Print the field value as requested
                printField(field.getName(), value);
            catch (IllegalAccessException ex) {
                // Cannot occur in fact, thanks to setAccessible
            }
        }
    }

    //---------------//
    // processObject //
    //---------------//
    private void processObject ()
    {
        do {
            // Process the class at hand
            processClass();

            // Walk up the inheritance tree
            cl = cl.getSuperclass();
        while (isClassRelevant(cl));
    }

    //~ Inner Classes ----------------------------------------------------------

    //--------//
    // Column //
    //--------//
    /**
     * Class <code>Column</code> implements a Dumper where all fields are
     * presented in one column, each field on a separate line. The column can be
     * left indented, according to the specified indentation level.
     */
    public static class Column
        extends Dumper
    {
        //~ Static fields/initializers -----------------------------------------

        private static final String MEMBER_GAP = "   ";
        private static final String INDENT_GAP = ".  ";

        //~ Instance fields ----------------------------------------------------

        private final String       title;
        private final StringBuffer prefix;

        //~ Constructors -------------------------------------------------------

        public Column (Object obj,
                       String title,
                       int    level)
        {
            super(obj, false);

            // Cache the title
            if (title != null) {
                this.title = title;
            else {
                this.title = "";
            }

            // Prepare indent prefix
            prefix = new StringBuffer(level * INDENT_GAP.length());

            for (int i = level; i > 0; i--) {
                prefix.append(INDENT_GAP);
            }
        }

        //~ Methods ------------------------------------------------------------

        @Override
        protected void printClassProlog ()
        {
            // We print the class name only for the lowest class in
            // heritance hierarchy
            if (obj.getClass() == cl) {
                sb.append("\n");
                sb.append(prefix)
                  .append(cl.getName());
                sb.append(" ")
                  .append(title)
                  .append(":");
            }
        }

        @Override
        protected void printField (String name,
                                   Object value)
        {
            sb.append("\n");
            sb.append(prefix)
              .append(MEMBER_GAP);
            sb.append(name)
              .append("=");
            super.printField(name, value);
        }
    }

    //------//
    // Html //
    //------//
    /**
     * Class <code>Html</code> implements a Dumper using HTML tags to present
     * fields in a table.
     */
    public static class Html
        extends Dumper
    {
        //~ Constructors -------------------------------------------------------

        protected Html (Object obj)
        {
            super(obj, true);
        }

        //~ Methods ------------------------------------------------------------

        @Override
        public String toString ()
        {
            // Style
            sb.append("<style> td {")
              .append(" font-family: Lucida Console, Verdana, sans-serif;")
              .append(" font-size: 9px;")
              .append(" font-style: normal;")
              .append("} </style>");

            // Table begin
            sb.append("<table border=0 cellpadding=3>");

            // The object
            super.processObject();

            // Table end
            sb.append("</table>");

            // Return the final content of string buffer
            return sb.toString();
        }

        @Override
        protected void printClassProlog ()
        {
            // Class name
            sb.append("<tr><td colspan=2><font color='BLUE'>")
              .append(cl.getName())
              .append("</font></td></tr>");
        }

        @Override
        protected void printField (String name,
                                   Object value)
        {
            // One table row per field
            sb.append("<tr>");

            // First the field name
            sb.append("<td align='right'><font color='RED'>")
              .append(name)
              .append("</font></td>");

            // Then the field value
            sb.append("<td>");
            super.printField(name, value);

            sb.append("</td>")
              .append("</tr>");
        }
    }

    //-----//
    // Row //
    //-----//
    /**
     * Class <code>Row</code> implements a Dumper where all fields are presented
     * on the same line.
     */
    public static class Row
        extends Dumper
    {
        //~ Constructors -------------------------------------------------------

        protected Row (Object obj)
        {
            super(obj, false);
        }

        //~ Methods ------------------------------------------------------------

        @Override
        protected void printClassEpilog ()
        {
            sb.append("}");
        }

        @Override
        protected void printClassProlog ()
        {
            // Class name
            sb.append("{");

            // Special annotation for superclass
            if (obj.getClass() != cl) {
                sb.append("from ");
            }

            sb.append(cl.getName())
              .append(":");
        }

        @Override
        protected void printField (String name,
                                   Object value)
        {
            sb.append(" ");
            sb.append(name)
              .append("=");
            super.printField(name, value);
        }
    }
}

   
    
    
  
Related examples in the same category
1. A simple logging facility.
2. Debug Utilities
3. Debug InputStream
4. Methods for printing Debug messages
5. Trace InputStream
6. Trace OutputStream
7. Debug Utility
8. Swing Console
9. How to do Benchmark
10. Methods for logging events
11. Printing indented text
12. Prints messages formatted for a specific line width.
13. Class providing static methods to log diagnostics
14. A bean that can be used to keep track of a counter
15. An integer synchronized counter class.
16. Counts down from a specified value the number of bytes actually read from the wrapped InputStream.
17. A long integer counter class
18. Logging class to record errors or unexpected behavior to a file
19. Handle obtaining string timestamps
20. Scans java source files in cvs tree and validates the license header
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.