001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.lang.builder;
019    
020    import java.lang.reflect.AccessibleObject;
021    import java.lang.reflect.Field;
022    import java.lang.reflect.Modifier;
023    import java.util.ArrayList;
024    import java.util.Arrays;
025    import java.util.Collection;
026    
027    import org.apache.commons.lang.ArrayUtils;
028    import org.apache.commons.lang.ClassUtils;
029    
030    /**
031     * <p>
032     * Assists in implementing {@link Object#toString()} methods using reflection.
033     * </p>
034     * 
035     * <p>
036     * This class uses reflection to determine the fields to append. Because these fields are usually private, the class
037     * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to
038     * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are
039     * set up correctly.
040     * </p>
041     * 
042     * <p>
043     * A typical invocation for this method would look like:
044     * </p>
045     * 
046     * <pre>
047     * public String toString() {
048     *   return ReflectionToStringBuilder.toString(this);
049     * }</pre>
050     * 
051     * 
052     * 
053     * <p>
054     * You can also use the builder to debug 3rd party objects:
055     * </p>
056     * 
057     * <pre>
058     * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));</pre>
059     * 
060     * 
061     * 
062     * <p>
063     * A subclass can control field output by overriding the methods:
064     * <ul>
065     * <li>{@link #accept(java.lang.reflect.Field)}</li>
066     * <li>{@link #getValue(java.lang.reflect.Field)}</li>
067     * </ul>
068     * </p>
069     * <p>
070     * For example, this method does <i>not</i> include the <code>password</code> field in the returned
071     * <code>String</code>:
072     * </p>
073     * 
074     * <pre>
075     * public String toString() {
076     *     return (new ReflectionToStringBuilder(this) {
077     *         protected boolean accept(Field f) {
078     *             return super.accept(f) && !f.getName().equals("password");
079     *         }
080     *     }).toString();
081     * }</pre>
082     * 
083     * 
084     * 
085     * <p>
086     * The exact format of the <code>toString</code> is determined by the {@link ToStringStyle} passed into the
087     * constructor.
088     * </p>
089     * 
090     * @author Apache Software Foundation
091     * @author Gary Gregory
092     * @author Pete Gieser
093     * @since 2.0
094     * @version $Id: ReflectionToStringBuilder.java 905636 2010-02-02 14:03:32Z niallp $
095     */
096    public class ReflectionToStringBuilder extends ToStringBuilder {
097    
098        /**
099         * <p>
100         * Builds a <code>toString</code> value using the default <code>ToStringStyle</code> through reflection.
101         * </p>
102         * 
103         * <p>
104         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
105         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
106         * also not as efficient as testing explicitly.
107         * </p>
108         * 
109         * <p>
110         * Transient members will be not be included, as they are likely derived. Static fields will not be included.
111         * Superclass fields will be appended.
112         * </p>
113         * 
114         * @param object
115         *            the Object to be output
116         * @return the String result
117         * @throws IllegalArgumentException
118         *             if the Object is <code>null</code>
119         */
120        public static String toString(Object object) {
121            return toString(object, null, false, false, null);
122        }
123    
124        /**
125         * <p>
126         * Builds a <code>toString</code> value through reflection.
127         * </p>
128         * 
129         * <p>
130         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
131         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
132         * also not as efficient as testing explicitly.
133         * </p>
134         * 
135         * <p>
136         * Transient members will be not be included, as they are likely derived. Static fields will not be included.
137         * Superclass fields will be appended.
138         * </p>
139         * 
140         * <p>
141         * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
142         * </p>
143         * 
144         * @param object
145         *            the Object to be output
146         * @param style
147         *            the style of the <code>toString</code> to create, may be <code>null</code>
148         * @return the String result
149         * @throws IllegalArgumentException
150         *             if the Object or <code>ToStringStyle</code> is <code>null</code>
151         */
152        public static String toString(Object object, ToStringStyle style) {
153            return toString(object, style, false, false, null);
154        }
155    
156        /**
157         * <p>
158         * Builds a <code>toString</code> value through reflection.
159         * </p>
160         * 
161         * <p>
162         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
163         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
164         * also not as efficient as testing explicitly.
165         * </p>
166         * 
167         * <p>
168         * If the <code>outputTransients</code> is <code>true</code>, transient members will be output, otherwise they
169         * are ignored, as they are likely derived fields, and not part of the value of the Object.
170         * </p>
171         * 
172         * <p>
173         * Static fields will not be included. Superclass fields will be appended.
174         * </p>
175         * 
176         * <p>
177         * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
178         * </p>
179         * 
180         * @param object
181         *            the Object to be output
182         * @param style
183         *            the style of the <code>toString</code> to create, may be <code>null</code>
184         * @param outputTransients
185         *            whether to include transient fields
186         * @return the String result
187         * @throws IllegalArgumentException
188         *             if the Object is <code>null</code>
189         */
190        public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
191            return toString(object, style, outputTransients, false, null);
192        }
193    
194        /**
195         * <p>
196         * Builds a <code>toString</code> value through reflection.
197         * </p>
198         * 
199         * <p>
200         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
201         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
202         * also not as efficient as testing explicitly.
203         * </p>
204         * 
205         * <p>
206         * If the <code>outputTransients</code> is <code>true</code>, transient fields will be output, otherwise they
207         * are ignored, as they are likely derived fields, and not part of the value of the Object.
208         * </p>
209         * 
210         * <p>
211         * If the <code>outputStatics</code> is <code>true</code>, static fields will be output, otherwise they are
212         * ignored.
213         * </p>
214         * 
215         * <p>
216         * Static fields will not be included. Superclass fields will be appended.
217         * </p>
218         * 
219         * <p>
220         * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
221         * </p>
222         * 
223         * @param object
224         *            the Object to be output
225         * @param style
226         *            the style of the <code>toString</code> to create, may be <code>null</code>
227         * @param outputTransients
228         *            whether to include transient fields
229         * @param outputStatics
230         *            whether to include transient fields
231         * @return the String result
232         * @throws IllegalArgumentException
233         *             if the Object is <code>null</code>
234         * @since 2.1
235         */
236        public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics) {
237            return toString(object, style, outputTransients, outputStatics, null);
238        }
239    
240        /**
241         * <p>
242         * Builds a <code>toString</code> value through reflection.
243         * </p>
244         * 
245         * <p>
246         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
247         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
248         * also not as efficient as testing explicitly.
249         * </p>
250         * 
251         * <p>
252         * If the <code>outputTransients</code> is <code>true</code>, transient fields will be output, otherwise they
253         * are ignored, as they are likely derived fields, and not part of the value of the Object.
254         * </p>
255         * 
256         * <p>
257         * If the <code>outputStatics</code> is <code>true</code>, static fields will be output, otherwise they are
258         * ignored.
259         * </p>
260         * 
261         * <p>
262         * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
263         * <code>java.lang.Object</code>.
264         * </p>
265         * 
266         * <p>
267         * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
268         * </p>
269         * 
270         * @param object
271         *            the Object to be output
272         * @param style
273         *            the style of the <code>toString</code> to create, may be <code>null</code>
274         * @param outputTransients
275         *            whether to include transient fields
276         * @param outputStatics
277         *            whether to include static fields
278         * @param reflectUpToClass
279         *            the superclass to reflect up to (inclusive), may be <code>null</code>
280         * @return the String result
281         * @throws IllegalArgumentException
282         *             if the Object is <code>null</code>
283         * @since 2.1
284         */
285        public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics,
286                Class reflectUpToClass) {
287            return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
288                    .toString();
289        }
290    
291        /**
292         * <p>
293         * Builds a <code>toString</code> value through reflection.
294         * </p>
295         * 
296         * <p>
297         * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
298         * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
299         * also not as efficient as testing explicitly.
300         * </p>
301         * 
302         * <p>
303         * If the <code>outputTransients</code> is <code>true</code>, transient members will be output, otherwise they
304         * are ignored, as they are likely derived fields, and not part of the value of the Object.
305         * </p>
306         * 
307         * <p>
308         * Static fields will not be included. Superclass fields will be appended up to and including the specified
309         * superclass. A null superclass is treated as <code>java.lang.Object</code>.
310         * </p>
311         * 
312         * <p>
313         * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
314         * </p>
315         * 
316         * @deprecated Use {@link #toString(Object,ToStringStyle,boolean,boolean,Class)}
317         * 
318         * @param object
319         *            the Object to be output
320         * @param style
321         *            the style of the <code>toString</code> to create, may be <code>null</code>
322         * @param outputTransients
323         *            whether to include transient fields
324         * @param reflectUpToClass
325         *            the superclass to reflect up to (inclusive), may be <code>null</code>
326         * @return the String result
327         * @throws IllegalArgumentException
328         *             if the Object is <code>null</code>
329         * @since 2.0
330         */
331        public static String toString(Object object, ToStringStyle style, 
332                                      boolean outputTransients, Class reflectUpToClass) 
333        {
334            return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
335        }
336    
337        /**
338         * Builds a String for a toString method excluding the given field name.
339         * 
340         * @param object
341         *            The object to "toString".
342         * @param excludeFieldName
343         *            The field name to exclude
344         * @return The toString value.
345         */
346        public static String toStringExclude(Object object, final String excludeFieldName) {
347            return toStringExclude(object, new String[]{excludeFieldName});
348        }
349    
350        /**
351         * Builds a String for a toString method excluding the given field names.
352         * 
353         * @param object
354         *            The object to "toString".
355         * @param excludeFieldNames
356         *            The field names to exclude. Null excludes nothing.
357         * @return The toString value.
358         */
359        public static String toStringExclude(Object object, Collection /*String*/ excludeFieldNames) {
360            return toStringExclude(object, toNoNullStringArray(excludeFieldNames));
361        }
362    
363        /**
364         * Converts the given Collection into an array of Strings. The returned array does not contain <code>null</code>
365         * entries. Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} if an array element 
366         * is <code>null</code>.
367         * 
368         * @param collection
369         *            The collection to convert
370         * @return A new array of Strings.
371         */
372        static String[] toNoNullStringArray(Collection collection) {
373            if (collection == null) {
374                return ArrayUtils.EMPTY_STRING_ARRAY;
375            }
376            return toNoNullStringArray(collection.toArray());
377        }
378    
379        /**
380         * Returns a new array of Strings without null elements. Internal method used to normalize exclude lists
381         * (arrays and collections). Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} 
382         * if an array element is <code>null</code>.
383         * 
384         * @param array
385         *            The array to check
386         * @return The given array or a new array without null.
387         */
388        static String[] toNoNullStringArray(Object[] array) {
389            ArrayList list = new ArrayList(array.length);
390            for (int i = 0; i < array.length; i++) {
391                Object e = array[i];
392                if (e != null) {
393                    list.add(e.toString());
394                }
395            }
396            return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
397        }
398        
399    
400        /**
401         * Builds a String for a toString method excluding the given field names.
402         * 
403         * @param object
404         *            The object to "toString".
405         * @param excludeFieldNames
406         *            The field names to exclude
407         * @return The toString value.
408         */
409        public static String toStringExclude(Object object, String[] excludeFieldNames) {
410            return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString();
411        }
412    
413        /**
414         * Whether or not to append static fields.
415         */
416        private boolean appendStatics = false;
417    
418        /**
419         * Whether or not to append transient fields.
420         */
421        private boolean appendTransients = false;
422    
423        /**
424         * Which field names to exclude from output. Intended for fields like <code>"password"</code>.
425         */
426        private String[] excludeFieldNames;
427    
428        /**
429         * The last super class to stop appending fields for.
430         */
431        private Class upToClass = null;
432    
433        /**
434         * <p>
435         * Constructor.
436         * </p>
437         * 
438         * <p>
439         * This constructor outputs using the default style set with <code>setDefaultStyle</code>.
440         * </p>
441         * 
442         * @param object
443         *            the Object to build a <code>toString</code> for, must not be <code>null</code>
444         * @throws IllegalArgumentException
445         *             if the Object passed in is <code>null</code>
446         */
447        public ReflectionToStringBuilder(Object object) {
448            super(object);
449        }
450    
451        /**
452         * <p>
453         * Constructor.
454         * </p>
455         * 
456         * <p>
457         * If the style is <code>null</code>, the default style is used.
458         * </p>
459         * 
460         * @param object
461         *            the Object to build a <code>toString</code> for, must not be <code>null</code>
462         * @param style
463         *            the style of the <code>toString</code> to create, may be <code>null</code>
464         * @throws IllegalArgumentException
465         *             if the Object passed in is <code>null</code>
466         */
467        public ReflectionToStringBuilder(Object object, ToStringStyle style) {
468            super(object, style);
469        }
470    
471        /**
472         * <p>
473         * Constructor.
474         * </p>
475         * 
476         * <p>
477         * If the style is <code>null</code>, the default style is used.
478         * </p>
479         * 
480         * <p>
481         * If the buffer is <code>null</code>, a new one is created.
482         * </p>
483         * 
484         * @param object
485         *            the Object to build a <code>toString</code> for
486         * @param style
487         *            the style of the <code>toString</code> to create, may be <code>null</code>
488         * @param buffer
489         *            the <code>StringBuffer</code> to populate, may be <code>null</code>
490         * @throws IllegalArgumentException
491         *             if the Object passed in is <code>null</code>
492         */
493        public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
494            super(object, style, buffer);
495        }
496    
497        /**
498         * Constructor.
499         * 
500         * @deprecated Use {@link #ReflectionToStringBuilder(Object,ToStringStyle,StringBuffer,Class,boolean,boolean)}.
501         * 
502         * @param object
503         *            the Object to build a <code>toString</code> for
504         * @param style
505         *            the style of the <code>toString</code> to create, may be <code>null</code>
506         * @param buffer
507         *            the <code>StringBuffer</code> to populate, may be <code>null</code>
508         * @param reflectUpToClass
509         *            the superclass to reflect up to (inclusive), may be <code>null</code>
510         * @param outputTransients
511         *            whether to include transient fields
512         */
513        public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
514                boolean outputTransients) {
515            super(object, style, buffer);
516            this.setUpToClass(reflectUpToClass);
517            this.setAppendTransients(outputTransients);
518        }
519    
520        /**
521         * Constructor.
522         * 
523         * @param object
524         *            the Object to build a <code>toString</code> for
525         * @param style
526         *            the style of the <code>toString</code> to create, may be <code>null</code>
527         * @param buffer
528         *            the <code>StringBuffer</code> to populate, may be <code>null</code>
529         * @param reflectUpToClass
530         *            the superclass to reflect up to (inclusive), may be <code>null</code>
531         * @param outputTransients
532         *            whether to include transient fields
533         * @param outputStatics
534         *            whether to include static fields
535         * @since 2.1
536         */
537        public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
538                boolean outputTransients, boolean outputStatics) {
539            super(object, style, buffer);
540            this.setUpToClass(reflectUpToClass);
541            this.setAppendTransients(outputTransients);
542            this.setAppendStatics(outputStatics);
543        }
544    
545        /**
546         * Returns whether or not to append the given <code>Field</code>.
547         * <ul>
548         * <li>Transient fields are appended only if {@link #isAppendTransients()} returns <code>true</code>.
549         * <li>Static fields are appended only if {@link #isAppendStatics()} returns <code>true</code>.
550         * <li>Inner class fields are not appened.</li>
551         * </ul>
552         * 
553         * @param field
554         *            The Field to test.
555         * @return Whether or not to append the given <code>Field</code>.
556         */
557        protected boolean accept(Field field) {
558            if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) {
559                // Reject field from inner class.
560                return false;
561            }
562            if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
563                // Reject transient fields.
564                return false;
565            }
566            if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
567                // Reject static fields.
568                return false;
569            }
570            if (this.getExcludeFieldNames() != null
571                && Arrays.binarySearch(this.getExcludeFieldNames(), field.getName()) >= 0) {
572                // Reject fields from the getExcludeFieldNames list.
573                return false;
574            }
575            return true;
576        }
577    
578        /**
579         * <p>
580         * Appends the fields and values defined by the given object of the given Class.
581         * </p>
582         * 
583         * <p>
584         * If a cycle is detected as an object is &quot;toString()'ed&quot;, such an object is rendered as if
585         * <code>Object.toString()</code> had been called and not implemented by the object.
586         * </p>
587         * 
588         * @param clazz
589         *            The class of object parameter
590         */
591        protected void appendFieldsIn(Class clazz) {
592            if (clazz.isArray()) {
593                this.reflectionAppendArray(this.getObject());
594                return;
595            }
596            Field[] fields = clazz.getDeclaredFields();
597            AccessibleObject.setAccessible(fields, true);
598            for (int i = 0; i < fields.length; i++) {
599                Field field = fields[i];
600                String fieldName = field.getName();
601                if (this.accept(field)) {
602                    try {
603                        // Warning: Field.get(Object) creates wrappers objects
604                        // for primitive types.
605                        Object fieldValue = this.getValue(field);
606                        this.append(fieldName, fieldValue);
607                    } catch (IllegalAccessException ex) {
608                        //this can't happen. Would get a Security exception
609                        // instead
610                        //throw a runtime exception in case the impossible
611                        // happens.
612                        throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
613                    }
614                }
615            }
616        }
617    
618        /**
619         * @return Returns the excludeFieldNames.
620         */
621        public String[] getExcludeFieldNames() {
622            return this.excludeFieldNames;
623        }
624    
625        /**
626         * <p>
627         * Gets the last super class to stop appending fields for.
628         * </p>
629         * 
630         * @return The last super class to stop appending fields for.
631         */
632        public Class getUpToClass() {
633            return this.upToClass;
634        }
635    
636        /**
637         * <p>
638         * Calls <code>java.lang.reflect.Field.get(Object)</code>.
639         * </p>
640         * 
641         * @param field
642         *            The Field to query.
643         * @return The Object from the given Field.
644         * 
645         * @throws IllegalArgumentException
646         *             see {@link java.lang.reflect.Field#get(Object)}
647         * @throws IllegalAccessException
648         *             see {@link java.lang.reflect.Field#get(Object)}
649         * 
650         * @see java.lang.reflect.Field#get(Object)
651         */
652        protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
653            return field.get(this.getObject());
654        }
655    
656        /**
657         * <p>
658         * Gets whether or not to append static fields.
659         * </p>
660         * 
661         * @return Whether or not to append static fields.
662         * @since 2.1
663         */
664        public boolean isAppendStatics() {
665            return this.appendStatics;
666        }
667    
668        /**
669         * <p>
670         * Gets whether or not to append transient fields.
671         * </p>
672         * 
673         * @return Whether or not to append transient fields.
674         */
675        public boolean isAppendTransients() {
676            return this.appendTransients;
677        }
678    
679        /**
680         * <p>
681         * Append to the <code>toString</code> an <code>Object</code> array.
682         * </p>
683         * 
684         * @param array
685         *            the array to add to the <code>toString</code>
686         * @return this
687         */
688        public ToStringBuilder reflectionAppendArray(Object array) {
689            this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
690            return this;
691        }
692    
693        /**
694         * <p>
695         * Sets whether or not to append static fields.
696         * </p>
697         * 
698         * @param appendStatics
699         *            Whether or not to append static fields.
700         * @since 2.1
701         */
702        public void setAppendStatics(boolean appendStatics) {
703            this.appendStatics = appendStatics;
704        }
705    
706        /**
707         * <p>
708         * Sets whether or not to append transient fields.
709         * </p>
710         * 
711         * @param appendTransients
712         *            Whether or not to append transient fields.
713         */
714        public void setAppendTransients(boolean appendTransients) {
715            this.appendTransients = appendTransients;
716        }
717    
718        /**
719         * Sets the field names to exclude.
720         * 
721         * @param excludeFieldNamesParam
722         *            The excludeFieldNames to excluding from toString or <code>null</code>.
723         * @return <code>this</code>
724         */
725        public ReflectionToStringBuilder setExcludeFieldNames(String[] excludeFieldNamesParam) {
726            if (excludeFieldNamesParam == null) {
727                this.excludeFieldNames = null;
728            } else {
729                this.excludeFieldNames = toNoNullStringArray(excludeFieldNamesParam);
730                Arrays.sort(this.excludeFieldNames);
731            }
732            return this;
733        }
734    
735        /**
736         * <p>
737         * Sets the last super class to stop appending fields for.
738         * </p>
739         * 
740         * @param clazz
741         *            The last super class to stop appending fields for.
742         */
743        public void setUpToClass(Class clazz) {
744            if (clazz != null) {
745                Object object = getObject();
746                if (object != null && clazz.isInstance(object) == false) {
747                    throw new IllegalArgumentException("Specified class is not a superclass of the object");
748                }
749            }
750            this.upToClass = clazz;
751        }
752    
753        /**
754         * <p>
755         * Gets the String built by this builder.
756         * </p>
757         * 
758         * @return the built string
759         */
760        public String toString() {
761            if (this.getObject() == null) {
762                return this.getStyle().getNullText();
763            }
764            Class clazz = this.getObject().getClass();
765            this.appendFieldsIn(clazz);
766            while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
767                clazz = clazz.getSuperclass();
768                this.appendFieldsIn(clazz);
769            }
770            return super.toString();
771        }
772    
773    }