com.ochafik.lang.reflect.DebugUtils Maven / Gradle / Ivy
The newest version!
/*
Copyright (c) 2009-2011 Olivier Chafik, All Rights Reserved
This file is part of JNAerator (http://jnaerator.googlecode.com/).
JNAerator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
JNAerator 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JNAerator. If not, see .
*/
package com.ochafik.lang.reflect;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import com.ochafik.io.StringBufferOutputStream;
import com.ochafik.lang.AssertUtils;
public class DebugUtils {
public static abstract class FieldAccessor {
public abstract Object access(Field f, Object target) throws IllegalArgumentException, IllegalAccessException;
//public Object access(Field f, Object target) throws IllegalArgumentException, IllegalAccessException {
//return f.get(target);
//}
}
public static final void print(Object o, FieldAccessor accessor) {
print(o, System.out, false, false, "", accessor);
}
public static final void printErr(Object o, FieldAccessor accessor) {
print(o, System.err, false, false, "", accessor);
}
public static final void println(Object o, FieldAccessor accessor) {
print(o, System.out, true, false, "", accessor);
}
public static final void printlnErr(Object o, FieldAccessor accessor) {
print(o, System.err, true, false, "", accessor);
}
public static final void print(Object o) {
print(o, System.out, false, false, "", null);
}
public static final void printErr(Object o) {
print(o, System.err, false, false, "", null);
}
public static final void println(Object o) {
print(o, System.out, true, false, "", null);
}
public static final void println(Object o, PrintStream out) {
print(o, out, true, false, "", null);
}
public static final void printlnErr(Object o) {
print(o, System.err, true, false, "", null);
}
protected static String escape(String s) {
return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\t", "\\t").replace("\r", "");
}
public static final void printAsCharSequence(CharSequence o, PrintStream out, boolean lines, boolean startIndent, String indent, FieldAccessor accessor) {
out.print('"');
out.print(escape(((CharSequence)o).toString()));
out.print('"');
if (lines) out.println();
}
public static final void printStructureInsides(Object o, PrintStream out, boolean lines, boolean startIndent, String indent, FieldAccessor accessor) {
Class> type = o.getClass();
Set fields = getFields(type);
int i = 0;
for (Field f : fields) {
boolean inaccessibleValue = false;
Object v;
try {
//f.isAccessible()
v = accessor == null ? f.get(o) : accessor.access(f, o);
} catch (IllegalAccessException ex) {
// field is private and from a different package than the accessor ! Try using a getter
String fn = f.getName();
try {
Method m = type.getMethod("get" + fn.substring(0,1).toUpperCase() + fn.substring(1), new Class[0]);
v = m.invoke(o, new Object[0]);
} catch (Exception e) {
inaccessibleValue = true;
v = null;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
if (lines) {
out.print(indent);
} else if (i++ != 0) out.print("; ");
out.print(f.getName());
out.print(" = ");
if (inaccessibleValue) {
out.print('?');
} else {
print(v, out, lines, false, indent, accessor);
}
}
}
public static final void print(Object o, PrintStream out, boolean lines, boolean startIndent, String indent, FieldAccessor accessor) {
if (lines && startIndent) out.print(indent);
if (o == null) {
out.print(o);
if (lines) out.println();
return;
}
Class> type = o.getClass();
boolean isCollection = o instanceof Collection>;
if (o instanceof CharSequence) {
out.print('"');
out.print(escape(o.toString()));
out.print('"');
if (lines) out.println();
return;
} else if (type == Character.class) {
out.print('\'');
out.print(escape(o.toString()));
out.print('\'');
if (lines) out.println();
return;
} else if (!isCollection && hasToStringMethod(type)) {
out.print(o);
if (lines) out.println();
return;
}
out.print(type.getSimpleName());
out.print(" {");
if (lines) out.println();
String newIndent = indent + "\t";
if (type.isArray()) {
for (int i = 0, n = Array.getLength(o); i < n; i++) {
if (!lines && i != 0) out.print(", ");
print(Array.get(o, i), out, lines, true, newIndent, accessor);
}
} else if (isCollection) {
int i = 0;
for (Object e : (Collection>)o) {
if (!lines && i++ != 0) out.print(", ");
print(e, out, lines, true, newIndent, accessor);
}
} else {
printStructureInsides(o, out, lines, startIndent, newIndent, accessor);
}
if (lines) out.print(indent);
out.print("}");
if (lines) out.println();
}
public static Set getFields(Class> type) {
Set fields = new TreeSet(new Comparator() { public int compare(Field o1, Field o2) {
return o1.getName().compareTo(o2.getName());
}});
fields.addAll(Arrays.asList(type.getFields()));
do {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
} while ((type = type.getSuperclass()) != null);
return fields;
}
protected static void getFields_aux(Class> type, Set fields) {
}
public static boolean hasToStringMethod(Class> c) {
if (c == Object.class) return false;
for (Method m : c.getDeclaredMethods()) {
if (m.getName().equals("toString") && m.getParameterTypes().length == 0) {
return true;
}
}
return hasToStringMethod(c.getSuperclass());
}
public static void main(String[] args) {
//print(new int[] { 1, 2, 3, 4});
println(new Object[] { new AssertUtils.Test(), }, new FieldAccessor() {
public Object access(Field f, Object target) throws IllegalArgumentException, IllegalAccessException {
return f.get(target);
}
});
}
public static String toString(Object object) {
StringBufferOutputStream out = new StringBufferOutputStream();
print(object, new PrintStream(out), false, false,"", null);
return out.toString();
}
}