Skip to content

Instantly share code, notes, and snippets.

@jawspeak
Created August 19, 2010 16:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jawspeak/538350 to your computer and use it in GitHub Desktop.
Save jawspeak/538350 to your computer and use it in GitHub Desktop.
BeanDumper useful for printing java objects
package com.example.utility;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import static com.google.common.collect.Iterables.*;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import java.beans.BeanInfo;
import static java.beans.Introspector.*;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static java.lang.String.*;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class BeanDumper {
private interface Processor {
boolean canProcess(Object value);
void dump(Object value, String context, BeanDumper dumper) throws Throwable;
}
private class PrimitiveProcessor implements Processor {
private List<Class> types = ImmutableList.<Class>builder().
add(BigDecimal.class).
add(BigInteger.class).
add(Boolean.class).
add(Boolean.TYPE).
add(Byte.class).
add(Byte.TYPE).
add(Character.class).
add(Character.TYPE).
add(Class.class).
add(Date.class).
add(Double.class).
add(Double.TYPE).
add(Float.class).
add(Float.TYPE).
add(Integer.class).
add(Integer.TYPE).
add(LocalDate.class).
add(LocalDateTime.class).
add(LocalTime.class).
add(Long.class).
add(Long.TYPE).
add(Short.class).
add(Short.TYPE).
add(String.class).
build();
public boolean canProcess(Object value) {
return value == null || value.getClass().isEnum() || types.contains(value.getClass());
}
public void dump(Object value, String context, BeanDumper dumper) throws Exception {
out.printf("%s=%s\n", context, value);
}
}
private class MapProcessor implements Processor {
public boolean canProcess(Object value) {
return value instanceof Map;
}
public void dump(Object value, String context, BeanDumper dumper) throws Exception {
for (Map.Entry item : (Set<Map.Entry>) ((Map) value).entrySet()) {
dumper.dump(item.getValue(), format("%s[%s]", context, item.getKey()));
}
}
}
private class ArrayProcessor implements Processor {
public boolean canProcess(Object value) {
return value.getClass().isArray();
}
public void dump(Object value, String context, BeanDumper dumper) throws Exception {
int length = Array.getLength(value);
for (int index = 0; index < length; index++) {
Object item = Array.get(value, index);
dumper.dump(item, format("%s[%s]", context, index));
}
}
}
private class IterableProcessor implements Processor {
public boolean canProcess(Object value) {
return value instanceof Iterable;
}
public void dump(Object value, String context, BeanDumper dumper) throws Exception {
int index = 0;
for (Object item : (Iterable) value) {
dumper.dump(item, format("%s[%s]", context, index++));
}
}
}
private class BeanProcessor implements Processor {
public boolean canProcess(Object value) {
return true;
}
public void dump(Object value, String context, BeanDumper dumper) throws Throwable {
BeanInfo beanInfo = getBeanInfo(value.getClass());
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
Method readMethod = descriptor.getReadMethod();
if (readMethod == null) continue;
try {
dumper.dump(readMethod.invoke(value), format("%s.%s", context, descriptor.getName()));
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
}
private static class CanProcess implements Predicate<Processor> {
private final Object value;
public CanProcess(Object value) {
this.value = value;
}
public boolean apply(Processor processor) {
return processor.canProcess(value);
}
}
private List<Processor> processors = ImmutableList.<Processor>builder().
add(new PrimitiveProcessor()).
add(new MapProcessor()).
add(new IterableProcessor()).
add(new ArrayProcessor()).
add(new BeanProcessor()).
build();
private PrintStream out = System.out;
public BeanDumper() {
}
public static String dumpToString(Object value, String context) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BeanDumper beanDumper = new BeanDumper(new PrintStream(baos));
beanDumper.dump(value, context);
return baos.toString();
}
public BeanDumper(PrintStream out) {
this.out = out;
}
public void dump(Object value, String context) {
try {
find(processors, new CanProcess(value)).dump(value, context, this);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
package com.example.utility;
import com.google.common.collect.Lists;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
public class BeanDumperTest {
@Test
public void dumpList() {
String expected = "list[0]=null\n" +
"list[1]=null\n";
assertEquals(expected, BeanDumper.dumpToString(Lists.newArrayList(null, null), "list"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment