package com.yoursway.utils;
import static com.google.common.collect.Maps.newIdentityHashMap;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
public class DebugOutputHelper {
private static Object MARKER = Boolean.TRUE;
private static ThreadLocal<Map<Object, Object>> objectsBeingPrinted = new ThreadLocal<Map<Object, Object>>();
/**
* Field values are not used � the only point of them is to avoid
* "unused field" warnings.
*/
public static String reflectionBasedToString(Object object, Object... fieldValues) {
return reflectionBasedToString(object);
}
public static String reflectionBasedToString(Object object) {
if (isObjectBeingPrinted(object))
return "...";
startPrintingObject(object);
try {
Class<?> klass = object.getClass();
int fieldCount = countFields(klass);
String simpleName = YsDebugging.simpleNameOf(klass);
if (fieldCount == 0)
return simpleName;
boolean showFieldNames = (fieldCount > 1);
return showFields(object, klass, simpleName, showFieldNames);
} finally {
finishedPrintingObject(object);
}
}
private static String showFields(Object object, Class<?> klass, String simpleName, boolean showFieldNames) {
StringBuilder result = new StringBuilder();
result.append(simpleName);
boolean firstField = true;
for (Field field : klass.getDeclaredFields()) {
if (isStatic(field))
continue;
if (firstField) {
result.append("(");
firstField = false;
} else {
result.append(", ");
}
appendFieldWithValue(field, object, result, showFieldNames);
}
if (!firstField)
result.append(")");
return result.toString();
}
private static int countFields(Class<?> klass) {
int fieldCount = 0;
for (Class<?> currentClass = klass; currentClass != null; currentClass = currentClass.getSuperclass())
for (Field field : klass.getDeclaredFields())
if (!isStatic(field))
fieldCount++;
return fieldCount;
}
private static boolean isStatic(Field field) {
int modifiers = field.getModifiers();
return (0 != (modifiers & Modifier.STATIC));
}
private static void appendFieldWithValue(Field field, Object object, StringBuilder result, boolean showFieldNames) {
if (showFieldNames)
result.append(field.getName()).append('=');
try {
Object value = field.get(object);
result.append(value.toString());
} catch (Throwable e) {
e.printStackTrace(System.err);
result.append("<ERR>");
}
}
private static boolean isObjectBeingPrinted(Object object) {
return objectsBeingPrinted().containsKey(object);
}
private static void startPrintingObject(Object object) {
objectsBeingPrinted().put(object, MARKER);
}
private static void finishedPrintingObject(Object object) {
objectsBeingPrinted().remove(object);
}
private static Map<Object, Object> objectsBeingPrinted() {
Map<Object, Object> map = objectsBeingPrinted.get();
if (map == null) {
map = newIdentityHashMap();
objectsBeingPrinted.set(map);
}
return map;
}
}