001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.walker;
006:
007: import com.tc.util.ClassUtils;
008:
009: import java.lang.reflect.Field;
010:
011: /**
012: * Produces a textual representation of the type visited
013: */
014: public class PrintVisitor implements Visitor {
015: private static final String INDENT = " ";
016: private final OutputSink out;
017: private final WalkTest walkTest;
018: private final ValueFormatter formatter;
019:
020: public PrintVisitor(OutputSink sink, WalkTest walkTest,
021: ValueFormatter formatter) {
022: this .out = sink;
023: this .walkTest = walkTest;
024: this .formatter = formatter;
025: }
026:
027: public void visitRootObject(MemberValue value) {
028: outputLine(typeDisplay(value.getValueObject().getClass())
029: + " (id " + value.getId() + ")");
030: }
031:
032: private void outputLine(String line) {
033: out.output(line);
034: }
035:
036: public void visitValue(MemberValue value, int depth) {
037: StringBuffer buf = new StringBuffer();
038: boolean isLiteral = !walkTest.shouldTraverse(value);
039:
040: indent(depth, buf);
041:
042: if (value.isMapKey()) {
043: buf.append("key ");
044: } else if (value.isMapValue()) {
045: buf.append("value ");
046: }
047:
048: Field field = value.getSourceField();
049: if (field != null) {
050: buf.append(typeDisplay(field.getType()) + " ");
051: boolean shadowed = value.isShadowed();
052: if (shadowed) {
053: buf.append(field.getDeclaringClass().getName() + ".");
054: }
055:
056: buf.append(field.getName() + " ");
057: }
058:
059: if (value.isElement()) {
060: buf.append("[" + value.getIndex() + "] ");
061: }
062:
063: buf.append("= ");
064:
065: Object o = value.getValueObject();
066:
067: if (isLiteral || o == null) {
068: buf.append(formatter.format(value.getValueObject()));
069: } else {
070: if (value.isRepeated()) {
071: buf.append("(ref id " + value.getId() + ")");
072: } else {
073: if ((field != null)
074: && (o.getClass().equals(field.getType()))) {
075: buf.append("(id " + value.getId() + ")");
076: } else {
077: buf.append("(" + typeDisplay(o.getClass())
078: + ", id " + value.getId() + ")");
079: }
080: }
081: }
082:
083: String adorn = formatter.valueAdornment(value);
084: if (adorn != null) {
085: buf.append(adorn);
086: }
087:
088: outputLine(buf.toString());
089: }
090:
091: private static final String JAVA_LANG = "java.lang.";
092: private static final int JAVA_LANG_LEN = JAVA_LANG.length();
093:
094: private static final String JAVA_UTIL = "java.util.";
095: private static final int JAVA_UTIL_LEN = JAVA_UTIL.length();
096:
097: private static String typeDisplay(Class c) {
098: String type = c.getName();
099: int dim = 0;
100: if (c.isArray()) {
101: dim = ClassUtils.arrayDimensions(c);
102: type = ClassUtils.baseComponentType(c).getName();
103: }
104:
105: if (type.startsWith(JAVA_LANG)
106: && type.lastIndexOf('.') + 1 == JAVA_LANG_LEN) {
107: type = type.substring(JAVA_LANG_LEN);
108: } else if (type.startsWith(JAVA_UTIL)
109: && type.lastIndexOf('.') + 1 == JAVA_UTIL_LEN) {
110: type = type.substring(JAVA_UTIL_LEN);
111: }
112:
113: for (int i = 0; i < dim; i++) {
114: type = type + "[]";
115: }
116:
117: return type;
118: }
119:
120: public void visitMapEntry(int index, int depth) {
121: StringBuffer buf = new StringBuffer();
122: indent(depth, buf);
123: buf.append("[entry ").append(index).append("]");
124: outputLine(buf.toString());
125: }
126:
127: private static void indent(int currentDepth, StringBuffer buffer) {
128: while (currentDepth-- > 0) {
129: buffer.append(INDENT);
130: }
131: }
132:
133: public interface OutputSink {
134: void output(String line);
135: }
136:
137: public interface ValueFormatter {
138: String format(Object value);
139:
140: String valueAdornment(MemberValue value);
141: }
142:
143: }
|