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