/*
* Created on Oct 13, 2003
*
* Works with beans that have private members, arrays, collections, ... whatever.
*
* @author Pinkham
*/
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* Get a debug string from any bean. Handles arrays and Collections.
* Does NOT detect reference cycles (stack will overflow).
*/
public final class DebugPrint {
private DebugPrint() {}
// setter methods below let you change these to suit your style
private static String beanPrefix = ":{";
private static String beanSuffix = "}";
private static String valueSeparator = "=";
private static String nullStr = "null";
private static String elementSeparator = "\n";
private static String propertySeparator = "\n"; // try ";" or "," for brevity
/**
* Given a JavaBean (an object with getter methods) this method will
* find and call the getter methods and prepare a toString
* that lists the values of all it's properties. The format looks like this:
*
* package.BeanName:{prop=value\nprop2=value2}
*
*/
public static String toString(Object bean)
{
if (bean == null)
return nullStr;
// Put classes that need special handling here...
if (bean instanceof java.util.Calendar)
return ((java.util.Calendar)bean).getTime().toString();
Class c = bean.getClass();
if (isLeafClass(c))
return bean.toString(); // bean must be just a primitive type
BeanInfo bi;
try
{
bi = Introspector.getBeanInfo(c, Object.class); // don't want Object methods like getClass
} catch (IntrospectionException e)
{
bi = null;
}
PropertyDescriptor[] pd = null;
if (bi != null)
pd = bi.getPropertyDescriptors();
if (pd == null || pd.length==0) // no properties
return bean.toString();
String ret = c.getName()+beanPrefix;
for (int i=0; i<pd.length; ++i)
{
if (i>0)
ret += propertySeparator;
//ret += pd[i].getName() + valueSeparator;
Method getter = pd[i].getReadMethod();
if (getter == null) // skip props with setter only
continue;
Object value;
try
{
value = getter.invoke(bean, new Object[0]);
} catch (Exception e) // invokationTarget, illegalArgument, illegalAccess
{
value = e.toString();
}
if (getter.getReturnType().isArray())
{
if (value == null)
{
ret += pd[i].getName() + "[]" + valueSeparator + nullStr;
} else
{
Object[] values = (Object[]) value;
for (int j=0; j<values.length; ++j)
{
if (j>0)
ret += elementSeparator;
ret += pd[i].getName() + "[" + j + "]" + valueSeparator + toString(values[j]);
}
}
} else
{
if (value instanceof Collection)
{
Iterator k = ((Collection)value).iterator();
int j=0;
boolean first = true;
while (k.hasNext())
{
if (first)
{
first = false;
ret += elementSeparator;
}
ret += pd[i].getName() + "[" + j + "]" + valueSeparator + toString(k.next());
}
} else
{
ret += pd[i].getName() + valueSeparator + toString(value);
}
}
}
ret += beanSuffix;
return ret;
}
// stop recursion and just do toString for these classes
private static List LEAF_CLASSES = null;
private static boolean isLeafClass(Class c)
{
if (LEAF_CLASSES == null)
{
LEAF_CLASSES = new ArrayList();
LEAF_CLASSES.add(String.class);
LEAF_CLASSES.add(Date.class);
LEAF_CLASSES.add(Float.class);
LEAF_CLASSES.add(Double.class);
LEAF_CLASSES.add(Integer.class);
LEAF_CLASSES.add(Long.class);
}
return LEAF_CLASSES.contains(c);
}
// modify as needed to format toString result
public static void setBeanPrefix(String beanPrefix) {
DebugPrint.beanPrefix = beanPrefix;
}
public static void setBeanSuffix(String beanSuffix) {
DebugPrint.beanSuffix = beanSuffix;
}
public static void setValueSeparator(String valueSeparator) {
DebugPrint.valueSeparator = valueSeparator;
}
public static void setNullStr(String nullStr) {
DebugPrint.nullStr = nullStr;
}
public static void setArrayElementSeparator(String arrayElementSeparator) {
DebugPrint.elementSeparator = arrayElementSeparator;
}
public static void setElementSeparator(String elementSeparator) {
DebugPrint.elementSeparator = elementSeparator;
}
public static void setPropertySeparator(String propertySeparator) {
DebugPrint.propertySeparator = propertySeparator;
}
}