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