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