View Javadoc

1   /*
2    * Copyright 2004 Sun Microsystems, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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 &&                             // ensure it has a getter method
113                         pReadMethod.getDeclaringClass()!=Object.class && // filter Object.class getter methods
114                         pReadMethod.getParameterTypes().length==0) {     // filter getter methods that take parameters
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