    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}