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