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