
org.integratedmodelling.engine.introspection.CallTracer Maven / Gradle / Ivy
/*******************************************************************************
* 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 - 2025 Weber Informatics LLC | Privacy Policy