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