1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.sun.syndication.common;
18
19 import java.beans.BeanInfo;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.lang.reflect.Array;
23 import java.lang.reflect.Method;
24 import java.util.Collection;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.io.Serializable;
28
29 /***
30 * Provides deep <b>Bean</b> toString support.
31 * <p>
32 * It works on all read/write properties, recursively. It support all primitive types, Strings, Collections,
33 * ToString objects and multi-dimensional arrays of any of them.
34 * <p>
35 * @author Alejandro Abdelnur
36 *
37 */
38 public class ToStringBean implements Serializable, ToString {
39
40 private static final Object[] NO_PARAMS = new Object[0];
41
42 private Object _obj;
43
44 /***
45 * Default constructor.
46 * <p>
47 * To be used by classes extending ToStringBean only.
48 * <p>
49 *
50 */
51 protected ToStringBean() {
52 _obj = this;
53 }
54
55 /***
56 * Creates a ToStringBean to be used in a delegation pattern.
57 * <p>
58 * For example:
59 * <p>
60 * <code>
61 * public class Foo implements ToString {
62 *
63 * public String toString(String prefix) {
64 * ToStringBean tsb = new ToStringBean(this);
65 * return tsb.toString(prefix);
66 * }
67 *
68 * public String toString() {
69 * return toString("Foo");
70 * }
71 *
72 * }
73 * </code>
74 * <p>
75 * @param obj object bean to create String representation.
76 *
77 */
78 public ToStringBean(Object obj) {
79 _obj = obj;
80 }
81
82 /***
83 * Returns the String representation of the bean given in the constructor.
84 * <p>
85 * It uses the Class name as the prefix.
86 * <p>
87 * @return bean object String representation.
88 *
89 */
90 public String toString() {
91 String className = _obj.getClass().getName();
92 className = className.substring(className.lastIndexOf(".")+1);
93 return toString(className);
94 }
95
96 /***
97 * Returns the String representation of the bean given in the constructor.
98 * <p>
99 * @param prefix to use for bean properties.
100 * @return bean object String representation.
101 *
102 */
103 public String toString(String prefix) {
104 StringBuffer sb = new StringBuffer(128);
105 try {
106 BeanInfo bi = Introspector.getBeanInfo(_obj.getClass());
107 PropertyDescriptor[] pds = bi.getPropertyDescriptors();
108 if (pds!=null) {
109 for (int i=0;i<pds.length;i++) {
110 String pName = pds[i].getName();
111 Method pReadMethod = pds[i].getReadMethod();
112 if (pReadMethod!=null &&
113 pReadMethod.getDeclaringClass()!=Object.class &&
114 pReadMethod.getParameterTypes().length==0) {
115 Object value = pReadMethod.invoke(_obj,NO_PARAMS);
116 printProperty(sb,prefix+"."+pName,value);
117 }
118 }
119 }
120 }
121 catch (Exception ex) {
122 sb.append("\n\nEXCEPTION: Could not complete ").append(_obj.getClass()).append(".toString()\n");
123 }
124 return sb.toString();
125 }
126
127 private void printProperty(StringBuffer sb,String prefix,Object value) {
128 if (value==null) {
129 sb.append(prefix).append("=null\n");
130 }
131 else
132 if (value.getClass().isArray()) {
133 printArrayProperty(sb,prefix,value);
134 }
135 else
136 if (value instanceof ToString) {
137 ToString ts = (ToString) value;
138 sb.append(ts.toString(prefix));
139 }
140 else
141 if (value instanceof Map) {
142 Map map = (Map) value;
143 Iterator i = map.entrySet().iterator();
144 if (i.hasNext()) {
145 while (i.hasNext()) {
146 Map.Entry me = (Map.Entry) i.next();
147 String ePrefix = prefix+"["+me.getKey()+"]";
148 Object eValue = me.getValue();
149 if (eValue instanceof ToString) {
150 ToString ts = (ToString) eValue;
151 sb.append(ts.toString(ePrefix));
152 }
153 else {
154 sb.append(ePrefix).append("=").append(eValue).append("\n");
155 }
156 }
157 }
158 else {
159 sb.append(prefix).append("=[]\n");
160 }
161 }
162 else
163 if (value instanceof Collection) {
164 Collection collection = (Collection) value;
165 Iterator i = collection.iterator();
166 if (i.hasNext()) {
167 int c = 0;
168 while (i.hasNext()) {
169 String cPrefix = prefix+"["+(c++)+"]";
170 Object cValue = i.next();
171 if (cValue instanceof ToString) {
172 ToString ts = (ToString) cValue;
173 sb.append(ts.toString(cPrefix));
174 }
175 else {
176 sb.append(cPrefix).append("=").append(cValue).append("\n");
177 }
178 }
179 }
180 else {
181 sb.append(prefix).append("=[]\n");
182 }
183 }
184 else {
185 sb.append(prefix).append("=").append(value).append("\n");
186 }
187 }
188
189 private void printArrayProperty(StringBuffer sb, String prefix,Object array) {
190 int length = Array.getLength(array);
191 for (int i=0;i<length;i++) {
192 Object obj = Array.get(array,i);
193 printProperty(sb,prefix+"["+i+"]",obj);
194 }
195 }
196
197 }
198