001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.lang3.builder; 019 020import java.lang.reflect.AccessibleObject; 021import java.lang.reflect.Field; 022import java.lang.reflect.Modifier; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.Comparator; 026import java.util.Objects; 027 028import org.apache.commons.lang3.ArraySorter; 029import org.apache.commons.lang3.ArrayUtils; 030import org.apache.commons.lang3.ClassUtils; 031import org.apache.commons.lang3.stream.Streams; 032 033/** 034 * Assists in implementing {@link Object#toString()} methods using reflection. 035 * 036 * <p> 037 * This class uses reflection to determine the fields to append. Because these fields are usually private, the class 038 * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to 039 * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are 040 * set up correctly. 041 * </p> 042 * <p> 043 * Using reflection to access (private) fields circumvents any synchronization protection guarding access to these 044 * fields. If a toString method cannot safely read a field, you should exclude it from the toString method, or use 045 * synchronization consistent with the class' lock management around the invocation of the method. Take special care to 046 * exclude non-thread-safe collection classes, because these classes may throw ConcurrentModificationException if 047 * modified while the toString method is executing. 048 * </p> 049 * <p> 050 * A typical invocation for this method would look like: 051 * </p> 052 * <pre> 053 * public String toString() { 054 * return ReflectionToStringBuilder.toString(this); 055 * } 056 * </pre> 057 * <p> 058 * You can also use the builder to debug 3rd party objects: 059 * </p> 060 * <pre> 061 * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject)); 062 * </pre> 063 * <p> 064 * A subclass can control field output by overriding the methods: 065 * </p> 066 * <ul> 067 * <li>{@link #accept(java.lang.reflect.Field)}</li> 068 * <li>{@link #getValue(java.lang.reflect.Field)}</li> 069 * </ul> 070 * <p> 071 * For example, this method does <em>not</em> include the {@code password} field in the returned {@link String}: 072 * </p> 073 * <pre> 074 * public String toString() { 075 * return (new ReflectionToStringBuilder(this) { 076 * protected boolean accept(Field f) { 077 * return super.accept(f) && !f.getName().equals("password"); 078 * } 079 * }).toString(); 080 * } 081 * </pre> 082 * <p> 083 * Alternatively the {@link ToStringExclude} annotation can be used to exclude fields from being incorporated in the 084 * result. 085 * </p> 086 * <p> 087 * It is also possible to use the {@link ToStringSummary} annotation to output the summary information instead of the 088 * detailed information of a field. 089 * </p> 090 * <p> 091 * The exact format of the {@code toString} is determined by the {@link ToStringStyle} passed into the constructor. 092 * </p> 093 * 094 * <p> 095 * <b>Note:</b> the default {@link ToStringStyle} will only do a "shallow" formatting, i.e. composed objects are not 096 * further traversed. To get "deep" formatting, use an instance of {@link RecursiveToStringStyle}. 097 * </p> 098 * 099 * @since 2.0 100 */ 101public 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 this.setUpToClass(reflectUpToClass); 555 this.setAppendTransients(outputTransients); 556 this.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 this.setUpToClass(reflectUpToClass); 586 this.setAppendTransients(outputTransients); 587 this.setAppendStatics(outputStatics); 588 this.setExcludeNullValues(excludeNullValues); 589 } 590 591 /** 592 * Returns whether or not to append the given {@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()) && !this.isAppendTransients()) { 609 // Reject transient fields. 610 return false; 611 } 612 if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) { 613 // Reject static fields. 614 return false; 615 } 616 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 this.reflectionAppendArray(this.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 (this.accept(field)) { 653 try { 654 // Warning: Field.get(Object) creates wrappers objects 655 // for primitive types. 656 final Object fieldValue = this.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 * 704 * @throws IllegalArgumentException 705 * see {@link java.lang.reflect.Field#get(Object)} 706 * @throws IllegalAccessException 707 * see {@link java.lang.reflect.Field#get(Object)} 708 * 709 * @see java.lang.reflect.Field#get(Object) 710 */ 711 protected Object getValue(final Field field) throws IllegalAccessException { 712 return field.get(this.getObject()); 713 } 714 715 /** 716 * Gets whether or not to append static fields. 717 * 718 * @return Whether or not to append static fields. 719 * @since 2.1 720 */ 721 public boolean isAppendStatics() { 722 return this.appendStatics; 723 } 724 725 /** 726 * Gets whether or not to append transient fields. 727 * 728 * @return Whether or not to append transient fields. 729 */ 730 public boolean isAppendTransients() { 731 return this.appendTransients; 732 } 733 734 /** 735 * Gets whether or not to append fields whose values are null. 736 * 737 * @return Whether or not to append fields whose values are null. 738 * @since 3.6 739 */ 740 public boolean isExcludeNullValues() { 741 return this.excludeNullValues; 742 } 743 744 /** 745 * Appends to the {@code toString} an {@link Object} array. 746 * 747 * @param array 748 * the array to add to the {@code toString} 749 * @return {@code this} instance. 750 */ 751 public ReflectionToStringBuilder reflectionAppendArray(final Object array) { 752 this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array); 753 return this; 754 } 755 756 /** 757 * Sets whether or not to append static fields. 758 * 759 * @param appendStatics 760 * Whether or not to append static fields. 761 * @since 2.1 762 */ 763 public void setAppendStatics(final boolean appendStatics) { 764 this.appendStatics = appendStatics; 765 } 766 767 /** 768 * Sets whether or not to append transient fields. 769 * 770 * @param appendTransients 771 * Whether or not to append transient fields. 772 */ 773 public void setAppendTransients(final boolean appendTransients) { 774 this.appendTransients = appendTransients; 775 } 776 777 /** 778 * Sets the field names to exclude. 779 * 780 * @param excludeFieldNamesParam 781 * The excludeFieldNames to excluding from toString or {@code null}. 782 * @return {@code this} 783 */ 784 public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) { 785 if (excludeFieldNamesParam == null) { 786 this.excludeFieldNames = null; 787 } else { 788 // clone and remove nulls 789 this.excludeFieldNames = ArraySorter.sort(toNoNullStringArray(excludeFieldNamesParam)); 790 } 791 return this; 792 } 793 794 /** 795 * Sets whether or not to append fields whose values are null. 796 * 797 * @param excludeNullValues 798 * Whether or not to append fields whose values are null. 799 * @since 3.6 800 */ 801 public void setExcludeNullValues(final boolean excludeNullValues) { 802 this.excludeNullValues = excludeNullValues; 803 } 804 805 /** 806 * 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. 807 * 808 * @param includeFieldNamesParam 809 * The includeFieldNames that must be on toString or {@code null}. 810 * @return {@code this} 811 * @since 3.13.0 812 */ 813 public ReflectionToStringBuilder setIncludeFieldNames(final String... includeFieldNamesParam) { 814 if (includeFieldNamesParam == null) { 815 this.includeFieldNames = null; 816 } else { 817 // clone and remove nulls 818 this.includeFieldNames = ArraySorter.sort(toNoNullStringArray(includeFieldNamesParam)); 819 } 820 return this; 821 } 822 823 /** 824 * Sets the last super class to stop appending fields for. 825 * 826 * @param clazz 827 * The last super class to stop appending fields for. 828 */ 829 public void setUpToClass(final Class<?> clazz) { 830 if (clazz != null) { 831 final Object object = getObject(); 832 if (object != null && !clazz.isInstance(object)) { 833 throw new IllegalArgumentException("Specified class is not a superclass of the object"); 834 } 835 } 836 this.upToClass = clazz; 837 } 838 839 /** 840 * Gets the String built by this builder. 841 * 842 * @return the built string 843 */ 844 @Override 845 public String toString() { 846 if (this.getObject() == null) { 847 return this.getStyle().getNullText(); 848 } 849 850 validate(); 851 852 Class<?> clazz = this.getObject().getClass(); 853 this.appendFieldsIn(clazz); 854 while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) { 855 clazz = clazz.getSuperclass(); 856 this.appendFieldsIn(clazz); 857 } 858 return super.toString(); 859 } 860 861 /** 862 * Validates that include and exclude names do not intersect. 863 */ 864 private void validate() { 865 if (ArrayUtils.containsAny(this.excludeFieldNames, (Object[]) this.includeFieldNames)) { 866 ToStringStyle.unregister(this.getObject()); 867 throw new IllegalStateException("includeFieldNames and excludeFieldNames must not intersect"); 868 } 869 } 870 871}