All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.engine.introspection.CallTracer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2014:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but without any warranty; without even the implied warranty of
 *    merchantability or fitness for a particular purpose.  See the
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.introspection;

import java.io.PrintStream;
import java.util.LinkedList;

import org.apache.commons.lang.StringUtils;

public class CallTracer {
    private static final String CALLING_CLASS_OPENING_TAG = "<@";
    private static final String CALLING_CLASS_CLOSING_TAG = ">";
    private static final String INDENTATION = "| ";
    private static final String METHOD_PARAMETER_BULLET = "* ";

    private static CallNode callTree = new RootNode();
    private static CallNode current = callTree;

    private static boolean enabled = true;

    private static class CallNode {
        public final String description;
        public final CallNode parent;
        public final LinkedList children;

        public CallNode(String description, CallNode parent) {
            this(description, parent, new LinkedList());
        }

        public CallNode(String description, CallNode parent, LinkedList children) {
            this.description = description;
            this.parent = parent;
            this.children = children;
        }

        public void dump(int indent, PrintStream out) {
            String indentSpaces = StringUtils.repeat(INDENTATION, indent);
            println(out, indentSpaces + description);
            for (CallNode node : children) {
                node.dump(indent + 1, out);
            }
        }
    }

    private static class RootNode extends CallNode {
        public RootNode() {
            super(null, null);
        }

        @Override
        public void dump(int indent, PrintStream out) {
            // don't print the label
            for (CallNode node : children) {
                node.dump(indent + 1, out);
            }
        }
    }

    private static class MessageNode extends CallNode {
        public MessageNode(String message, CallNode parent) {
            super(message, parent, null);
        }

        @Override
        public void dump(int indent, PrintStream out) {
            String indentSpaces = StringUtils.repeat(INDENTATION, indent);
            println(out, indentSpaces + description);
        }
    }

    /**
     * use carefully - watch out for enable/disable synchronization and nesting quirks
     */
    public static void disable() {
        enabled = false;
        clear();
    }

    /**
     * enable() can safely be called repeatedly
     */
    public static void enable() {
        enabled = true;
    }

    static void println(PrintStream out, String s) {
        if (out != null) {
            out.println(s);
        }
    }

    public static void indent(String methodDescription) {
        if (!enabled) {
            return;
        }
        CallNode newNode = new CallNode(methodDescription, current);
        current.children.add(newNode);
        current = newNode;
    }

    public static void indent(String string, Object caller) {
        indent(string, caller, new Object[] {});
    }

    public static void indent(String string, Object caller, Object... arguments) {
        indent(detailedDescription(string, caller));
        for (Object argument : arguments) {
            msg(METHOD_PARAMETER_BULLET + detailedDescription(argument));
        }
    }

    public static String detailedDescription(String string, Object object) {
        return string + " " + CALLING_CLASS_OPENING_TAG + detailedDescription(object)
                + CALLING_CLASS_CLOSING_TAG;
    }

    public static String detailedDescription(Object object) {
        if (object == null) {
            return "(null)";
        }
        return object.getClass().getSimpleName() + " " + object.toString() + ":"
                + System.identityHashCode(object);
    }

    public static void msg(String message) {
        if (!enabled) {
            return;
        }
        CallNode newNode = new MessageNode(message, current);
        current.children.add(newNode);
    }

    public static void msg(String string, Object caller) {
        msg(detailedDescription(string, caller));
    }

    public static void unIndent() {
        if (!enabled) {
            return;
        }
        current = current.parent;
    }

    public static void unIndent(String string, Object caller) {
        if (!enabled) {
            return;
        }
        msg(string, caller);
        current = current.parent;
    }

    public static void dump(PrintStream out) {
        if (!enabled) {
            return;
        }
        callTree.dump(-1, out); // account for the root node (start at 0 for the next level)
        clear();
    }

    public static void clear() {
        callTree = new RootNode();
        current = callTree;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy