/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
package org.apache.commons.lang3.builder; |
|
import java.lang.reflect.AccessibleObject; |
|
import java.lang.reflect.Field; |
|
import java.lang.reflect.Modifier; |
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.Collection; |
|
import java.util.Comparator; |
|
import java.util.List; |
|
import org.apache.commons.lang3.ArrayUtils; |
|
import org.apache.commons.lang3.ClassUtils; |
|
import org.apache.commons.lang3.Validate; |
|
/** |
|
* <p> |
|
* Assists in implementing {@link Object#toString()} methods using reflection. |
|
* </p> |
|
* <p> |
|
* This class uses reflection to determine the fields to append. Because these fields are usually private, the class |
|
* uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to |
|
* change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are |
|
* set up correctly. |
|
* </p> |
|
* <p> |
|
* Using reflection to access (private) fields circumvents any synchronization protection guarding access to these |
|
* fields. If a toString method cannot safely read a field, you should exclude it from the toString method, or use |
|
* synchronization consistent with the class' lock management around the invocation of the method. Take special care to |
|
* exclude non-thread-safe collection classes, because these classes may throw ConcurrentModificationException if |
|
* modified while the toString method is executing. |
|
* </p> |
|
* <p> |
|
* A typical invocation for this method would look like: |
|
* </p> |
|
* <pre> |
|
* public String toString() { |
|
* return ReflectionToStringBuilder.toString(this); |
|
* } |
|
* </pre> |
|
* <p> |
|
* You can also use the builder to debug 3rd party objects: |
|
* </p> |
|
* <pre> |
|
* System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject)); |
|
* </pre> |
|
* <p> |
|
* A subclass can control field output by overriding the methods: |
|
* </p> |
|
* <ul> |
|
* <li>{@link #accept(java.lang.reflect.Field)}</li> |
|
* <li>{@link #getValue(java.lang.reflect.Field)}</li> |
|
* </ul> |
|
* <p> |
|
* For example, this method does <i>not</i> include the {@code password} field in the returned {@code String}: |
|
* </p> |
|
* <pre> |
|
* public String toString() { |
|
* return (new ReflectionToStringBuilder(this) { |
|
* protected boolean accept(Field f) { |
|
* return super.accept(f) && !f.getName().equals("password"); |
|
* } |
|
* }).toString(); |
|
* } |
|
* </pre> |
|
* <p> |
|
* Alternatively the {@link ToStringExclude} annotation can be used to exclude fields from being incorporated in the |
|
* result. |
|
* </p> |
|
* <p> |
|
* It is also possible to use the {@link ToStringSummary} annotation to output the summary information instead of the |
|
* detailed information of a field. |
|
* </p> |
|
* <p> |
|
* The exact format of the {@code toString} is determined by the {@link ToStringStyle} passed into the constructor. |
|
* </p> |
|
* |
|
* <p> |
|
* <b>Note:</b> the default {@link ToStringStyle} will only do a "shallow" formatting, i.e. composed objects are not |
|
* further traversed. To get "deep" formatting, use an instance of {@link RecursiveToStringStyle}. |
|
* </p> |
|
* |
|
* @since 2.0 |
|
*/ |
|
public class ReflectionToStringBuilder extends ToStringBuilder { |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value using the default {@code ToStringStyle} through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* Transient members will be not be included, as they are likely derived. Static fields will not be included. |
|
* Superclass fields will be appended. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to be output |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
*/ |
|
public static String toString(final Object object) { |
|
return toString(object, null, false, false, null); |
|
} |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* Transient members will be not be included, as they are likely derived. Static fields will not be included. |
|
* Superclass fields will be appended. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default {@code ToStringStyle} is used. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to be output |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object or {@code ToStringStyle} is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
*/ |
|
public static String toString(final Object object, final ToStringStyle style) { |
|
return toString(object, style, false, false, null); |
|
} |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputTransients} is {@code true}, transient members will be output, otherwise they |
|
* are ignored, as they are likely derived fields, and not part of the value of the Object. |
|
* </p> |
|
* |
|
* <p> |
|
* Static fields will not be included. Superclass fields will be appended. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default {@code ToStringStyle} is used. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to be output |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
*/ |
|
public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients) { |
|
return toString(object, style, outputTransients, false, null); |
|
} |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they |
|
* are ignored, as they are likely derived fields, and not part of the value of the Object. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are |
|
* ignored. |
|
* </p> |
|
* |
|
* <p> |
|
* Static fields will not be included. Superclass fields will be appended. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default {@code ToStringStyle} is used. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to be output |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @param outputStatics |
|
* whether to include static fields |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
* @since 2.1 |
|
*/ |
|
public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients, final boolean outputStatics) { |
|
return toString(object, style, outputTransients, outputStatics, null); |
|
} |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they |
|
* are ignored, as they are likely derived fields, and not part of the value of the Object. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are |
|
* ignored. |
|
* </p> |
|
* |
|
* <p> |
|
* Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as |
|
* {@code java.lang.Object}. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default {@code ToStringStyle} is used. |
|
* </p> |
|
* |
|
* @param <T> |
|
* the type of the object |
|
* @param object |
|
* the Object to be output |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @param outputStatics |
|
* whether to include static fields |
|
* @param reflectUpToClass |
|
* the superclass to reflect up to (inclusive), may be {@code null} |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
* @since 2.1 |
|
*/ |
|
public static <T> String toString( |
|
final T object, final ToStringStyle style, final boolean outputTransients, |
|
final boolean outputStatics, final Class<? super T> reflectUpToClass) { |
|
return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics) |
|
.toString(); |
|
} |
|
/** |
|
* <p> |
|
* Builds a {@code toString} value through reflection. |
|
* </p> |
|
* |
|
* <p> |
|
* It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will |
|
* throw a security exception if run under a security manager, if the permissions are not set up correctly. It is |
|
* also not as efficient as testing explicitly. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they |
|
* are ignored, as they are likely derived fields, and not part of the value of the Object. |
|
* </p> |
|
* |
|
* <p> |
|
* If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are |
|
* ignored. |
|
* </p> |
|
* |
|
* <p> |
|
* Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as |
|
* {@code java.lang.Object}. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default {@code ToStringStyle} is used. |
|
* </p> |
|
* |
|
* @param <T> |
|
* the type of the object |
|
* @param object |
|
* the Object to be output |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @param outputStatics |
|
* whether to include static fields |
|
* @param excludeNullValues |
|
* whether to exclude fields whose values are null |
|
* @param reflectUpToClass |
|
* the superclass to reflect up to (inclusive), may be {@code null} |
|
* @return the String result |
|
* @throws IllegalArgumentException |
|
* if the Object is {@code null} |
|
* |
|
* @see ToStringExclude |
|
* @see ToStringSummary |
|
* @since 3.6 |
|
*/ |
|
public static <T> String toString( |
|
final T object, final ToStringStyle style, final boolean outputTransients, |
|
final boolean outputStatics, final boolean excludeNullValues, final Class<? super T> reflectUpToClass) { |
|
return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics, excludeNullValues) |
|
.toString(); |
|
} |
|
/** |
|
* Builds a String for a toString method excluding the given field names. |
|
* |
|
* @param object |
|
* The object to "toString". |
|
* @param excludeFieldNames |
|
* The field names to exclude. Null excludes nothing. |
|
* @return The toString value. |
|
*/ |
|
public static String toStringExclude(final Object object, final Collection<String> excludeFieldNames) { |
|
return toStringExclude(object, toNoNullStringArray(excludeFieldNames)); |
|
} |
|
/** |
|
* Converts the given Collection into an array of Strings. The returned array does not contain {@code null} |
|
* entries. Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} if an array element |
|
* is {@code null}. |
|
* |
|
* @param collection |
|
* The collection to convert |
|
* @return A new array of Strings. |
|
*/ |
|
static String[] toNoNullStringArray(final Collection<String> collection) { |
|
if (collection == null) { |
|
return ArrayUtils.EMPTY_STRING_ARRAY; |
|
} |
|
return toNoNullStringArray(collection.toArray()); |
|
} |
|
/** |
|
* Returns a new array of Strings without null elements. Internal method used to normalize exclude lists |
|
* (arrays and collections). Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} |
|
* if an array element is {@code null}. |
|
* |
|
* @param array |
|
* The array to check |
|
* @return The given array or a new array without null. |
|
*/ |
|
static String[] toNoNullStringArray(final Object[] array) { |
|
final List<String> list = new ArrayList<>(array.length); |
|
for (final Object e : array) { |
|
if (e != null) { |
|
list.add(e.toString()); |
|
} |
|
} |
|
return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); |
|
} |
|
/** |
|
* Builds a String for a toString method excluding the given field names. |
|
* |
|
* @param object |
|
* The object to "toString". |
|
* @param excludeFieldNames |
|
* The field names to exclude |
|
* @return The toString value. |
|
*/ |
|
public static String toStringExclude(final Object object, final String... excludeFieldNames) { |
|
return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString(); |
|
} |
|
private static Object checkNotNull(final Object obj) { |
|
return Validate.notNull(obj, "The Object passed in should not be null."); |
|
} |
|
/** |
|
* Whether or not to append static fields. |
|
*/ |
|
private boolean appendStatics = false; |
|
/** |
|
* Whether or not to append transient fields. |
|
*/ |
|
private boolean appendTransients = false; |
|
/** |
|
* Whether or not to append fields that are null. |
|
*/ |
|
private boolean excludeNullValues; |
|
/** |
|
* Which field names to exclude from output. Intended for fields like {@code "password"}. |
|
* |
|
* @since 3.0 this is protected instead of private |
|
*/ |
|
protected String[] excludeFieldNames; |
|
/** |
|
* The last super class to stop appending fields for. |
|
*/ |
|
private Class<?> upToClass = null; |
|
/** |
|
* <p> |
|
* Constructor. |
|
* </p> |
|
* |
|
* <p> |
|
* This constructor outputs using the default style set with {@code setDefaultStyle}. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to build a {@code toString} for, must not be {@code null} |
|
* @throws IllegalArgumentException |
|
* if the Object passed in is {@code null} |
|
*/ |
|
public ReflectionToStringBuilder(final Object object) { |
|
super(checkNotNull(object)); |
|
} |
|
/** |
|
* <p> |
|
* Constructor. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default style is used. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to build a {@code toString} for, must not be {@code null} |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @throws IllegalArgumentException |
|
* if the Object passed in is {@code null} |
|
*/ |
|
public ReflectionToStringBuilder(final Object object, final ToStringStyle style) { |
|
super(checkNotNull(object), style); |
|
} |
|
/** |
|
* <p> |
|
* Constructor. |
|
* </p> |
|
* |
|
* <p> |
|
* If the style is {@code null}, the default style is used. |
|
* </p> |
|
* |
|
* <p> |
|
* If the buffer is {@code null}, a new one is created. |
|
* </p> |
|
* |
|
* @param object |
|
* the Object to build a {@code toString} for |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param buffer |
|
* the {@code StringBuffer} to populate, may be {@code null} |
|
* @throws IllegalArgumentException |
|
* if the Object passed in is {@code null} |
|
*/ |
|
public ReflectionToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) { |
|
super(checkNotNull(object), style, buffer); |
|
} |
|
/** |
|
* Constructor. |
|
* |
|
* @param <T> |
|
* the type of the object |
|
* @param object |
|
* the Object to build a {@code toString} for |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param buffer |
|
* the {@code StringBuffer} to populate, may be {@code null} |
|
* @param reflectUpToClass |
|
* the superclass to reflect up to (inclusive), may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @param outputStatics |
|
* whether to include static fields |
|
* @since 2.1 |
|
*/ |
|
public <T> ReflectionToStringBuilder( |
|
final T object, final ToStringStyle style, final StringBuffer buffer, |
|
final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics) { |
|
super(checkNotNull(object), style, buffer); |
|
this.setUpToClass(reflectUpToClass); |
|
this.setAppendTransients(outputTransients); |
|
this.setAppendStatics(outputStatics); |
|
} |
|
/** |
|
* Constructor. |
|
* |
|
* @param <T> |
|
* the type of the object |
|
* @param object |
|
* the Object to build a {@code toString} for |
|
* @param style |
|
* the style of the {@code toString} to create, may be {@code null} |
|
* @param buffer |
|
* the {@code StringBuffer} to populate, may be {@code null} |
|
* @param reflectUpToClass |
|
* the superclass to reflect up to (inclusive), may be {@code null} |
|
* @param outputTransients |
|
* whether to include transient fields |
|
* @param outputStatics |
|
* whether to include static fields |
|
* @param excludeNullValues |
|
* whether to exclude fields who value is null |
|
* @since 3.6 |
|
*/ |
|
public <T> ReflectionToStringBuilder( |
|
final T object, final ToStringStyle style, final StringBuffer buffer, |
|
final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics, |
|
final boolean excludeNullValues) { |
|
super(checkNotNull(object), style, buffer); |
|
this.setUpToClass(reflectUpToClass); |
|
this.setAppendTransients(outputTransients); |
|
this.setAppendStatics(outputStatics); |
|
this.setExcludeNullValues(excludeNullValues); |
|
} |
|
/** |
|
* Returns whether or not to append the given {@code Field}. |
|
* <ul> |
|
* <li>Transient fields are appended only if {@link #isAppendTransients()} returns {@code true}. |
|
* <li>Static fields are appended only if {@link #isAppendStatics()} returns {@code true}. |
|
* <li>Inner class fields are not appended.</li> |
|
* </ul> |
|
* |
|
* @param field |
|
* The Field to test. |
|
* @return Whether or not to append the given {@code Field}. |
|
*/ |
|
protected boolean accept(final Field field) { |
|
if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) { |
|
// Reject field from inner class. |
|
return false; |
|
} |
|
if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) { |
|
// Reject transient fields. |
|
return false; |
|
} |
|
if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) { |
|
// Reject static fields. |
|
return false; |
|
} |
|
if (this.excludeFieldNames != null |
|
&& Arrays.binarySearch(this.excludeFieldNames, field.getName()) >= 0) { |
|
// Reject fields from the getExcludeFieldNames list. |
|
return false; |
|
} |
|
return !field.isAnnotationPresent(ToStringExclude.class); |
|
} |
|
/** |
|
* <p> |
|
* Appends the fields and values defined by the given object of the given Class. |
|
* </p> |
|
* |
|
* <p> |
|
* If a cycle is detected as an object is "toString()'ed", such an object is rendered as if |
|
* {@code Object.toString()} had been called and not implemented by the object. |
|
* </p> |
|
* |
|
* @param clazz |
|
* The class of object parameter |
|
*/ |
|
protected void appendFieldsIn(final Class<?> clazz) { |
|
if (clazz.isArray()) { |
|
this.reflectionAppendArray(this.getObject()); |
|
return; |
|
} |
|
// The elements in the returned array are not sorted and are not in any particular order. |
|
final Field[] fields = clazz.getDeclaredFields(); |
|
Arrays.sort(fields, Comparator.comparing(Field::getName)); |
|
AccessibleObject.setAccessible(fields, true); |
|
for (final Field field : fields) { |
|
final String fieldName = field.getName(); |
|
if (this.accept(field)) { |
|
try { |
|
// Warning: Field.get(Object) creates wrappers objects |
|
// for primitive types. |
|
final Object fieldValue = this.getValue(field); |
|
if (!excludeNullValues || fieldValue != null) { |
|
this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class)); |
|
} |
|
} catch (final IllegalAccessException ex) { |
|
//this can't happen. Would get a Security exception |
|
// instead |
|
//throw a runtime exception in case the impossible |
|
// happens. |
|
throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage()); |
|
} |
|
} |
|
} |
|
} |
|
/** |
|
* @return Returns the excludeFieldNames. |
|
*/ |
|
public String[] getExcludeFieldNames() { |
|
return this.excludeFieldNames.clone(); |
|
} |
|
/** |
|
* <p> |
|
* Gets the last super class to stop appending fields for. |
|
* </p> |
|
* |
|
* @return The last super class to stop appending fields for. |
|
*/ |
|
public Class<?> getUpToClass() { |
|
return this.upToClass; |
|
} |
|
/** |
|
* <p> |
|
* Calls {@code java.lang.reflect.Field.get(Object)}. |
|
* </p> |
|
* |
|
* @param field |
|
* The Field to query. |
|
* @return The Object from the given Field. |
|
* |
|
* @throws IllegalArgumentException |
|
* see {@link java.lang.reflect.Field#get(Object)} |
|
* @throws IllegalAccessException |
|
* see {@link java.lang.reflect.Field#get(Object)} |
|
* |
|
* @see java.lang.reflect.Field#get(Object) |
|
*/ |
|
protected Object getValue(final Field field) throws IllegalAccessException { |
|
return field.get(this.getObject()); |
|
} |
|
/** |
|
* <p> |
|
* Gets whether or not to append static fields. |
|
* </p> |
|
* |
|
* @return Whether or not to append static fields. |
|
* @since 2.1 |
|
*/ |
|
public boolean isAppendStatics() { |
|
return this.appendStatics; |
|
} |
|
/** |
|
* <p> |
|
* Gets whether or not to append transient fields. |
|
* </p> |
|
* |
|
* @return Whether or not to append transient fields. |
|
*/ |
|
public boolean isAppendTransients() { |
|
return this.appendTransients; |
|
} |
|
/** |
|
* <p> |
|
* Gets whether or not to append fields whose values are null. |
|
* </p> |
|
* |
|
* @return Whether or not to append fields whose values are null. |
|
* @since 3.6 |
|
*/ |
|
public boolean isExcludeNullValues() { |
|
return this.excludeNullValues; |
|
} |
|
/** |
|
* <p> |
|
* Append to the {@code toString} an {@code Object} array. |
|
* </p> |
|
* |
|
* @param array |
|
* the array to add to the {@code toString} |
|
* @return this |
|
*/ |
|
public ReflectionToStringBuilder reflectionAppendArray(final Object array) { |
|
this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array); |
|
return this; |
|
} |
|
/** |
|
* <p> |
|
* Sets whether or not to append static fields. |
|
* </p> |
|
* |
|
* @param appendStatics |
|
* Whether or not to append static fields. |
|
* @since 2.1 |
|
*/ |
|
public void setAppendStatics(final boolean appendStatics) { |
|
this.appendStatics = appendStatics; |
|
} |
|
/** |
|
* <p> |
|
* Sets whether or not to append transient fields. |
|
* </p> |
|
* |
|
* @param appendTransients |
|
* Whether or not to append transient fields. |
|
*/ |
|
public void setAppendTransients(final boolean appendTransients) { |
|
this.appendTransients = appendTransients; |
|
} |
|
/** |
|
* <p> |
|
* Sets whether or not to append fields whose values are null. |
|
* </p> |
|
* |
|
* @param excludeNullValues |
|
* Whether or not to append fields whose values are null. |
|
* @since 3.6 |
|
*/ |
|
public void setExcludeNullValues(final boolean excludeNullValues) { |
|
this.excludeNullValues = excludeNullValues; |
|
} |
|
/** |
|
* Sets the field names to exclude. |
|
* |
|
* @param excludeFieldNamesParam |
|
* The excludeFieldNames to excluding from toString or {@code null}. |
|
* @return {@code this} |
|
*/ |
|
public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) { |
|
if (excludeFieldNamesParam == null) { |
|
this.excludeFieldNames = null; |
|
} else { |
|
//clone and remove nulls |
|
this.excludeFieldNames = toNoNullStringArray(excludeFieldNamesParam); |
|
Arrays.sort(this.excludeFieldNames); |
|
} |
|
return this; |
|
} |
|
/** |
|
* <p> |
|
* Sets the last super class to stop appending fields for. |
|
* </p> |
|
* |
|
* @param clazz |
|
* The last super class to stop appending fields for. |
|
*/ |
|
public void setUpToClass(final Class<?> clazz) { |
|
if (clazz != null) { |
|
final Object object = getObject(); |
|
if (object != null && !clazz.isInstance(object)) { |
|
throw new IllegalArgumentException("Specified class is not a superclass of the object"); |
|
} |
|
} |
|
this.upToClass = clazz; |
|
} |
|
/** |
|
* <p> |
|
* Gets the String built by this builder. |
|
* </p> |
|
* |
|
* @return the built string |
|
*/ |
|
@Override |
|
public String toString() { |
|
if (this.getObject() == null) { |
|
return this.getStyle().getNullText(); |
|
} |
|
Class<?> clazz = this.getObject().getClass(); |
|
this.appendFieldsIn(clazz); |
|
while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) { |
|
clazz = clazz.getSuperclass(); |
|
this.appendFieldsIn(clazz); |
|
} |
|
return super.toString(); |
|
} |
|
} |