1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.lang.builder;
19 
20 import java.lang.reflect.AccessibleObject;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 
27 import org.apache.commons.lang.ArrayUtils;
28 import org.apache.commons.lang.ClassUtils;
29 
30 /**
31  * <p>
32  * Assists in implementing {@link Object#toString()} methods using reflection.
33  * </p>
34  *
35  * <p>
36  * This class uses reflection to determine the fields to append. Because these fields are usually private, the class
37  * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to
38  * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are
39  * set up correctly.
40  * </p>
41  *
42  * <p>
43  * A typical invocation for this method would look like:
44  * </p>
45  *
46  * <pre>
47  * public String toString() {
48  *   return ReflectionToStringBuilder.toString(this);
49  * }</pre>
50  *
51  *
52  *
53  * <p>
54  * You can also use the builder to debug 3rd party objects:
55  * </p>
56  *
57  * <pre>
58  * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));</pre>
59  *
60  *
61  *
62  * <p>
63  * A subclass can control field output by overriding the methods:
64  * <ul>
65  * <li>{@link #accept(java.lang.reflect.Field)}</li>
66  * <li>{@link #getValue(java.lang.reflect.Field)}</li>
67  * </ul>
68  * </p>
69  * <p>
70  * For example, this method does <i>not</i> include the <code>password</code> field in the returned
71  * <code>String</code>:
72  * </p>
73  *
74  * <pre>
75  * public String toString() {
76  *     return (new ReflectionToStringBuilder(this) {
77  *         protected boolean accept(Field f) {
78  *             return super.accept(f) && !f.getName().equals("password");
79  *         }
80  *     }).toString();
81  * }</pre>
82  *
83  *
84  *
85  * <p>
86  * The exact format of the <code>toString</code> is determined by the {@link ToStringStyle} passed into the
87  * constructor.
88  * </p>
89  *
90  * @author Apache Software Foundation
91  * @author Gary Gregory
92  * @author Pete Gieser
93  * @since 2.0
94  * @version $Id: ReflectionToStringBuilder.java 905636 2010-02-02 14:03:32Z niallp $
95  */
96 public class ReflectionToStringBuilder extends ToStringBuilder {
97 
98     /**
99      * <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      */
toString(Object object)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      */
toString(Object object, ToStringStyle style)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      */
toString(Object object, ToStringStyle style, boolean outputTransients)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      */
toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics)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      */
toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics, Class reflectUpToClass)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      */
toString(Object object, ToStringStyle style, boolean outputTransients, Class reflectUpToClass)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      */
toStringExclude(Object object, final String excludeFieldName)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      */
toStringExclude(Object object, Collection excludeFieldNames)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      */
toNoNullStringArray(Collection collection)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      */
toNoNullStringArray(Object[] array)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      */
toStringExclude(Object object, String[] excludeFieldNames)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      */
ReflectionToStringBuilder(Object object)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      */
ReflectionToStringBuilder(Object object, ToStringStyle style)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      */
ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer)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      */
ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass, boolean outputTransients)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      */
ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass, boolean outputTransients, boolean outputStatics)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      */
accept(Field field)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      */
appendFieldsIn(Class clazz)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      */
getExcludeFieldNames()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      */
getUpToClass()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      */
getValue(Field field)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      */
isAppendStatics()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      */
isAppendTransients()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      */
reflectionAppendArray(Object array)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      */
setAppendStatics(boolean appendStatics)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      */
setAppendTransients(boolean appendTransients)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      */
setExcludeFieldNames(String[] excludeFieldNamesParam)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      */
setUpToClass(Class clazz)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      */
toString()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 }
774