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