1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.interceptor.debugging;
23
24 import java.beans.IntrospectionException;
25 import java.io.Writer;
26 import java.util.Collection;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31
32 import com.opensymphony.xwork2.util.reflection.ReflectionException;
33 import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
34
35 /***
36 * Writes an object as a table, where each field can be expanded if it is an Object/Collection/Array
37 *
38 */
39 class ObjectToHTMLWriter {
40 private PrettyPrintWriter prettyWriter;
41
42 ObjectToHTMLWriter(Writer writer) {
43 this.prettyWriter = new PrettyPrintWriter(writer);
44 this.prettyWriter.setEscape(false);
45 }
46
47 @SuppressWarnings("unchecked")
48 public void write(ReflectionProvider reflectionProvider, Object root, String expr) throws IntrospectionException,
49 ReflectionException {
50 prettyWriter.startNode("table");
51 prettyWriter.addAttribute("class", "debugTable");
52
53 if (root instanceof Map) {
54 for (Iterator iterator = ((Map) root).entrySet().iterator(); iterator
55 .hasNext();) {
56 Map.Entry property = (Map.Entry) iterator.next();
57 String key = property.getKey().toString();
58 Object value = property.getValue();
59 writeProperty(key, value, expr);
60 }
61 } else if (root instanceof List) {
62 List list = (List) root;
63 for (int i = 0; i < list.size(); i++) {
64 Object element = list.get(i);
65 writeProperty(String.valueOf(i), element, expr);
66 }
67 } else if (root instanceof Set) {
68 Set set = (Set) root;
69 for (Iterator iterator = set.iterator(); iterator.hasNext();) {
70 writeProperty("", iterator.next(), expr);
71 }
72 } else if (root.getClass().isArray()) {
73 Object[] objects = (Object[]) root;
74 for (int i = 0; i < objects.length; i++) {
75 writeProperty(String.valueOf(i), objects[i], expr);
76 }
77 } else {
78
79 Map<String, Object> properties = reflectionProvider.getBeanMap(root);
80 for (Map.Entry<String, Object> property : properties.entrySet()) {
81 String name = property.getKey();
82 Object value = property.getValue();
83
84 if ("class".equals(name))
85 continue;
86
87 writeProperty(name, value, expr);
88 }
89 }
90
91 prettyWriter.endNode();
92 }
93
94 private void writeProperty(String name, Object value, String expr) {
95 prettyWriter.startNode("tr");
96
97
98 prettyWriter.startNode("td");
99 prettyWriter.addAttribute("class", "nameColumn");
100 prettyWriter.setValue(name);
101 prettyWriter.endNode();
102
103
104 prettyWriter.startNode("td");
105 if (value != null) {
106
107 if (value != null &&
108 (isEmptyCollection(value) || isEmptyMap(value) || (value.getClass()
109 .isArray() && ((Object[]) value).length == 0))) {
110 prettyWriter.addAttribute("class", "emptyCollection");
111 prettyWriter.setValue("empty");
112 } else {
113 prettyWriter.addAttribute("class", "valueColumn");
114 writeValue(name, value, expr);
115 }
116 } else {
117 prettyWriter.addAttribute("class", "nullValue");
118 prettyWriter.setValue("null");
119 }
120 prettyWriter.endNode();
121
122
123 prettyWriter.startNode("td");
124 if (value != null) {
125 prettyWriter.addAttribute("class", "typeColumn");
126 Class clazz = value.getClass();
127 prettyWriter.setValue(clazz.getName());
128 } else {
129 prettyWriter.addAttribute("class", "nullValue");
130 prettyWriter.setValue("unknown");
131 }
132 prettyWriter.endNode();
133
134
135 prettyWriter.endNode();
136 }
137
138 /***
139 * Some maps, like AttributeMap will throw an exception when isEmpty() is called
140 */
141 private boolean isEmptyMap(Object value) {
142 try {
143 return value instanceof Map && ((Map) value).isEmpty();
144 } catch (Exception e) {
145 return true;
146 }
147 }
148
149 /***
150 * Some collections might throw an exception when isEmpty() is called
151 */
152 private boolean isEmptyCollection(Object value) {
153 try {
154 return value instanceof Collection && ((Collection) value).isEmpty();
155 } catch (Exception e) {
156 return true;
157 }
158 }
159
160 private void writeValue(String name, Object value, String expr) {
161 Class clazz = value.getClass();
162 if (clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) ||
163 clazz.equals(String.class) || Boolean.class.equals(clazz)) {
164 prettyWriter.setValue(String.valueOf(value));
165 } else {
166 prettyWriter.startNode("a");
167 String path = expr.replaceAll("#", "%23") + "[\"" +
168 name.replaceAll("#", "%23") + "\"]";
169 prettyWriter.addAttribute("onclick", "expand(this, '" + path + "')");
170 prettyWriter.addAttribute("href", "javascript://nop/");
171 prettyWriter.setValue("Expand");
172 prettyWriter.endNode();
173 }
174 }
175 }