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 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 &&                             // ensure it has a getter method
117                         pReadMethod.getDeclaringClass()!=Object.class && // filter Object.class getter methods
118                         pReadMethod.getParameterTypes().length==0) {     // filter getter methods that take parameters
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