1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.lang3.builder;
19
20 import java.lang.reflect.AccessibleObject;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Comparator;
26 import java.util.Objects;
27
28 import org.apache.commons.lang3.ArraySorter;
29 import org.apache.commons.lang3.ArrayUtils;
30 import org.apache.commons.lang3.ClassUtils;
31 import org.apache.commons.lang3.stream.Streams;
32
33 /**
34 * Assists in implementing {@link Object#toString()} methods using reflection.
35 *
36 * <p>
37 * This class uses reflection to determine the fields to append. Because these fields are usually private, the class
38 * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to
39 * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are
40 * set up correctly.
41 * </p>
42 * <p>
43 * Using reflection to access (private) fields circumvents any synchronization protection guarding access to these
44 * fields. If a toString method cannot safely read a field, you should exclude it from the toString method, or use
45 * synchronization consistent with the class' lock management around the invocation of the method. Take special care to
46 * exclude non-thread-safe collection classes, because these classes may throw ConcurrentModificationException if
47 * modified while the toString method is executing.
48 * </p>
49 * <p>
50 * A typical invocation for this method would look like:
51 * </p>
52 * <pre>
53 * public String toString() {
54 * return ReflectionToStringBuilder.toString(this);
55 * }
56 * </pre>
57 * <p>
58 * You can also use the builder to debug 3rd party objects:
59 * </p>
60 * <pre>
61 * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));
62 * </pre>
63 * <p>
64 * A subclass can control field output by overriding the methods:
65 * </p>
66 * <ul>
67 * <li>{@link #accept(java.lang.reflect.Field)}</li>
68 * <li>{@link #getValue(java.lang.reflect.Field)}</li>
69 * </ul>
70 * <p>
71 * For example, this method does <em>not</em> include the {@code password} field in the returned {@link String}:
72 * </p>
73 * <pre>
74 * public String toString() {
75 * return (new ReflectionToStringBuilder(this) {
76 * protected boolean accept(Field f) {
77 * return super.accept(f) && !f.getName().equals("password");
78 * }
79 * }).toString();
80 * }
81 * </pre>
82 * <p>
83 * Alternatively the {@link ToStringExclude} annotation can be used to exclude fields from being incorporated in the
84 * result.
85 * </p>
86 * <p>
87 * It is also possible to use the {@link ToStringSummary} annotation to output the summary information instead of the
88 * detailed information of a field.
89 * </p>
90 * <p>
91 * The exact format of the {@code toString} is determined by the {@link ToStringStyle} passed into the constructor.
92 * </p>
93 *
94 * <p>
95 * <strong>Note:</strong> the default {@link ToStringStyle} will only do a "shallow" formatting, i.e. composed objects are not
96 * further traversed. To get "deep" formatting, use an instance of {@link RecursiveToStringStyle}.
97 * </p>
98 *
99 * @since 2.0
100 */
101 public class ReflectionToStringBuilder extends ToStringBuilder {
102
103 /**
104 * Converts the given Collection into an array of Strings. The returned array does not contain {@code null}
105 * entries. Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} if an array element
106 * is {@code null}.
107 *
108 * @param collection
109 * The collection to convert
110 * @return A new array of Strings.
111 */
112 static String[] toNoNullStringArray(final Collection<String> collection) {
113 if (collection == null) {
114 return ArrayUtils.EMPTY_STRING_ARRAY;
115 }
116 return toNoNullStringArray(collection.toArray());
117 }
118
119 /**
120 * Returns a new array of Strings without null elements. Internal method used to normalize exclude lists
121 * (arrays and collections). Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException}
122 * if an array element is {@code null}.
123 *
124 * @param array
125 * The array to check
126 * @return The given array or a new array without null.
127 */
128 static String[] toNoNullStringArray(final Object[] array) {
129 return Streams.nonNull(array).map(Objects::toString).toArray(String[]::new);
130 }
131
132 /**
133 * Builds a {@code toString} value using the default {@link ToStringStyle} through reflection.
134 *
135 * <p>
136 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
137 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
138 * also not as efficient as testing explicitly.
139 * </p>
140 *
141 * <p>
142 * Transient members will be not be included, as they are likely derived. Static fields will not be included.
143 * Superclass fields will be appended.
144 * </p>
145 *
146 * @param object
147 * the Object to be output
148 * @return the String result
149 * @throws IllegalArgumentException
150 * if the Object is {@code null}
151 *
152 * @see ToStringExclude
153 * @see ToStringSummary
154 */
155 public static String toString(final Object object) {
156 return toString(object, null, false, false, null);
157 }
158
159 /**
160 * Builds a {@code toString} value through reflection.
161 *
162 * <p>
163 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
164 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
165 * also not as efficient as testing explicitly.
166 * </p>
167 *
168 * <p>
169 * Transient members will be not be included, as they are likely derived. Static fields will not be included.
170 * Superclass fields will be appended.
171 * </p>
172 *
173 * <p>
174 * If the style is {@code null}, the default {@link ToStringStyle} is used.
175 * </p>
176 *
177 * @param object
178 * the Object to be output
179 * @param style
180 * the style of the {@code toString} to create, may be {@code null}
181 * @return the String result
182 * @throws IllegalArgumentException
183 * if the Object or {@link ToStringStyle} is {@code null}
184 *
185 * @see ToStringExclude
186 * @see ToStringSummary
187 */
188 public static String toString(final Object object, final ToStringStyle style) {
189 return toString(object, style, false, false, null);
190 }
191
192 /**
193 * Builds a {@code toString} value through reflection.
194 *
195 * <p>
196 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
197 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
198 * also not as efficient as testing explicitly.
199 * </p>
200 *
201 * <p>
202 * If the {@code outputTransients} is {@code true}, transient members will be output, otherwise they
203 * are ignored, as they are likely derived fields, and not part of the value of the Object.
204 * </p>
205 *
206 * <p>
207 * Static fields will not be included. Superclass fields will be appended.
208 * </p>
209 *
210 * <p>
211 * If the style is {@code null}, the default {@link ToStringStyle} is used.
212 * </p>
213 *
214 * @param object
215 * the Object to be output
216 * @param style
217 * the style of the {@code toString} to create, may be {@code null}
218 * @param outputTransients
219 * whether to include transient fields
220 * @return the String result
221 * @throws IllegalArgumentException
222 * if the Object is {@code null}
223 *
224 * @see ToStringExclude
225 * @see ToStringSummary
226 */
227 public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients) {
228 return toString(object, style, outputTransients, false, null);
229 }
230
231 /**
232 * Builds a {@code toString} value through reflection.
233 *
234 * <p>
235 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
236 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
237 * also not as efficient as testing explicitly.
238 * </p>
239 *
240 * <p>
241 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they
242 * are ignored, as they are likely derived fields, and not part of the value of the Object.
243 * </p>
244 *
245 * <p>
246 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are
247 * ignored.
248 * </p>
249 *
250 * <p>
251 * Static fields will not be included. Superclass fields will be appended.
252 * </p>
253 *
254 * <p>
255 * If the style is {@code null}, the default {@link ToStringStyle} is used.
256 * </p>
257 *
258 * @param object
259 * the Object to be output
260 * @param style
261 * the style of the {@code toString} to create, may be {@code null}
262 * @param outputTransients
263 * whether to include transient fields
264 * @param outputStatics
265 * whether to include static fields
266 * @return the String result
267 * @throws IllegalArgumentException
268 * if the Object is {@code null}
269 *
270 * @see ToStringExclude
271 * @see ToStringSummary
272 * @since 2.1
273 */
274 public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients, final boolean outputStatics) {
275 return toString(object, style, outputTransients, outputStatics, null);
276 }
277
278 /**
279 * Builds a {@code toString} value through reflection.
280 *
281 * <p>
282 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
283 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
284 * also not as efficient as testing explicitly.
285 * </p>
286 *
287 * <p>
288 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they
289 * are ignored, as they are likely derived fields, and not part of the value of the Object.
290 * </p>
291 *
292 * <p>
293 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are
294 * ignored.
295 * </p>
296 *
297 * <p>
298 * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
299 * {@link Object}.
300 * </p>
301 *
302 * <p>
303 * If the style is {@code null}, the default {@link ToStringStyle} is used.
304 * </p>
305 *
306 * @param <T>
307 * the type of the object
308 * @param object
309 * the Object to be output
310 * @param style
311 * the style of the {@code toString} to create, may be {@code null}
312 * @param outputTransients
313 * whether to include transient fields
314 * @param outputStatics
315 * whether to include static fields
316 * @param excludeNullValues
317 * whether to exclude fields whose values are null
318 * @param reflectUpToClass
319 * the superclass to reflect up to (inclusive), may be {@code null}
320 * @return the String result
321 * @throws IllegalArgumentException
322 * if the Object is {@code null}
323 *
324 * @see ToStringExclude
325 * @see ToStringSummary
326 * @since 3.6
327 */
328 public static <T> String toString(
329 final T object, final ToStringStyle style, final boolean outputTransients,
330 final boolean outputStatics, final boolean excludeNullValues, final Class<? super T> reflectUpToClass) {
331 return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics, excludeNullValues)
332 .toString();
333 }
334
335 /**
336 * Builds a {@code toString} value through reflection.
337 *
338 * <p>
339 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
340 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
341 * also not as efficient as testing explicitly.
342 * </p>
343 *
344 * <p>
345 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they
346 * are ignored, as they are likely derived fields, and not part of the value of the Object.
347 * </p>
348 *
349 * <p>
350 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are
351 * ignored.
352 * </p>
353 *
354 * <p>
355 * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
356 * {@link Object}.
357 * </p>
358 *
359 * <p>
360 * If the style is {@code null}, the default {@link ToStringStyle} is used.
361 * </p>
362 *
363 * @param <T>
364 * the type of the object
365 * @param object
366 * the Object to be output
367 * @param style
368 * the style of the {@code toString} to create, may be {@code null}
369 * @param outputTransients
370 * whether to include transient fields
371 * @param outputStatics
372 * whether to include static fields
373 * @param reflectUpToClass
374 * the superclass to reflect up to (inclusive), may be {@code null}
375 * @return the String result
376 * @throws IllegalArgumentException
377 * if the Object is {@code null}
378 *
379 * @see ToStringExclude
380 * @see ToStringSummary
381 * @since 2.1
382 */
383 public static <T> String toString(
384 final T object, final ToStringStyle style, final boolean outputTransients,
385 final boolean outputStatics, final Class<? super T> reflectUpToClass) {
386 return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
387 .toString();
388 }
389
390 /**
391 * Builds a String for a toString method excluding the given field names.
392 *
393 * @param object
394 * The object to "toString".
395 * @param excludeFieldNames
396 * The field names to exclude. Null excludes nothing.
397 * @return The toString value.
398 */
399 public static String toStringExclude(final Object object, final Collection<String> excludeFieldNames) {
400 return toStringExclude(object, toNoNullStringArray(excludeFieldNames));
401 }
402
403 /**
404 * Builds a String for a toString method excluding the given field names.
405 *
406 * @param object
407 * The object to "toString".
408 * @param excludeFieldNames
409 * The field names to exclude
410 * @return The toString value.
411 */
412 public static String toStringExclude(final Object object, final String... excludeFieldNames) {
413 return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString();
414 }
415
416 /**
417 * Builds a String for a toString method including the given field names.
418 *
419 * @param object
420 * The object to "toString".
421 * @param includeFieldNames
422 * {@code null} or empty means all fields are included. All fields are included by default. This method will override the default behavior.
423 * @return The toString value.
424 * @since 3.13.0
425 */
426 public static String toStringInclude(final Object object, final Collection<String> includeFieldNames) {
427 return toStringInclude(object, toNoNullStringArray(includeFieldNames));
428 }
429
430 /**
431 * Builds a String for a toString method including the given field names.
432 *
433 * @param object
434 * The object to "toString".
435 * @param includeFieldNames
436 * The field names to include. {@code null} or empty means all fields are included. All fields are included by default. This method will override the default
437 * behavior.
438 * @return The toString value.
439 * @since 3.13.0
440 */
441 public static String toStringInclude(final Object object, final String... includeFieldNames) {
442 return new ReflectionToStringBuilder(object).setIncludeFieldNames(includeFieldNames).toString();
443 }
444
445 /**
446 * Whether or not to append static fields.
447 */
448 private boolean appendStatics;
449
450 /**
451 * Whether or not to append transient fields.
452 */
453 private boolean appendTransients;
454
455 /**
456 * Whether or not to append fields that are null.
457 */
458 private boolean excludeNullValues;
459
460 /**
461 * Which field names to exclude from output. Intended for fields like {@code "password"}.
462 *
463 * @since 3.0 this is protected instead of private
464 */
465 protected String[] excludeFieldNames;
466
467 /**
468 * Field names that will be included in the output. All fields are included by default.
469 *
470 * @since 3.13.0
471 */
472 protected String[] includeFieldNames;
473
474 /**
475 * The last super class to stop appending fields for.
476 */
477 private Class<?> upToClass;
478
479 /**
480 * Constructs a new instance.
481 *
482 * <p>
483 * This constructor outputs using the default style set with {@code setDefaultStyle}.
484 * </p>
485 *
486 * @param object
487 * the Object to build a {@code toString} for, must not be {@code null}
488 */
489 public ReflectionToStringBuilder(final Object object) {
490 super(object);
491 }
492
493 /**
494 * Constructs a new instance.
495 *
496 * <p>
497 * If the style is {@code null}, the default style is used.
498 * </p>
499 *
500 * @param object
501 * the Object to build a {@code toString} for, must not be {@code null}
502 * @param style
503 * the style of the {@code toString} to create, may be {@code null}
504 */
505 public ReflectionToStringBuilder(final Object object, final ToStringStyle style) {
506 super(object, style);
507 }
508
509 /**
510 * Constructs a new instance.
511 *
512 * <p>
513 * If the style is {@code null}, the default style is used.
514 * </p>
515 *
516 * <p>
517 * If the buffer is {@code null}, a new one is created.
518 * </p>
519 *
520 * @param object
521 * the Object to build a {@code toString} for
522 * @param style
523 * the style of the {@code toString} to create, may be {@code null}
524 * @param buffer
525 * the {@link StringBuffer} to populate, may be {@code null}
526 */
527 public ReflectionToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) {
528 super(object, style, buffer);
529 }
530
531 /**
532 * Constructs a new instance.
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 {@link 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(object, style, buffer);
554 setUpToClass(reflectUpToClass);
555 setAppendTransients(outputTransients);
556 setAppendStatics(outputStatics);
557 }
558
559 /**
560 * Constructs a new instance.
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 {@link 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(object, style, buffer);
585 setUpToClass(reflectUpToClass);
586 setAppendTransients(outputTransients);
587 setAppendStatics(outputStatics);
588 setExcludeNullValues(excludeNullValues);
589 }
590
591 /**
592 * Returns whether or not to append the given {@link 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 {@link 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()) && !isAppendTransients()) {
609 // Reject transient fields.
610 return false;
611 }
612 if (Modifier.isStatic(field.getModifiers()) && !isAppendStatics()) {
613 // Reject static fields.
614 return false;
615 }
616
617 if (this.excludeFieldNames != null
618 && Arrays.binarySearch(this.excludeFieldNames, field.getName()) >= 0) {
619 // Reject fields from the getExcludeFieldNames list.
620 return false;
621 }
622
623 if (ArrayUtils.isNotEmpty(includeFieldNames)) {
624 // Accept fields from the getIncludeFieldNames list. {@code null} or empty means all fields are included. All fields are included by default.
625 return Arrays.binarySearch(this.includeFieldNames, field.getName()) >= 0;
626 }
627
628 return !field.isAnnotationPresent(ToStringExclude.class);
629 }
630
631 /**
632 * Appends the fields and values defined by the given object of the given Class.
633 *
634 * <p>
635 * If a cycle is detected as an object is "toString()'ed", such an object is rendered as if
636 * {@code Object.toString()} had been called and not implemented by the object.
637 * </p>
638 *
639 * @param clazz
640 * The class of object parameter
641 */
642 protected void appendFieldsIn(final Class<?> clazz) {
643 if (clazz.isArray()) {
644 reflectionAppendArray(getObject());
645 return;
646 }
647 // The elements in the returned array are not sorted and are not in any particular order.
648 final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
649 AccessibleObject.setAccessible(fields, true);
650 for (final Field field : fields) {
651 final String fieldName = field.getName();
652 if (accept(field)) {
653 try {
654 // Warning: Field.get(Object) creates wrappers objects
655 // for primitive types.
656 final Object fieldValue = getValue(field);
657 if (!excludeNullValues || fieldValue != null) {
658 this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class));
659 }
660 } catch (final IllegalAccessException e) {
661 // this can't happen. Would get a Security exception instead throw a runtime exception in case the
662 // impossible happens.
663 throw new IllegalStateException(e);
664 }
665 }
666 }
667 }
668
669 /**
670 * Gets the excludeFieldNames.
671 *
672 * @return the excludeFieldNames.
673 */
674 public String[] getExcludeFieldNames() {
675 return this.excludeFieldNames.clone();
676 }
677
678 /**
679 * Gets the includeFieldNames
680 *
681 * @return the includeFieldNames.
682 * @since 3.13.0
683 */
684 public String[] getIncludeFieldNames() {
685 return this.includeFieldNames.clone();
686 }
687
688 /**
689 * Gets the last super class to stop appending fields for.
690 *
691 * @return The last super class to stop appending fields for.
692 */
693 public Class<?> getUpToClass() {
694 return this.upToClass;
695 }
696
697 /**
698 * Calls {@code java.lang.reflect.Field.get(Object)}.
699 *
700 * @param field
701 * The Field to query.
702 * @return The Object from the given Field.
703 * @throws IllegalArgumentException
704 * see {@link java.lang.reflect.Field#get(Object)}
705 * @throws IllegalAccessException
706 * see {@link java.lang.reflect.Field#get(Object)}
707 *
708 * @see java.lang.reflect.Field#get(Object)
709 */
710 protected Object getValue(final Field field) throws IllegalAccessException {
711 return field.get(getObject());
712 }
713
714 /**
715 * Gets whether or not to append static fields.
716 *
717 * @return Whether or not to append static fields.
718 * @since 2.1
719 */
720 public boolean isAppendStatics() {
721 return this.appendStatics;
722 }
723
724 /**
725 * Gets whether or not to append transient fields.
726 *
727 * @return Whether or not to append transient fields.
728 */
729 public boolean isAppendTransients() {
730 return this.appendTransients;
731 }
732
733 /**
734 * Gets whether or not to append fields whose values are null.
735 *
736 * @return Whether or not to append fields whose values are null.
737 * @since 3.6
738 */
739 public boolean isExcludeNullValues() {
740 return this.excludeNullValues;
741 }
742
743 /**
744 * Appends to the {@code toString} an {@link Object} array.
745 *
746 * @param array
747 * the array to add to the {@code toString}
748 * @return {@code this} instance.
749 */
750 public ReflectionToStringBuilder reflectionAppendArray(final Object array) {
751 getStyle().reflectionAppendArrayDetail(getStringBuffer(), null, array);
752 return this;
753 }
754
755 /**
756 * Sets whether or not to append static fields.
757 *
758 * @param appendStatics
759 * Whether or not to append static fields.
760 * @since 2.1
761 */
762 public void setAppendStatics(final boolean appendStatics) {
763 this.appendStatics = appendStatics;
764 }
765
766 /**
767 * Sets whether or not to append transient fields.
768 *
769 * @param appendTransients
770 * Whether or not to append transient fields.
771 */
772 public void setAppendTransients(final boolean appendTransients) {
773 this.appendTransients = appendTransients;
774 }
775
776 /**
777 * Sets the field names to exclude.
778 *
779 * @param excludeFieldNamesParam
780 * The excludeFieldNames to excluding from toString or {@code null}.
781 * @return {@code this}
782 */
783 public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) {
784 if (excludeFieldNamesParam == null) {
785 this.excludeFieldNames = null;
786 } else {
787 // clone and remove nulls
788 this.excludeFieldNames = ArraySorter.sort(toNoNullStringArray(excludeFieldNamesParam));
789 }
790 return this;
791 }
792
793 /**
794 * Sets whether or not to append fields whose values are null.
795 *
796 * @param excludeNullValues
797 * Whether or not to append fields whose values are null.
798 * @since 3.6
799 */
800 public void setExcludeNullValues(final boolean excludeNullValues) {
801 this.excludeNullValues = excludeNullValues;
802 }
803
804 /**
805 * Sets the field names to include. {@code null} or empty means all fields are included. All fields are included by default. This method will override the default behavior.
806 *
807 * @param includeFieldNamesParam
808 * The includeFieldNames that must be on toString or {@code null}.
809 * @return {@code this}
810 * @since 3.13.0
811 */
812 public ReflectionToStringBuilder setIncludeFieldNames(final String... includeFieldNamesParam) {
813 if (includeFieldNamesParam == null) {
814 this.includeFieldNames = null;
815 } else {
816 // clone and remove nulls
817 this.includeFieldNames = ArraySorter.sort(toNoNullStringArray(includeFieldNamesParam));
818 }
819 return this;
820 }
821
822 /**
823 * Sets the last super class to stop appending fields for.
824 *
825 * @param clazz
826 * The last super class to stop appending fields for.
827 */
828 public void setUpToClass(final Class<?> clazz) {
829 if (clazz != null) {
830 final Object object = getObject();
831 if (object != null && !clazz.isInstance(object)) {
832 throw new IllegalArgumentException("Specified class is not a superclass of the object");
833 }
834 }
835 this.upToClass = clazz;
836 }
837
838 /**
839 * Gets the String built by this builder.
840 *
841 * @return the built string
842 */
843 @Override
844 public String toString() {
845 if (getObject() == null) {
846 return getStyle().getNullText();
847 }
848
849 validate();
850
851 Class<?> clazz = getObject().getClass();
852 appendFieldsIn(clazz);
853 while (clazz.getSuperclass() != null && clazz != getUpToClass()) {
854 clazz = clazz.getSuperclass();
855 appendFieldsIn(clazz);
856 }
857 return super.toString();
858 }
859
860 /**
861 * Validates that include and exclude names do not intersect.
862 */
863 private void validate() {
864 if (ArrayUtils.containsAny(this.excludeFieldNames, (Object[]) this.includeFieldNames)) {
865 ToStringStyle.unregister(getObject());
866 throw new IllegalStateException("includeFieldNames and excludeFieldNames must not intersect");
867 }
868 }
869
870 }