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