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