1 package org.altusmetrum.AltosDroid;
\r
3 import java.lang.reflect.Array;
\r
4 import java.lang.reflect.Field;
\r
5 import java.util.HashMap;
\r
7 public class Dumper {
\r
8 private static Dumper instance = new Dumper();
\r
10 protected static Dumper getInstance() {
\r
16 int maxArrayElements = 0;
\r
18 HashMap<String, String> ignoreList = new HashMap<String, String>();
\r
19 HashMap<Object, Integer> visited = new HashMap<Object, Integer>();
\r
22 public static String dump(Object o) {
\r
23 return dump(o, 0, 0, null);
\r
26 public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {
\r
27 DumpContext ctx = Dumper.getInstance().new DumpContext();
\r
28 ctx.maxDepth = maxDepth;
\r
29 ctx.maxArrayElements = maxArrayElements;
\r
31 if (ignoreList != null) {
\r
32 for (int i = 0; i < Array.getLength(ignoreList); i++) {
\r
33 int colonIdx = ignoreList[i].indexOf(':');
\r
35 ignoreList[i] = ignoreList[i] + ":";
\r
36 ctx.ignoreList.put(ignoreList[i], ignoreList[i]);
\r
40 return dump(o, ctx);
\r
43 protected static String dump(Object o, DumpContext ctx) {
\r
49 StringBuffer tabs = new StringBuffer();
\r
50 for (int k = 0; k < ctx.callCount; k++) {
\r
53 StringBuffer buffer = new StringBuffer();
\r
54 @SuppressWarnings("rawtypes")
\r
55 Class oClass = o.getClass();
\r
57 String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);
\r
59 if (ctx.ignoreList.get(oSimpleName + ":") != null)
\r
62 if (oClass.isArray()) {
\r
63 buffer.append("\n");
\r
64 buffer.append(tabs.toString().substring(1));
\r
65 buffer.append("[\n");
\r
66 int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));
\r
67 for (int i = 0; i < rowCount; i++) {
\r
68 buffer.append(tabs.toString());
\r
70 Object value = Array.get(o, i);
\r
71 buffer.append(dumpValue(value, ctx));
\r
72 } catch (Exception e) {
\r
73 buffer.append(e.getMessage());
\r
75 if (i < Array.getLength(o) - 1)
\r
77 buffer.append("\n");
\r
79 if (rowCount < Array.getLength(o)) {
\r
80 buffer.append(tabs.toString());
\r
81 buffer.append(Array.getLength(o) - rowCount + " more array elements...");
\r
82 buffer.append("\n");
\r
84 buffer.append(tabs.toString().substring(1));
\r
87 buffer.append("\n");
\r
88 buffer.append(tabs.toString().substring(1));
\r
89 buffer.append("{\n");
\r
90 buffer.append(tabs.toString());
\r
91 buffer.append("hashCode: " + o.hashCode());
\r
92 buffer.append("\n");
\r
93 while (oClass != null && oClass != Object.class) {
\r
94 Field[] fields = oClass.getDeclaredFields();
\r
96 if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {
\r
97 if (oClass != o.getClass()) {
\r
98 buffer.append(tabs.toString().substring(1));
\r
99 buffer.append(" Inherited from superclass " + oSimpleName + ":\n");
\r
102 for (int i = 0; i < fields.length; i++) {
\r
104 String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());
\r
105 String fName = fields[i].getName();
\r
107 fields[i].setAccessible(true);
\r
108 buffer.append(tabs.toString());
\r
109 buffer.append(fName + "(" + fSimpleName + ")");
\r
110 buffer.append("=");
\r
112 if (ctx.ignoreList.get(":" + fName) == null &&
\r
113 ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&
\r
114 ctx.ignoreList.get(fSimpleName + ":") == null) {
\r
117 Object value = fields[i].get(o);
\r
118 buffer.append(dumpValue(value, ctx));
\r
119 } catch (Exception e) {
\r
120 buffer.append(e.getMessage());
\r
122 buffer.append("\n");
\r
124 buffer.append("<Ignored>");
\r
125 buffer.append("\n");
\r
128 oClass = oClass.getSuperclass();
\r
129 oSimpleName = oClass.getSimpleName();
\r
135 buffer.append(tabs.toString().substring(1));
\r
136 buffer.append("}");
\r
139 return buffer.toString();
\r
142 protected static String dumpValue(Object value, DumpContext ctx) {
\r
143 if (value == null) {
\r
146 if (value.getClass().isPrimitive() ||
\r
147 value.getClass() == java.lang.Short.class ||
\r
148 value.getClass() == java.lang.Long.class ||
\r
149 value.getClass() == java.lang.String.class ||
\r
150 value.getClass() == java.lang.Integer.class ||
\r
151 value.getClass() == java.lang.Float.class ||
\r
152 value.getClass() == java.lang.Byte.class ||
\r
153 value.getClass() == java.lang.Character.class ||
\r
154 value.getClass() == java.lang.Double.class ||
\r
155 value.getClass() == java.lang.Boolean.class) {
\r
157 return value.toString();
\r
161 Integer visitedIndex = ctx.visited.get(value);
\r
162 if (visitedIndex == null) {
\r
163 ctx.visited.put(value, ctx.callCount);
\r
164 if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {
\r
165 return dump(value, ctx);
\r
167 return "<Reached max recursion depth>";
\r
170 return "<Previously visited - see hashCode " + value.hashCode() + ">";
\r
176 private static String getSimpleNameWithoutArrayQualifier(@SuppressWarnings("rawtypes") Class clazz) {
\r
177 String simpleName = clazz.getSimpleName();
\r
178 int indexOfBracket = simpleName.indexOf('[');
\r
179 if (indexOfBracket != -1)
\r
180 return simpleName.substring(0, indexOfBracket);
\r