package de.jpaw.bonaparte.util; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Map; import de.jpaw.bonaparte.core.BonaPortable; public class ToStringHelper { public static int maxSet = -1; public static int maxList = -1; public static int maxMap = -1; public static boolean showTransientFields = false; public static String toStringML(Object obj) { StringBuilder _buffer = new StringBuilder(1000); FieldOut(_buffer, new StringBuilder("\n"), true, obj); return _buffer.toString(); } public static String toStringSL(Object obj) { StringBuilder _buffer = new StringBuilder(1000); FieldOut(_buffer, null, false, obj); return _buffer.toString(); } private static void delimiter(StringBuilder _buffer, StringBuilder _currentIndent, boolean ofSuperClass) { if (_currentIndent == null) { // single line output _buffer.append(ofSuperClass ? "< " : ", "); } else { if (ofSuperClass) { _buffer.append(_currentIndent); _buffer.append("^^^"); _buffer.append(_currentIndent); } else { _buffer.append(","); _buffer.append(_currentIndent); } } } public static void FieldOut(StringBuilder _buffer, StringBuilder _currentIndent, boolean showNulls, Object value) { int count = 0; if (value == null) { _buffer.append("null"); } else if (value instanceof BonaPortable) { BonaPortable(_buffer, _currentIndent, showNulls, value); } else if (value instanceof java.util.List) { // output a list of objects boolean firstInList = true; _buffer.append("["); for (Object e : (java.util.List<?>)value) { if (!firstInList) _buffer.append(", "); firstInList = false; ++count; if (maxList >= 0 && count > maxList) { // abort, list too long _buffer.append("..."); break; } FieldOut(_buffer, _currentIndent, showNulls, e); } _buffer.append("]"); } else if (value instanceof java.util.Set) { // output a list of objects boolean firstInList = true; _buffer.append("{"); for (Object e : (java.util.Set<?>)value) { if (!firstInList) _buffer.append(", "); firstInList = false; ++count; if (maxSet >= 0 && count > maxSet) { // abort, list too long _buffer.append("..."); break; } FieldOut(_buffer, _currentIndent, showNulls, e); } _buffer.append("}"); } else if (value instanceof java.util.Map) { // output a map of objects boolean firstInList = true; _buffer.append("("); Map<?,?> m = (java.util.Map<?,?>)value; for (Map.Entry<?,?> e : m.entrySet()) { if (!firstInList) _buffer.append(", "); firstInList = false; ++count; if (maxMap >= 0 && count > maxMap) { // abort, list too long _buffer.append("..."); break; } _buffer.append(e.getKey().toString()); _buffer.append(":"); FieldOut(_buffer, _currentIndent, showNulls, e.getValue()); } _buffer.append(")"); } else { _buffer.append(value.toString()); } } public static void BonaPortable(StringBuilder _buffer, StringBuilder _currentIndent, boolean showNulls, Object obj) { _buffer.append(obj.getClass().getSimpleName()); _buffer.append("("); if (_currentIndent != null) { _currentIndent.append(" "); // indent more _buffer.append(_currentIndent); } // object output // this is mainly used for debugging, so speed is not as relevant and reflection can be used instead of generated code toStringHelperClassOut(_buffer, _currentIndent, showNulls, obj, obj.getClass()); // closure if (_currentIndent != null) { _currentIndent.setLength(_currentIndent.length() - 2); // restore previous length _buffer.append(_currentIndent); // and add for closing parenthesis } _buffer.append(")"); } // returns true if at least one field has been printed private static boolean toStringHelperClassOut(StringBuilder _buffer, StringBuilder _currentIndent, boolean showNulls, Object obj, Class<?> thisClass) { boolean firstField = true; boolean didSome = false; if (thisClass.getSuperclass() != Object.class) { // descend didSome = toStringHelperClassOut(_buffer, _currentIndent, showNulls, obj, thisClass.getSuperclass()); if (didSome) delimiter(_buffer, _currentIndent, true); } for (Field field : thisClass.getDeclaredFields()) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; // skip static fields if (!showTransientFields && (field.getModifiers() & Modifier.TRANSIENT) != 0) continue; // skip transient fields if (!firstField) delimiter(_buffer, _currentIndent, false); firstField = false; field.setAccessible(true); // You might want to set modifier to public first. Object value = null; try { value = field.get(obj); } catch (IllegalArgumentException e) { _buffer.append(field.getName()); _buffer.append(": ***Illegal argument exception***"); firstField = false; } catch (IllegalAccessException e) { _buffer.append(field.getName()); _buffer.append(": ***Illegal access exception***"); firstField = false; } if (value != null || showNulls) { _buffer.append(field.getName()); _buffer.append("="); FieldOut(_buffer, _currentIndent, showNulls, value); } } return didSome || !firstField; } }