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 com.sun.syndication.common.impl.BeanIntrospector;
20
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 Class _beanClass;
43 private Object _obj;
44
45 /***
46 * Default constructor.
47 * <p>
48 * To be used by classes extending ToStringBean only.
49 * <p>
50 * @param beanClass indicates the class to scan for properties, normally an interface class.
51 *
52 */
53 protected ToStringBean(Class beanClass) {
54 _beanClass = beanClass;
55 _obj = this;
56 }
57
58 /***
59 * Creates a ToStringBean to be used in a delegation pattern.
60 * <p>
61 * For example:
62 * <p>
63 * <code>
64 * public class Foo implements ToString {
65 *
66 * public String toString(String prefix) {
67 * ToStringBean tsb = new ToStringBean(this);
68 * return tsb.toString(prefix);
69 * }
70 *
71 * public String toString() {
72 * return toString("Foo");
73 * }
74 *
75 * }
76 * </code>
77 * <p>
78 * @param beanClass indicates the class to scan for properties, normally an interface class.
79 * @param obj object bean to create String representation.
80 *
81 */
82 public ToStringBean(Class beanClass,Object obj) {
83 _beanClass = beanClass;
84 _obj = obj;
85 }
86
87 /***
88 * Returns the String representation of the bean given in the constructor.
89 * <p>
90 * It uses the Class name as the prefix.
91 * <p>
92 * @return bean object String representation.
93 *
94 */
95 public String toString() {
96 String className = _obj.getClass().getName();
97 className = className.substring(className.lastIndexOf(".")+1);
98 return toString(className);
99 }
100
101 /***
102 * Returns the String representation of the bean given in the constructor.
103 * <p>
104 * @param prefix to use for bean properties.
105 * @return bean object String representation.
106 *
107 */
108 public String toString(String prefix) {
109 StringBuffer sb = new StringBuffer(128);
110 try {
111 PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanClass);
112 if (pds!=null) {
113 for (int i=0;i<pds.length;i++) {
114 String pName = pds[i].getName();
115 Method pReadMethod = pds[i].getReadMethod();
116 if (pReadMethod!=null &&
117 pReadMethod.getDeclaringClass()!=Object.class &&
118 pReadMethod.getParameterTypes().length==0) {
119 Object value = pReadMethod.invoke(_obj,NO_PARAMS);
120 printProperty(sb,prefix+"."+pName,value);
121 }
122 }
123 }
124 }
125 catch (Exception ex) {
126 sb.append("\n\nEXCEPTION: Could not complete ").append(_obj.getClass()).append(".toString()\n");
127 }
128 return sb.toString();
129 }
130
131 private void printProperty(StringBuffer sb,String prefix,Object value) {
132 if (value==null) {
133 sb.append(prefix).append("=null\n");
134 }
135 else
136 if (value.getClass().isArray()) {
137 printArrayProperty(sb,prefix,value);
138 }
139 else
140 if (value instanceof ToString) {
141 ToString ts = (ToString) value;
142 sb.append(ts.toString(prefix));
143 }
144 else
145 if (value instanceof Map) {
146 Map map = (Map) value;
147 Iterator i = map.entrySet().iterator();
148 if (i.hasNext()) {
149 while (i.hasNext()) {
150 Map.Entry me = (Map.Entry) i.next();
151 String ePrefix = prefix+"["+me.getKey()+"]";
152 Object eValue = me.getValue();
153 if (eValue instanceof ToString) {
154 ToString ts = (ToString) eValue;
155 sb.append(ts.toString(ePrefix));
156 }
157 else {
158 sb.append(ePrefix).append("=").append(eValue).append("\n");
159 }
160 }
161 }
162 else {
163 sb.append(prefix).append("=[]\n");
164 }
165 }
166 else
167 if (value instanceof Collection) {
168 Collection collection = (Collection) value;
169 Iterator i = collection.iterator();
170 if (i.hasNext()) {
171 int c = 0;
172 while (i.hasNext()) {
173 String cPrefix = prefix+"["+(c++)+"]";
174 Object cValue = i.next();
175 if (cValue instanceof ToString) {
176 ToString ts = (ToString) cValue;
177 sb.append(ts.toString(cPrefix));
178 }
179 else {
180 sb.append(cPrefix).append("=").append(cValue).append("\n");
181 }
182 }
183 }
184 else {
185 sb.append(prefix).append("=[]\n");
186 }
187 }
188 else {
189 sb.append(prefix).append("=").append(value).append("\n");
190 }
191 }
192
193 private void printArrayProperty(StringBuffer sb, String prefix,Object array) {
194 int length = Array.getLength(array);
195 for (int i=0;i<length;i++) {
196 Object obj = Array.get(array,i);
197 printProperty(sb,prefix+"["+i+"]",obj);
198 }
199 }
200
201 }
202