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 */ 017package org.apache.commons.lang3.builder; 018 019import java.io.Serializable; 020import java.lang.reflect.Array; 021import java.util.Collection; 022import java.util.Map; 023import java.util.WeakHashMap; 024 025import org.apache.commons.lang3.ClassUtils; 026import org.apache.commons.lang3.ObjectUtils; 027import org.apache.commons.lang3.SystemUtils; 028 029/** 030 * <p>Controls <code>String</code> formatting for {@link ToStringBuilder}. 031 * The main public interface is always via <code>ToStringBuilder</code>.</p> 032 * 033 * <p>These classes are intended to be used as <code>Singletons</code>. 034 * There is no need to instantiate a new style each time. A program 035 * will generally use one of the predefined constants on this class. 036 * Alternatively, the {@link StandardToStringStyle} class can be used 037 * to set the individual settings. Thus most styles can be achieved 038 * without subclassing.</p> 039 * 040 * <p>If required, a subclass can override as many or as few of the 041 * methods as it requires. Each object type (from <code>boolean</code> 042 * to <code>long</code> to <code>Object</code> to <code>int[]</code>) has 043 * its own methods to output it. Most have two versions, detail and summary. 044 * 045 * <p>For example, the detail version of the array based methods will 046 * output the whole array, whereas the summary method will just output 047 * the array length.</p> 048 * 049 * <p>If you want to format the output of certain objects, such as dates, you 050 * must create a subclass and override a method. 051 * <pre> 052 * public class MyStyle extends ToStringStyle { 053 * protected void appendDetail(StringBuffer buffer, String fieldName, Object value) { 054 * if (value instanceof Date) { 055 * value = new SimpleDateFormat("yyyy-MM-dd").format(value); 056 * } 057 * buffer.append(value); 058 * } 059 * } 060 * </pre> 061 * </p> 062 * 063 * @since 1.0 064 * @version $Id: ToStringStyle.java 1525014 2013-09-20 14:08:12Z britter $ 065 */ 066public abstract class ToStringStyle implements Serializable { 067 068 /** 069 * Serialization version ID. 070 */ 071 private static final long serialVersionUID = -2587890625525655916L; 072 073 /** 074 * The default toString style. Using the Using the <code>Person</code> 075 * example from {@link ToStringBuilder}, the output would look like this: 076 * 077 * <pre> 078 * Person@182f0db[name=John Doe,age=33,smoker=false] 079 * </pre> 080 */ 081 public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle(); 082 083 /** 084 * The multi line toString style. Using the <code>Person</code> 085 * example from {@link ToStringBuilder}, the output would look like this: 086 * 087 * <pre> 088 * Person@182f0db[ 089 * name=John Doe 090 * age=33 091 * smoker=false 092 * ] 093 * </pre> 094 */ 095 public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle(); 096 097 /** 098 * The no field names toString style. Using the Using the 099 * <code>Person</code> example from {@link ToStringBuilder}, the output 100 * would look like this: 101 * 102 * <pre> 103 * Person@182f0db[John Doe,33,false] 104 * </pre> 105 */ 106 public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle(); 107 108 /** 109 * The short prefix toString style. Using the <code>Person</code> example 110 * from {@link ToStringBuilder}, the output would look like this: 111 * 112 * <pre> 113 * Person[name=John Doe,age=33,smoker=false] 114 * </pre> 115 * 116 * @since 2.1 117 */ 118 public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle(); 119 120 /** 121 * The simple toString style. Using the Using the <code>Person</code> 122 * example from {@link ToStringBuilder}, the output would look like this: 123 * 124 * <pre> 125 * John Doe,33,false 126 * </pre> 127 */ 128 public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle(); 129 130 /** 131 * <p> 132 * A registry of objects used by <code>reflectionToString</code> methods 133 * to detect cyclical object references and avoid infinite loops. 134 * </p> 135 */ 136 private static final ThreadLocal<WeakHashMap<Object, Object>> REGISTRY = 137 new ThreadLocal<WeakHashMap<Object,Object>>(); 138 /* 139 * Note that objects of this class are generally shared between threads, so 140 * an instance variable would not be suitable here. 141 * 142 * In normal use the registry should always be left empty, because the caller 143 * should call toString() which will clean up. 144 * 145 * See LANG-792 146 */ 147 148 /** 149 * <p> 150 * Returns the registry of objects being traversed by the <code>reflectionToString</code> 151 * methods in the current thread. 152 * </p> 153 * 154 * @return Set the registry of objects being traversed 155 */ 156 static Map<Object, Object> getRegistry() { 157 return REGISTRY.get(); 158 } 159 160 /** 161 * <p> 162 * Returns <code>true</code> if the registry contains the given object. 163 * Used by the reflection methods to avoid infinite loops. 164 * </p> 165 * 166 * @param value 167 * The object to lookup in the registry. 168 * @return boolean <code>true</code> if the registry contains the given 169 * object. 170 */ 171 static boolean isRegistered(final Object value) { 172 final Map<Object, Object> m = getRegistry(); 173 return m != null && m.containsKey(value); 174 } 175 176 /** 177 * <p> 178 * Registers the given object. Used by the reflection methods to avoid 179 * infinite loops. 180 * </p> 181 * 182 * @param value 183 * The object to register. 184 */ 185 static void register(final Object value) { 186 if (value != null) { 187 final Map<Object, Object> m = getRegistry(); 188 if (m == null) { 189 REGISTRY.set(new WeakHashMap<Object, Object>()); 190 } 191 getRegistry().put(value, null); 192 } 193 } 194 195 /** 196 * <p> 197 * Unregisters the given object. 198 * </p> 199 * 200 * <p> 201 * Used by the reflection methods to avoid infinite loops. 202 * </p> 203 * 204 * @param value 205 * The object to unregister. 206 */ 207 static void unregister(final Object value) { 208 if (value != null) { 209 final Map<Object, Object> m = getRegistry(); 210 if (m != null) { 211 m.remove(value); 212 if (m.isEmpty()) { 213 REGISTRY.remove(); 214 } 215 } 216 } 217 } 218 219 /** 220 * Whether to use the field names, the default is <code>true</code>. 221 */ 222 private boolean useFieldNames = true; 223 224 /** 225 * Whether to use the class name, the default is <code>true</code>. 226 */ 227 private boolean useClassName = true; 228 229 /** 230 * Whether to use short class names, the default is <code>false</code>. 231 */ 232 private boolean useShortClassName = false; 233 234 /** 235 * Whether to use the identity hash code, the default is <code>true</code>. 236 */ 237 private boolean useIdentityHashCode = true; 238 239 /** 240 * The content start <code>'['</code>. 241 */ 242 private String contentStart = "["; 243 244 /** 245 * The content end <code>']'</code>. 246 */ 247 private String contentEnd = "]"; 248 249 /** 250 * The field name value separator <code>'='</code>. 251 */ 252 private String fieldNameValueSeparator = "="; 253 254 /** 255 * Whether the field separator should be added before any other fields. 256 */ 257 private boolean fieldSeparatorAtStart = false; 258 259 /** 260 * Whether the field separator should be added after any other fields. 261 */ 262 private boolean fieldSeparatorAtEnd = false; 263 264 /** 265 * The field separator <code>','</code>. 266 */ 267 private String fieldSeparator = ","; 268 269 /** 270 * The array start <code>'{'</code>. 271 */ 272 private String arrayStart = "{"; 273 274 /** 275 * The array separator <code>','</code>. 276 */ 277 private String arraySeparator = ","; 278 279 /** 280 * The detail for array content. 281 */ 282 private boolean arrayContentDetail = true; 283 284 /** 285 * The array end <code>'}'</code>. 286 */ 287 private String arrayEnd = "}"; 288 289 /** 290 * The value to use when fullDetail is <code>null</code>, 291 * the default value is <code>true</code>. 292 */ 293 private boolean defaultFullDetail = true; 294 295 /** 296 * The <code>null</code> text <code>'<null>'</code>. 297 */ 298 private String nullText = "<null>"; 299 300 /** 301 * The summary size text start <code>'<size'</code>. 302 */ 303 private String sizeStartText = "<size="; 304 305 /** 306 * The summary size text start <code>'>'</code>. 307 */ 308 private String sizeEndText = ">"; 309 310 /** 311 * The summary object text start <code>'<'</code>. 312 */ 313 private String summaryObjectStartText = "<"; 314 315 /** 316 * The summary object text start <code>'>'</code>. 317 */ 318 private String summaryObjectEndText = ">"; 319 320 //---------------------------------------------------------------------------- 321 322 /** 323 * <p>Constructor.</p> 324 */ 325 protected ToStringStyle() { 326 super(); 327 } 328 329 //---------------------------------------------------------------------------- 330 331 /** 332 * <p>Append to the <code>toString</code> the superclass toString.</p> 333 * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p> 334 * 335 * <p>A <code>null</code> <code>superToString</code> is ignored.</p> 336 * 337 * @param buffer the <code>StringBuffer</code> to populate 338 * @param superToString the <code>super.toString()</code> 339 * @since 2.0 340 */ 341 public void appendSuper(final StringBuffer buffer, final String superToString) { 342 appendToString(buffer, superToString); 343 } 344 345 /** 346 * <p>Append to the <code>toString</code> another toString.</p> 347 * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p> 348 * 349 * <p>A <code>null</code> <code>toString</code> is ignored.</p> 350 * 351 * @param buffer the <code>StringBuffer</code> to populate 352 * @param toString the additional <code>toString</code> 353 * @since 2.0 354 */ 355 public void appendToString(final StringBuffer buffer, final String toString) { 356 if (toString != null) { 357 final int pos1 = toString.indexOf(contentStart) + contentStart.length(); 358 final int pos2 = toString.lastIndexOf(contentEnd); 359 if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) { 360 final String data = toString.substring(pos1, pos2); 361 if (fieldSeparatorAtStart) { 362 removeLastFieldSeparator(buffer); 363 } 364 buffer.append(data); 365 appendFieldSeparator(buffer); 366 } 367 } 368 } 369 370 /** 371 * <p>Append to the <code>toString</code> the start of data indicator.</p> 372 * 373 * @param buffer the <code>StringBuffer</code> to populate 374 * @param object the <code>Object</code> to build a <code>toString</code> for 375 */ 376 public void appendStart(final StringBuffer buffer, final Object object) { 377 if (object != null) { 378 appendClassName(buffer, object); 379 appendIdentityHashCode(buffer, object); 380 appendContentStart(buffer); 381 if (fieldSeparatorAtStart) { 382 appendFieldSeparator(buffer); 383 } 384 } 385 } 386 387 /** 388 * <p>Append to the <code>toString</code> the end of data indicator.</p> 389 * 390 * @param buffer the <code>StringBuffer</code> to populate 391 * @param object the <code>Object</code> to build a 392 * <code>toString</code> for. 393 */ 394 public void appendEnd(final StringBuffer buffer, final Object object) { 395 if (this.fieldSeparatorAtEnd == false) { 396 removeLastFieldSeparator(buffer); 397 } 398 appendContentEnd(buffer); 399 unregister(object); 400 } 401 402 /** 403 * <p>Remove the last field separator from the buffer.</p> 404 * 405 * @param buffer the <code>StringBuffer</code> to populate 406 * @since 2.0 407 */ 408 protected void removeLastFieldSeparator(final StringBuffer buffer) { 409 final int len = buffer.length(); 410 final int sepLen = fieldSeparator.length(); 411 if (len > 0 && sepLen > 0 && len >= sepLen) { 412 boolean match = true; 413 for (int i = 0; i < sepLen; i++) { 414 if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) { 415 match = false; 416 break; 417 } 418 } 419 if (match) { 420 buffer.setLength(len - sepLen); 421 } 422 } 423 } 424 425 //---------------------------------------------------------------------------- 426 427 /** 428 * <p>Append to the <code>toString</code> an <code>Object</code> 429 * value, printing the full <code>toString</code> of the 430 * <code>Object</code> passed in.</p> 431 * 432 * @param buffer the <code>StringBuffer</code> to populate 433 * @param fieldName the field name 434 * @param value the value to add to the <code>toString</code> 435 * @param fullDetail <code>true</code> for detail, <code>false</code> 436 * for summary info, <code>null</code> for style decides 437 */ 438 public void append(final StringBuffer buffer, final String fieldName, final Object value, final Boolean fullDetail) { 439 appendFieldStart(buffer, fieldName); 440 441 if (value == null) { 442 appendNullText(buffer, fieldName); 443 444 } else { 445 appendInternal(buffer, fieldName, value, isFullDetail(fullDetail)); 446 } 447 448 appendFieldEnd(buffer, fieldName); 449 } 450 451 /** 452 * <p>Append to the <code>toString</code> an <code>Object</code>, 453 * correctly interpreting its type.</p> 454 * 455 * <p>This method performs the main lookup by Class type to correctly 456 * route arrays, <code>Collections</code>, <code>Maps</code> and 457 * <code>Objects</code> to the appropriate method.</p> 458 * 459 * <p>Either detail or summary views can be specified.</p> 460 * 461 * <p>If a cycle is detected, an object will be appended with the 462 * <code>Object.toString()</code> format.</p> 463 * 464 * @param buffer the <code>StringBuffer</code> to populate 465 * @param fieldName the field name, typically not used as already appended 466 * @param value the value to add to the <code>toString</code>, 467 * not <code>null</code> 468 * @param detail output detail or not 469 */ 470 protected void appendInternal(final StringBuffer buffer, final String fieldName, final Object value, final boolean detail) { 471 if (isRegistered(value) 472 && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) { 473 appendCyclicObject(buffer, fieldName, value); 474 return; 475 } 476 477 register(value); 478 479 try { 480 if (value instanceof Collection<?>) { 481 if (detail) { 482 appendDetail(buffer, fieldName, (Collection<?>) value); 483 } else { 484 appendSummarySize(buffer, fieldName, ((Collection<?>) value).size()); 485 } 486 487 } else if (value instanceof Map<?, ?>) { 488 if (detail) { 489 appendDetail(buffer, fieldName, (Map<?, ?>) value); 490 } else { 491 appendSummarySize(buffer, fieldName, ((Map<?, ?>) value).size()); 492 } 493 494 } else if (value instanceof long[]) { 495 if (detail) { 496 appendDetail(buffer, fieldName, (long[]) value); 497 } else { 498 appendSummary(buffer, fieldName, (long[]) value); 499 } 500 501 } else if (value instanceof int[]) { 502 if (detail) { 503 appendDetail(buffer, fieldName, (int[]) value); 504 } else { 505 appendSummary(buffer, fieldName, (int[]) value); 506 } 507 508 } else if (value instanceof short[]) { 509 if (detail) { 510 appendDetail(buffer, fieldName, (short[]) value); 511 } else { 512 appendSummary(buffer, fieldName, (short[]) value); 513 } 514 515 } else if (value instanceof byte[]) { 516 if (detail) { 517 appendDetail(buffer, fieldName, (byte[]) value); 518 } else { 519 appendSummary(buffer, fieldName, (byte[]) value); 520 } 521 522 } else if (value instanceof char[]) { 523 if (detail) { 524 appendDetail(buffer, fieldName, (char[]) value); 525 } else { 526 appendSummary(buffer, fieldName, (char[]) value); 527 } 528 529 } else if (value instanceof double[]) { 530 if (detail) { 531 appendDetail(buffer, fieldName, (double[]) value); 532 } else { 533 appendSummary(buffer, fieldName, (double[]) value); 534 } 535 536 } else if (value instanceof float[]) { 537 if (detail) { 538 appendDetail(buffer, fieldName, (float[]) value); 539 } else { 540 appendSummary(buffer, fieldName, (float[]) value); 541 } 542 543 } else if (value instanceof boolean[]) { 544 if (detail) { 545 appendDetail(buffer, fieldName, (boolean[]) value); 546 } else { 547 appendSummary(buffer, fieldName, (boolean[]) value); 548 } 549 550 } else if (value.getClass().isArray()) { 551 if (detail) { 552 appendDetail(buffer, fieldName, (Object[]) value); 553 } else { 554 appendSummary(buffer, fieldName, (Object[]) value); 555 } 556 557 } else { 558 if (detail) { 559 appendDetail(buffer, fieldName, value); 560 } else { 561 appendSummary(buffer, fieldName, value); 562 } 563 } 564 } finally { 565 unregister(value); 566 } 567 } 568 569 /** 570 * <p>Append to the <code>toString</code> an <code>Object</code> 571 * value that has been detected to participate in a cycle. This 572 * implementation will print the standard string value of the value.</p> 573 * 574 * @param buffer the <code>StringBuffer</code> to populate 575 * @param fieldName the field name, typically not used as already appended 576 * @param value the value to add to the <code>toString</code>, 577 * not <code>null</code> 578 * 579 * @since 2.2 580 */ 581 protected void appendCyclicObject(final StringBuffer buffer, final String fieldName, final Object value) { 582 ObjectUtils.identityToString(buffer, value); 583 } 584 585 /** 586 * <p>Append to the <code>toString</code> an <code>Object</code> 587 * value, printing the full detail of the <code>Object</code>.</p> 588 * 589 * @param buffer the <code>StringBuffer</code> to populate 590 * @param fieldName the field name, typically not used as already appended 591 * @param value the value to add to the <code>toString</code>, 592 * not <code>null</code> 593 */ 594 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) { 595 buffer.append(value); 596 } 597 598 /** 599 * <p>Append to the <code>toString</code> a <code>Collection</code>.</p> 600 * 601 * @param buffer the <code>StringBuffer</code> to populate 602 * @param fieldName the field name, typically not used as already appended 603 * @param coll the <code>Collection</code> to add to the 604 * <code>toString</code>, not <code>null</code> 605 */ 606 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Collection<?> coll) { 607 buffer.append(coll); 608 } 609 610 /** 611 * <p>Append to the <code>toString</code> a <code>Map<code>.</p> 612 * 613 * @param buffer the <code>StringBuffer</code> to populate 614 * @param fieldName the field name, typically not used as already appended 615 * @param map the <code>Map</code> to add to the <code>toString</code>, 616 * not <code>null</code> 617 */ 618 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Map<?, ?> map) { 619 buffer.append(map); 620 } 621 622 /** 623 * <p>Append to the <code>toString</code> an <code>Object</code> 624 * value, printing a summary of the <code>Object</code>.</P> 625 * 626 * @param buffer the <code>StringBuffer</code> to populate 627 * @param fieldName the field name, typically not used as already appended 628 * @param value the value to add to the <code>toString</code>, 629 * not <code>null</code> 630 */ 631 protected void appendSummary(final StringBuffer buffer, final String fieldName, final Object value) { 632 buffer.append(summaryObjectStartText); 633 buffer.append(getShortClassName(value.getClass())); 634 buffer.append(summaryObjectEndText); 635 } 636 637 //---------------------------------------------------------------------------- 638 639 /** 640 * <p>Append to the <code>toString</code> a <code>long</code> 641 * value.</p> 642 * 643 * @param buffer the <code>StringBuffer</code> to populate 644 * @param fieldName the field name 645 * @param value the value to add to the <code>toString</code> 646 */ 647 public void append(final StringBuffer buffer, final String fieldName, final long value) { 648 appendFieldStart(buffer, fieldName); 649 appendDetail(buffer, fieldName, value); 650 appendFieldEnd(buffer, fieldName); 651 } 652 653 /** 654 * <p>Append to the <code>toString</code> a <code>long</code> 655 * value.</p> 656 * 657 * @param buffer the <code>StringBuffer</code> to populate 658 * @param fieldName the field name, typically not used as already appended 659 * @param value the value to add to the <code>toString</code> 660 */ 661 protected void appendDetail(final StringBuffer buffer, final String fieldName, final long value) { 662 buffer.append(value); 663 } 664 665 //---------------------------------------------------------------------------- 666 667 /** 668 * <p>Append to the <code>toString</code> an <code>int</code> 669 * value.</p> 670 * 671 * @param buffer the <code>StringBuffer</code> to populate 672 * @param fieldName the field name 673 * @param value the value to add to the <code>toString</code> 674 */ 675 public void append(final StringBuffer buffer, final String fieldName, final int value) { 676 appendFieldStart(buffer, fieldName); 677 appendDetail(buffer, fieldName, value); 678 appendFieldEnd(buffer, fieldName); 679 } 680 681 /** 682 * <p>Append to the <code>toString</code> an <code>int</code> 683 * value.</p> 684 * 685 * @param buffer the <code>StringBuffer</code> to populate 686 * @param fieldName the field name, typically not used as already appended 687 * @param value the value to add to the <code>toString</code> 688 */ 689 protected void appendDetail(final StringBuffer buffer, final String fieldName, final int value) { 690 buffer.append(value); 691 } 692 693 //---------------------------------------------------------------------------- 694 695 /** 696 * <p>Append to the <code>toString</code> a <code>short</code> 697 * value.</p> 698 * 699 * @param buffer the <code>StringBuffer</code> to populate 700 * @param fieldName the field name 701 * @param value the value to add to the <code>toString</code> 702 */ 703 public void append(final StringBuffer buffer, final String fieldName, final short value) { 704 appendFieldStart(buffer, fieldName); 705 appendDetail(buffer, fieldName, value); 706 appendFieldEnd(buffer, fieldName); 707 } 708 709 /** 710 * <p>Append to the <code>toString</code> a <code>short</code> 711 * value.</p> 712 * 713 * @param buffer the <code>StringBuffer</code> to populate 714 * @param fieldName the field name, typically not used as already appended 715 * @param value the value to add to the <code>toString</code> 716 */ 717 protected void appendDetail(final StringBuffer buffer, final String fieldName, final short value) { 718 buffer.append(value); 719 } 720 721 //---------------------------------------------------------------------------- 722 723 /** 724 * <p>Append to the <code>toString</code> a <code>byte</code> 725 * value.</p> 726 * 727 * @param buffer the <code>StringBuffer</code> to populate 728 * @param fieldName the field name 729 * @param value the value to add to the <code>toString</code> 730 */ 731 public void append(final StringBuffer buffer, final String fieldName, final byte value) { 732 appendFieldStart(buffer, fieldName); 733 appendDetail(buffer, fieldName, value); 734 appendFieldEnd(buffer, fieldName); 735 } 736 737 /** 738 * <p>Append to the <code>toString</code> a <code>byte</code> 739 * value.</p> 740 * 741 * @param buffer the <code>StringBuffer</code> to populate 742 * @param fieldName the field name, typically not used as already appended 743 * @param value the value to add to the <code>toString</code> 744 */ 745 protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte value) { 746 buffer.append(value); 747 } 748 749 //---------------------------------------------------------------------------- 750 751 /** 752 * <p>Append to the <code>toString</code> a <code>char</code> 753 * value.</p> 754 * 755 * @param buffer the <code>StringBuffer</code> to populate 756 * @param fieldName the field name 757 * @param value the value to add to the <code>toString</code> 758 */ 759 public void append(final StringBuffer buffer, final String fieldName, final char value) { 760 appendFieldStart(buffer, fieldName); 761 appendDetail(buffer, fieldName, value); 762 appendFieldEnd(buffer, fieldName); 763 } 764 765 /** 766 * <p>Append to the <code>toString</code> a <code>char</code> 767 * value.</p> 768 * 769 * @param buffer the <code>StringBuffer</code> to populate 770 * @param fieldName the field name, typically not used as already appended 771 * @param value the value to add to the <code>toString</code> 772 */ 773 protected void appendDetail(final StringBuffer buffer, final String fieldName, final char value) { 774 buffer.append(value); 775 } 776 777 //---------------------------------------------------------------------------- 778 779 /** 780 * <p>Append to the <code>toString</code> a <code>double</code> 781 * value.</p> 782 * 783 * @param buffer the <code>StringBuffer</code> to populate 784 * @param fieldName the field name 785 * @param value the value to add to the <code>toString</code> 786 */ 787 public void append(final StringBuffer buffer, final String fieldName, final double value) { 788 appendFieldStart(buffer, fieldName); 789 appendDetail(buffer, fieldName, value); 790 appendFieldEnd(buffer, fieldName); 791 } 792 793 /** 794 * <p>Append to the <code>toString</code> a <code>double</code> 795 * value.</p> 796 * 797 * @param buffer the <code>StringBuffer</code> to populate 798 * @param fieldName the field name, typically not used as already appended 799 * @param value the value to add to the <code>toString</code> 800 */ 801 protected void appendDetail(final StringBuffer buffer, final String fieldName, final double value) { 802 buffer.append(value); 803 } 804 805 //---------------------------------------------------------------------------- 806 807 /** 808 * <p>Append to the <code>toString</code> a <code>float</code> 809 * value.</p> 810 * 811 * @param buffer the <code>StringBuffer</code> to populate 812 * @param fieldName the field name 813 * @param value the value to add to the <code>toString</code> 814 */ 815 public void append(final StringBuffer buffer, final String fieldName, final float value) { 816 appendFieldStart(buffer, fieldName); 817 appendDetail(buffer, fieldName, value); 818 appendFieldEnd(buffer, fieldName); 819 } 820 821 /** 822 * <p>Append to the <code>toString</code> a <code>float</code> 823 * value.</p> 824 * 825 * @param buffer the <code>StringBuffer</code> to populate 826 * @param fieldName the field name, typically not used as already appended 827 * @param value the value to add to the <code>toString</code> 828 */ 829 protected void appendDetail(final StringBuffer buffer, final String fieldName, final float value) { 830 buffer.append(value); 831 } 832 833 //---------------------------------------------------------------------------- 834 835 /** 836 * <p>Append to the <code>toString</code> a <code>boolean</code> 837 * value.</p> 838 * 839 * @param buffer the <code>StringBuffer</code> to populate 840 * @param fieldName the field name 841 * @param value the value to add to the <code>toString</code> 842 */ 843 public void append(final StringBuffer buffer, final String fieldName, final boolean value) { 844 appendFieldStart(buffer, fieldName); 845 appendDetail(buffer, fieldName, value); 846 appendFieldEnd(buffer, fieldName); 847 } 848 849 /** 850 * <p>Append to the <code>toString</code> a <code>boolean</code> 851 * value.</p> 852 * 853 * @param buffer the <code>StringBuffer</code> to populate 854 * @param fieldName the field name, typically not used as already appended 855 * @param value the value to add to the <code>toString</code> 856 */ 857 protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean value) { 858 buffer.append(value); 859 } 860 861 /** 862 * <p>Append to the <code>toString</code> an <code>Object</code> 863 * array.</p> 864 * 865 * @param buffer the <code>StringBuffer</code> to populate 866 * @param fieldName the field name 867 * @param array the array to add to the toString 868 * @param fullDetail <code>true</code> for detail, <code>false</code> 869 * for summary info, <code>null</code> for style decides 870 */ 871 public void append(final StringBuffer buffer, final String fieldName, final Object[] array, final Boolean fullDetail) { 872 appendFieldStart(buffer, fieldName); 873 874 if (array == null) { 875 appendNullText(buffer, fieldName); 876 877 } else if (isFullDetail(fullDetail)) { 878 appendDetail(buffer, fieldName, array); 879 880 } else { 881 appendSummary(buffer, fieldName, array); 882 } 883 884 appendFieldEnd(buffer, fieldName); 885 } 886 887 //---------------------------------------------------------------------------- 888 889 /** 890 * <p>Append to the <code>toString</code> the detail of an 891 * <code>Object</code> array.</p> 892 * 893 * @param buffer the <code>StringBuffer</code> to populate 894 * @param fieldName the field name, typically not used as already appended 895 * @param array the array to add to the <code>toString</code>, 896 * not <code>null</code> 897 */ 898 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object[] array) { 899 buffer.append(arrayStart); 900 for (int i = 0; i < array.length; i++) { 901 final Object item = array[i]; 902 if (i > 0) { 903 buffer.append(arraySeparator); 904 } 905 if (item == null) { 906 appendNullText(buffer, fieldName); 907 908 } else { 909 appendInternal(buffer, fieldName, item, arrayContentDetail); 910 } 911 } 912 buffer.append(arrayEnd); 913 } 914 915 /** 916 * <p>Append to the <code>toString</code> the detail of an array type.</p> 917 * 918 * @param buffer the <code>StringBuffer</code> to populate 919 * @param fieldName the field name, typically not used as already appended 920 * @param array the array to add to the <code>toString</code>, 921 * not <code>null</code> 922 * @since 2.0 923 */ 924 protected void reflectionAppendArrayDetail(final StringBuffer buffer, final String fieldName, final Object array) { 925 buffer.append(arrayStart); 926 final int length = Array.getLength(array); 927 for (int i = 0; i < length; i++) { 928 final Object item = Array.get(array, i); 929 if (i > 0) { 930 buffer.append(arraySeparator); 931 } 932 if (item == null) { 933 appendNullText(buffer, fieldName); 934 935 } else { 936 appendInternal(buffer, fieldName, item, arrayContentDetail); 937 } 938 } 939 buffer.append(arrayEnd); 940 } 941 942 /** 943 * <p>Append to the <code>toString</code> a summary of an 944 * <code>Object</code> array.</p> 945 * 946 * @param buffer the <code>StringBuffer</code> to populate 947 * @param fieldName the field name, typically not used as already appended 948 * @param array the array to add to the <code>toString</code>, 949 * not <code>null</code> 950 */ 951 protected void appendSummary(final StringBuffer buffer, final String fieldName, final Object[] array) { 952 appendSummarySize(buffer, fieldName, array.length); 953 } 954 955 //---------------------------------------------------------------------------- 956 957 /** 958 * <p>Append to the <code>toString</code> a <code>long</code> 959 * array.</p> 960 * 961 * @param buffer the <code>StringBuffer</code> to populate 962 * @param fieldName the field name 963 * @param array the array to add to the <code>toString</code> 964 * @param fullDetail <code>true</code> for detail, <code>false</code> 965 * for summary info, <code>null</code> for style decides 966 */ 967 public void append(final StringBuffer buffer, final String fieldName, final long[] array, final Boolean fullDetail) { 968 appendFieldStart(buffer, fieldName); 969 970 if (array == null) { 971 appendNullText(buffer, fieldName); 972 973 } else if (isFullDetail(fullDetail)) { 974 appendDetail(buffer, fieldName, array); 975 976 } else { 977 appendSummary(buffer, fieldName, array); 978 } 979 980 appendFieldEnd(buffer, fieldName); 981 } 982 983 /** 984 * <p>Append to the <code>toString</code> the detail of a 985 * <code>long</code> array.</p> 986 * 987 * @param buffer the <code>StringBuffer</code> to populate 988 * @param fieldName the field name, typically not used as already appended 989 * @param array the array to add to the <code>toString</code>, 990 * not <code>null</code> 991 */ 992 protected void appendDetail(final StringBuffer buffer, final String fieldName, final long[] array) { 993 buffer.append(arrayStart); 994 for (int i = 0; i < array.length; i++) { 995 if (i > 0) { 996 buffer.append(arraySeparator); 997 } 998 appendDetail(buffer, fieldName, array[i]); 999 } 1000 buffer.append(arrayEnd); 1001 } 1002 1003 /** 1004 * <p>Append to the <code>toString</code> a summary of a 1005 * <code>long</code> array.</p> 1006 * 1007 * @param buffer the <code>StringBuffer</code> to populate 1008 * @param fieldName the field name, typically not used as already appended 1009 * @param array the array to add to the <code>toString</code>, 1010 * not <code>null</code> 1011 */ 1012 protected void appendSummary(final StringBuffer buffer, final String fieldName, final long[] array) { 1013 appendSummarySize(buffer, fieldName, array.length); 1014 } 1015 1016 //---------------------------------------------------------------------------- 1017 1018 /** 1019 * <p>Append to the <code>toString</code> an <code>int</code> 1020 * array.</p> 1021 * 1022 * @param buffer the <code>StringBuffer</code> to populate 1023 * @param fieldName the field name 1024 * @param array the array to add to the <code>toString</code> 1025 * @param fullDetail <code>true</code> for detail, <code>false</code> 1026 * for summary info, <code>null</code> for style decides 1027 */ 1028 public void append(final StringBuffer buffer, final String fieldName, final int[] array, final Boolean fullDetail) { 1029 appendFieldStart(buffer, fieldName); 1030 1031 if (array == null) { 1032 appendNullText(buffer, fieldName); 1033 1034 } else if (isFullDetail(fullDetail)) { 1035 appendDetail(buffer, fieldName, array); 1036 1037 } else { 1038 appendSummary(buffer, fieldName, array); 1039 } 1040 1041 appendFieldEnd(buffer, fieldName); 1042 } 1043 1044 /** 1045 * <p>Append to the <code>toString</code> the detail of an 1046 * <code>int</code> array.</p> 1047 * 1048 * @param buffer the <code>StringBuffer</code> to populate 1049 * @param fieldName the field name, typically not used as already appended 1050 * @param array the array to add to the <code>toString</code>, 1051 * not <code>null</code> 1052 */ 1053 protected void appendDetail(final StringBuffer buffer, final String fieldName, final int[] array) { 1054 buffer.append(arrayStart); 1055 for (int i = 0; i < array.length; i++) { 1056 if (i > 0) { 1057 buffer.append(arraySeparator); 1058 } 1059 appendDetail(buffer, fieldName, array[i]); 1060 } 1061 buffer.append(arrayEnd); 1062 } 1063 1064 /** 1065 * <p>Append to the <code>toString</code> a summary of an 1066 * <code>int</code> array.</p> 1067 * 1068 * @param buffer the <code>StringBuffer</code> to populate 1069 * @param fieldName the field name, typically not used as already appended 1070 * @param array the array to add to the <code>toString</code>, 1071 * not <code>null</code> 1072 */ 1073 protected void appendSummary(final StringBuffer buffer, final String fieldName, final int[] array) { 1074 appendSummarySize(buffer, fieldName, array.length); 1075 } 1076 1077 //---------------------------------------------------------------------------- 1078 1079 /** 1080 * <p>Append to the <code>toString</code> a <code>short</code> 1081 * array.</p> 1082 * 1083 * @param buffer the <code>StringBuffer</code> to populate 1084 * @param fieldName the field name 1085 * @param array the array to add to the <code>toString</code> 1086 * @param fullDetail <code>true</code> for detail, <code>false</code> 1087 * for summary info, <code>null</code> for style decides 1088 */ 1089 public void append(final StringBuffer buffer, final String fieldName, final short[] array, final Boolean fullDetail) { 1090 appendFieldStart(buffer, fieldName); 1091 1092 if (array == null) { 1093 appendNullText(buffer, fieldName); 1094 1095 } else if (isFullDetail(fullDetail)) { 1096 appendDetail(buffer, fieldName, array); 1097 1098 } else { 1099 appendSummary(buffer, fieldName, array); 1100 } 1101 1102 appendFieldEnd(buffer, fieldName); 1103 } 1104 1105 /** 1106 * <p>Append to the <code>toString</code> the detail of a 1107 * <code>short</code> array.</p> 1108 * 1109 * @param buffer the <code>StringBuffer</code> to populate 1110 * @param fieldName the field name, typically not used as already appended 1111 * @param array the array to add to the <code>toString</code>, 1112 * not <code>null</code> 1113 */ 1114 protected void appendDetail(final StringBuffer buffer, final String fieldName, final short[] array) { 1115 buffer.append(arrayStart); 1116 for (int i = 0; i < array.length; i++) { 1117 if (i > 0) { 1118 buffer.append(arraySeparator); 1119 } 1120 appendDetail(buffer, fieldName, array[i]); 1121 } 1122 buffer.append(arrayEnd); 1123 } 1124 1125 /** 1126 * <p>Append to the <code>toString</code> a summary of a 1127 * <code>short</code> array.</p> 1128 * 1129 * @param buffer the <code>StringBuffer</code> to populate 1130 * @param fieldName the field name, typically not used as already appended 1131 * @param array the array to add to the <code>toString</code>, 1132 * not <code>null</code> 1133 */ 1134 protected void appendSummary(final StringBuffer buffer, final String fieldName, final short[] array) { 1135 appendSummarySize(buffer, fieldName, array.length); 1136 } 1137 1138 //---------------------------------------------------------------------------- 1139 1140 /** 1141 * <p>Append to the <code>toString</code> a <code>byte</code> 1142 * array.</p> 1143 * 1144 * @param buffer the <code>StringBuffer</code> to populate 1145 * @param fieldName the field name 1146 * @param array the array to add to the <code>toString</code> 1147 * @param fullDetail <code>true</code> for detail, <code>false</code> 1148 * for summary info, <code>null</code> for style decides 1149 */ 1150 public void append(final StringBuffer buffer, final String fieldName, final byte[] array, final Boolean fullDetail) { 1151 appendFieldStart(buffer, fieldName); 1152 1153 if (array == null) { 1154 appendNullText(buffer, fieldName); 1155 1156 } else if (isFullDetail(fullDetail)) { 1157 appendDetail(buffer, fieldName, array); 1158 1159 } else { 1160 appendSummary(buffer, fieldName, array); 1161 } 1162 1163 appendFieldEnd(buffer, fieldName); 1164 } 1165 1166 /** 1167 * <p>Append to the <code>toString</code> the detail of a 1168 * <code>byte</code> array.</p> 1169 * 1170 * @param buffer the <code>StringBuffer</code> to populate 1171 * @param fieldName the field name, typically not used as already appended 1172 * @param array the array to add to the <code>toString</code>, 1173 * not <code>null</code> 1174 */ 1175 protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte[] array) { 1176 buffer.append(arrayStart); 1177 for (int i = 0; i < array.length; i++) { 1178 if (i > 0) { 1179 buffer.append(arraySeparator); 1180 } 1181 appendDetail(buffer, fieldName, array[i]); 1182 } 1183 buffer.append(arrayEnd); 1184 } 1185 1186 /** 1187 * <p>Append to the <code>toString</code> a summary of a 1188 * <code>byte</code> array.</p> 1189 * 1190 * @param buffer the <code>StringBuffer</code> to populate 1191 * @param fieldName the field name, typically not used as already appended 1192 * @param array the array to add to the <code>toString</code>, 1193 * not <code>null</code> 1194 */ 1195 protected void appendSummary(final StringBuffer buffer, final String fieldName, final byte[] array) { 1196 appendSummarySize(buffer, fieldName, array.length); 1197 } 1198 1199 //---------------------------------------------------------------------------- 1200 1201 /** 1202 * <p>Append to the <code>toString</code> a <code>char</code> 1203 * array.</p> 1204 * 1205 * @param buffer the <code>StringBuffer</code> to populate 1206 * @param fieldName the field name 1207 * @param array the array to add to the <code>toString</code> 1208 * @param fullDetail <code>true</code> for detail, <code>false</code> 1209 * for summary info, <code>null</code> for style decides 1210 */ 1211 public void append(final StringBuffer buffer, final String fieldName, final char[] array, final Boolean fullDetail) { 1212 appendFieldStart(buffer, fieldName); 1213 1214 if (array == null) { 1215 appendNullText(buffer, fieldName); 1216 1217 } else if (isFullDetail(fullDetail)) { 1218 appendDetail(buffer, fieldName, array); 1219 1220 } else { 1221 appendSummary(buffer, fieldName, array); 1222 } 1223 1224 appendFieldEnd(buffer, fieldName); 1225 } 1226 1227 /** 1228 * <p>Append to the <code>toString</code> the detail of a 1229 * <code>char</code> array.</p> 1230 * 1231 * @param buffer the <code>StringBuffer</code> to populate 1232 * @param fieldName the field name, typically not used as already appended 1233 * @param array the array to add to the <code>toString</code>, 1234 * not <code>null</code> 1235 */ 1236 protected void appendDetail(final StringBuffer buffer, final String fieldName, final char[] array) { 1237 buffer.append(arrayStart); 1238 for (int i = 0; i < array.length; i++) { 1239 if (i > 0) { 1240 buffer.append(arraySeparator); 1241 } 1242 appendDetail(buffer, fieldName, array[i]); 1243 } 1244 buffer.append(arrayEnd); 1245 } 1246 1247 /** 1248 * <p>Append to the <code>toString</code> a summary of a 1249 * <code>char</code> array.</p> 1250 * 1251 * @param buffer the <code>StringBuffer</code> to populate 1252 * @param fieldName the field name, typically not used as already appended 1253 * @param array the array to add to the <code>toString</code>, 1254 * not <code>null</code> 1255 */ 1256 protected void appendSummary(final StringBuffer buffer, final String fieldName, final char[] array) { 1257 appendSummarySize(buffer, fieldName, array.length); 1258 } 1259 1260 //---------------------------------------------------------------------------- 1261 1262 /** 1263 * <p>Append to the <code>toString</code> a <code>double</code> 1264 * array.</p> 1265 * 1266 * @param buffer the <code>StringBuffer</code> to populate 1267 * @param fieldName the field name 1268 * @param array the array to add to the toString 1269 * @param fullDetail <code>true</code> for detail, <code>false</code> 1270 * for summary info, <code>null</code> for style decides 1271 */ 1272 public void append(final StringBuffer buffer, final String fieldName, final double[] array, final Boolean fullDetail) { 1273 appendFieldStart(buffer, fieldName); 1274 1275 if (array == null) { 1276 appendNullText(buffer, fieldName); 1277 1278 } else if (isFullDetail(fullDetail)) { 1279 appendDetail(buffer, fieldName, array); 1280 1281 } else { 1282 appendSummary(buffer, fieldName, array); 1283 } 1284 1285 appendFieldEnd(buffer, fieldName); 1286 } 1287 1288 /** 1289 * <p>Append to the <code>toString</code> the detail of a 1290 * <code>double</code> array.</p> 1291 * 1292 * @param buffer the <code>StringBuffer</code> to populate 1293 * @param fieldName the field name, typically not used as already appended 1294 * @param array the array to add to the <code>toString</code>, 1295 * not <code>null</code> 1296 */ 1297 protected void appendDetail(final StringBuffer buffer, final String fieldName, final double[] array) { 1298 buffer.append(arrayStart); 1299 for (int i = 0; i < array.length; i++) { 1300 if (i > 0) { 1301 buffer.append(arraySeparator); 1302 } 1303 appendDetail(buffer, fieldName, array[i]); 1304 } 1305 buffer.append(arrayEnd); 1306 } 1307 1308 /** 1309 * <p>Append to the <code>toString</code> a summary of a 1310 * <code>double</code> array.</p> 1311 * 1312 * @param buffer the <code>StringBuffer</code> to populate 1313 * @param fieldName the field name, typically not used as already appended 1314 * @param array the array to add to the <code>toString</code>, 1315 * not <code>null</code> 1316 */ 1317 protected void appendSummary(final StringBuffer buffer, final String fieldName, final double[] array) { 1318 appendSummarySize(buffer, fieldName, array.length); 1319 } 1320 1321 //---------------------------------------------------------------------------- 1322 1323 /** 1324 * <p>Append to the <code>toString</code> a <code>float</code> 1325 * array.</p> 1326 * 1327 * @param buffer the <code>StringBuffer</code> to populate 1328 * @param fieldName the field name 1329 * @param array the array to add to the toString 1330 * @param fullDetail <code>true</code> for detail, <code>false</code> 1331 * for summary info, <code>null</code> for style decides 1332 */ 1333 public void append(final StringBuffer buffer, final String fieldName, final float[] array, final Boolean fullDetail) { 1334 appendFieldStart(buffer, fieldName); 1335 1336 if (array == null) { 1337 appendNullText(buffer, fieldName); 1338 1339 } else if (isFullDetail(fullDetail)) { 1340 appendDetail(buffer, fieldName, array); 1341 1342 } else { 1343 appendSummary(buffer, fieldName, array); 1344 } 1345 1346 appendFieldEnd(buffer, fieldName); 1347 } 1348 1349 /** 1350 * <p>Append to the <code>toString</code> the detail of a 1351 * <code>float</code> array.</p> 1352 * 1353 * @param buffer the <code>StringBuffer</code> to populate 1354 * @param fieldName the field name, typically not used as already appended 1355 * @param array the array to add to the <code>toString</code>, 1356 * not <code>null</code> 1357 */ 1358 protected void appendDetail(final StringBuffer buffer, final String fieldName, final float[] array) { 1359 buffer.append(arrayStart); 1360 for (int i = 0; i < array.length; i++) { 1361 if (i > 0) { 1362 buffer.append(arraySeparator); 1363 } 1364 appendDetail(buffer, fieldName, array[i]); 1365 } 1366 buffer.append(arrayEnd); 1367 } 1368 1369 /** 1370 * <p>Append to the <code>toString</code> a summary of a 1371 * <code>float</code> array.</p> 1372 * 1373 * @param buffer the <code>StringBuffer</code> to populate 1374 * @param fieldName the field name, typically not used as already appended 1375 * @param array the array to add to the <code>toString</code>, 1376 * not <code>null</code> 1377 */ 1378 protected void appendSummary(final StringBuffer buffer, final String fieldName, final float[] array) { 1379 appendSummarySize(buffer, fieldName, array.length); 1380 } 1381 1382 //---------------------------------------------------------------------------- 1383 1384 /** 1385 * <p>Append to the <code>toString</code> a <code>boolean</code> 1386 * array.</p> 1387 * 1388 * @param buffer the <code>StringBuffer</code> to populate 1389 * @param fieldName the field name 1390 * @param array the array to add to the toString 1391 * @param fullDetail <code>true</code> for detail, <code>false</code> 1392 * for summary info, <code>null</code> for style decides 1393 */ 1394 public void append(final StringBuffer buffer, final String fieldName, final boolean[] array, final Boolean fullDetail) { 1395 appendFieldStart(buffer, fieldName); 1396 1397 if (array == null) { 1398 appendNullText(buffer, fieldName); 1399 1400 } else if (isFullDetail(fullDetail)) { 1401 appendDetail(buffer, fieldName, array); 1402 1403 } else { 1404 appendSummary(buffer, fieldName, array); 1405 } 1406 1407 appendFieldEnd(buffer, fieldName); 1408 } 1409 1410 /** 1411 * <p>Append to the <code>toString</code> the detail of a 1412 * <code>boolean</code> array.</p> 1413 * 1414 * @param buffer the <code>StringBuffer</code> to populate 1415 * @param fieldName the field name, typically not used as already appended 1416 * @param array the array to add to the <code>toString</code>, 1417 * not <code>null</code> 1418 */ 1419 protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean[] array) { 1420 buffer.append(arrayStart); 1421 for (int i = 0; i < array.length; i++) { 1422 if (i > 0) { 1423 buffer.append(arraySeparator); 1424 } 1425 appendDetail(buffer, fieldName, array[i]); 1426 } 1427 buffer.append(arrayEnd); 1428 } 1429 1430 /** 1431 * <p>Append to the <code>toString</code> a summary of a 1432 * <code>boolean</code> array.</p> 1433 * 1434 * @param buffer the <code>StringBuffer</code> to populate 1435 * @param fieldName the field name, typically not used as already appended 1436 * @param array the array to add to the <code>toString</code>, 1437 * not <code>null</code> 1438 */ 1439 protected void appendSummary(final StringBuffer buffer, final String fieldName, final boolean[] array) { 1440 appendSummarySize(buffer, fieldName, array.length); 1441 } 1442 1443 //---------------------------------------------------------------------------- 1444 1445 /** 1446 * <p>Append to the <code>toString</code> the class name.</p> 1447 * 1448 * @param buffer the <code>StringBuffer</code> to populate 1449 * @param object the <code>Object</code> whose name to output 1450 */ 1451 protected void appendClassName(final StringBuffer buffer, final Object object) { 1452 if (useClassName && object != null) { 1453 register(object); 1454 if (useShortClassName) { 1455 buffer.append(getShortClassName(object.getClass())); 1456 } else { 1457 buffer.append(object.getClass().getName()); 1458 } 1459 } 1460 } 1461 1462 /** 1463 * <p>Append the {@link System#identityHashCode(java.lang.Object)}.</p> 1464 * 1465 * @param buffer the <code>StringBuffer</code> to populate 1466 * @param object the <code>Object</code> whose id to output 1467 */ 1468 protected void appendIdentityHashCode(final StringBuffer buffer, final Object object) { 1469 if (this.isUseIdentityHashCode() && object!=null) { 1470 register(object); 1471 buffer.append('@'); 1472 buffer.append(Integer.toHexString(System.identityHashCode(object))); 1473 } 1474 } 1475 1476 /** 1477 * <p>Append to the <code>toString</code> the content start.</p> 1478 * 1479 * @param buffer the <code>StringBuffer</code> to populate 1480 */ 1481 protected void appendContentStart(final StringBuffer buffer) { 1482 buffer.append(contentStart); 1483 } 1484 1485 /** 1486 * <p>Append to the <code>toString</code> the content end.</p> 1487 * 1488 * @param buffer the <code>StringBuffer</code> to populate 1489 */ 1490 protected void appendContentEnd(final StringBuffer buffer) { 1491 buffer.append(contentEnd); 1492 } 1493 1494 /** 1495 * <p>Append to the <code>toString</code> an indicator for <code>null</code>.</p> 1496 * 1497 * <p>The default indicator is <code>'<null>'</code>.</p> 1498 * 1499 * @param buffer the <code>StringBuffer</code> to populate 1500 * @param fieldName the field name, typically not used as already appended 1501 */ 1502 protected void appendNullText(final StringBuffer buffer, final String fieldName) { 1503 buffer.append(nullText); 1504 } 1505 1506 /** 1507 * <p>Append to the <code>toString</code> the field separator.</p> 1508 * 1509 * @param buffer the <code>StringBuffer</code> to populate 1510 */ 1511 protected void appendFieldSeparator(final StringBuffer buffer) { 1512 buffer.append(fieldSeparator); 1513 } 1514 1515 /** 1516 * <p>Append to the <code>toString</code> the field start.</p> 1517 * 1518 * @param buffer the <code>StringBuffer</code> to populate 1519 * @param fieldName the field name 1520 */ 1521 protected void appendFieldStart(final StringBuffer buffer, final String fieldName) { 1522 if (useFieldNames && fieldName != null) { 1523 buffer.append(fieldName); 1524 buffer.append(fieldNameValueSeparator); 1525 } 1526 } 1527 1528 /** 1529 * <p>Append to the <code>toString<code> the field end.</p> 1530 * 1531 * @param buffer the <code>StringBuffer</code> to populate 1532 * @param fieldName the field name, typically not used as already appended 1533 */ 1534 protected void appendFieldEnd(final StringBuffer buffer, final String fieldName) { 1535 appendFieldSeparator(buffer); 1536 } 1537 1538 /** 1539 * <p>Append to the <code>toString</code> a size summary.</p> 1540 * 1541 * <p>The size summary is used to summarize the contents of 1542 * <code>Collections</code>, <code>Maps</code> and arrays.</p> 1543 * 1544 * <p>The output consists of a prefix, the passed in size 1545 * and a suffix.</p> 1546 * 1547 * <p>The default format is <code>'<size=n>'<code>.</p> 1548 * 1549 * @param buffer the <code>StringBuffer</code> to populate 1550 * @param fieldName the field name, typically not used as already appended 1551 * @param size the size to append 1552 */ 1553 protected void appendSummarySize(final StringBuffer buffer, final String fieldName, final int size) { 1554 buffer.append(sizeStartText); 1555 buffer.append(size); 1556 buffer.append(sizeEndText); 1557 } 1558 1559 /** 1560 * <p>Is this field to be output in full detail.</p> 1561 * 1562 * <p>This method converts a detail request into a detail level. 1563 * The calling code may request full detail (<code>true</code>), 1564 * but a subclass might ignore that and always return 1565 * <code>false</code>. The calling code may pass in 1566 * <code>null</code> indicating that it doesn't care about 1567 * the detail level. In this case the default detail level is 1568 * used.</p> 1569 * 1570 * @param fullDetailRequest the detail level requested 1571 * @return whether full detail is to be shown 1572 */ 1573 protected boolean isFullDetail(final Boolean fullDetailRequest) { 1574 if (fullDetailRequest == null) { 1575 return defaultFullDetail; 1576 } 1577 return fullDetailRequest.booleanValue(); 1578 } 1579 1580 /** 1581 * <p>Gets the short class name for a class.</p> 1582 * 1583 * <p>The short class name is the classname excluding 1584 * the package name.</p> 1585 * 1586 * @param cls the <code>Class</code> to get the short name of 1587 * @return the short name 1588 */ 1589 protected String getShortClassName(final Class<?> cls) { 1590 return ClassUtils.getShortClassName(cls); 1591 } 1592 1593 // Setters and getters for the customizable parts of the style 1594 // These methods are not expected to be overridden, except to make public 1595 // (They are not public so that immutable subclasses can be written) 1596 //--------------------------------------------------------------------- 1597 1598 /** 1599 * <p>Gets whether to use the class name.</p> 1600 * 1601 * @return the current useClassName flag 1602 */ 1603 protected boolean isUseClassName() { 1604 return useClassName; 1605 } 1606 1607 /** 1608 * <p>Sets whether to use the class name.</p> 1609 * 1610 * @param useClassName the new useClassName flag 1611 */ 1612 protected void setUseClassName(final boolean useClassName) { 1613 this.useClassName = useClassName; 1614 } 1615 1616 //--------------------------------------------------------------------- 1617 1618 /** 1619 * <p>Gets whether to output short or long class names.</p> 1620 * 1621 * @return the current useShortClassName flag 1622 * @since 2.0 1623 */ 1624 protected boolean isUseShortClassName() { 1625 return useShortClassName; 1626 } 1627 1628 /** 1629 * <p>Sets whether to output short or long class names.</p> 1630 * 1631 * @param useShortClassName the new useShortClassName flag 1632 * @since 2.0 1633 */ 1634 protected void setUseShortClassName(final boolean useShortClassName) { 1635 this.useShortClassName = useShortClassName; 1636 } 1637 1638 //--------------------------------------------------------------------- 1639 1640 /** 1641 * <p>Gets whether to use the identity hash code.</p> 1642 * 1643 * @return the current useIdentityHashCode flag 1644 */ 1645 protected boolean isUseIdentityHashCode() { 1646 return useIdentityHashCode; 1647 } 1648 1649 /** 1650 * <p>Sets whether to use the identity hash code.</p> 1651 * 1652 * @param useIdentityHashCode the new useIdentityHashCode flag 1653 */ 1654 protected void setUseIdentityHashCode(final boolean useIdentityHashCode) { 1655 this.useIdentityHashCode = useIdentityHashCode; 1656 } 1657 1658 //--------------------------------------------------------------------- 1659 1660 /** 1661 * <p>Gets whether to use the field names passed in.</p> 1662 * 1663 * @return the current useFieldNames flag 1664 */ 1665 protected boolean isUseFieldNames() { 1666 return useFieldNames; 1667 } 1668 1669 /** 1670 * <p>Sets whether to use the field names passed in.</p> 1671 * 1672 * @param useFieldNames the new useFieldNames flag 1673 */ 1674 protected void setUseFieldNames(final boolean useFieldNames) { 1675 this.useFieldNames = useFieldNames; 1676 } 1677 1678 //--------------------------------------------------------------------- 1679 1680 /** 1681 * <p>Gets whether to use full detail when the caller doesn't 1682 * specify.</p> 1683 * 1684 * @return the current defaultFullDetail flag 1685 */ 1686 protected boolean isDefaultFullDetail() { 1687 return defaultFullDetail; 1688 } 1689 1690 /** 1691 * <p>Sets whether to use full detail when the caller doesn't 1692 * specify.</p> 1693 * 1694 * @param defaultFullDetail the new defaultFullDetail flag 1695 */ 1696 protected void setDefaultFullDetail(final boolean defaultFullDetail) { 1697 this.defaultFullDetail = defaultFullDetail; 1698 } 1699 1700 //--------------------------------------------------------------------- 1701 1702 /** 1703 * <p>Gets whether to output array content detail.</p> 1704 * 1705 * @return the current array content detail setting 1706 */ 1707 protected boolean isArrayContentDetail() { 1708 return arrayContentDetail; 1709 } 1710 1711 /** 1712 * <p>Sets whether to output array content detail.</p> 1713 * 1714 * @param arrayContentDetail the new arrayContentDetail flag 1715 */ 1716 protected void setArrayContentDetail(final boolean arrayContentDetail) { 1717 this.arrayContentDetail = arrayContentDetail; 1718 } 1719 1720 //--------------------------------------------------------------------- 1721 1722 /** 1723 * <p>Gets the array start text.</p> 1724 * 1725 * @return the current array start text 1726 */ 1727 protected String getArrayStart() { 1728 return arrayStart; 1729 } 1730 1731 /** 1732 * <p>Sets the array start text.</p> 1733 * 1734 * <p><code>null</code> is accepted, but will be converted to 1735 * an empty String.</p> 1736 * 1737 * @param arrayStart the new array start text 1738 */ 1739 protected void setArrayStart(String arrayStart) { 1740 if (arrayStart == null) { 1741 arrayStart = ""; 1742 } 1743 this.arrayStart = arrayStart; 1744 } 1745 1746 //--------------------------------------------------------------------- 1747 1748 /** 1749 * <p>Gets the array end text.</p> 1750 * 1751 * @return the current array end text 1752 */ 1753 protected String getArrayEnd() { 1754 return arrayEnd; 1755 } 1756 1757 /** 1758 * <p>Sets the array end text.</p> 1759 * 1760 * <p><code>null</code> is accepted, but will be converted to 1761 * an empty String.</p> 1762 * 1763 * @param arrayEnd the new array end text 1764 */ 1765 protected void setArrayEnd(String arrayEnd) { 1766 if (arrayEnd == null) { 1767 arrayEnd = ""; 1768 } 1769 this.arrayEnd = arrayEnd; 1770 } 1771 1772 //--------------------------------------------------------------------- 1773 1774 /** 1775 * <p>Gets the array separator text.</p> 1776 * 1777 * @return the current array separator text 1778 */ 1779 protected String getArraySeparator() { 1780 return arraySeparator; 1781 } 1782 1783 /** 1784 * <p>Sets the array separator text.</p> 1785 * 1786 * <p><code>null</code> is accepted, but will be converted to 1787 * an empty String.</p> 1788 * 1789 * @param arraySeparator the new array separator text 1790 */ 1791 protected void setArraySeparator(String arraySeparator) { 1792 if (arraySeparator == null) { 1793 arraySeparator = ""; 1794 } 1795 this.arraySeparator = arraySeparator; 1796 } 1797 1798 //--------------------------------------------------------------------- 1799 1800 /** 1801 * <p>Gets the content start text.</p> 1802 * 1803 * @return the current content start text 1804 */ 1805 protected String getContentStart() { 1806 return contentStart; 1807 } 1808 1809 /** 1810 * <p>Sets the content start text.</p> 1811 * 1812 * <p><code>null</code> is accepted, but will be converted to 1813 * an empty String.</p> 1814 * 1815 * @param contentStart the new content start text 1816 */ 1817 protected void setContentStart(String contentStart) { 1818 if (contentStart == null) { 1819 contentStart = ""; 1820 } 1821 this.contentStart = contentStart; 1822 } 1823 1824 //--------------------------------------------------------------------- 1825 1826 /** 1827 * <p>Gets the content end text.</p> 1828 * 1829 * @return the current content end text 1830 */ 1831 protected String getContentEnd() { 1832 return contentEnd; 1833 } 1834 1835 /** 1836 * <p>Sets the content end text.</p> 1837 * 1838 * <p><code>null</code> is accepted, but will be converted to 1839 * an empty String.</p> 1840 * 1841 * @param contentEnd the new content end text 1842 */ 1843 protected void setContentEnd(String contentEnd) { 1844 if (contentEnd == null) { 1845 contentEnd = ""; 1846 } 1847 this.contentEnd = contentEnd; 1848 } 1849 1850 //--------------------------------------------------------------------- 1851 1852 /** 1853 * <p>Gets the field name value separator text.</p> 1854 * 1855 * @return the current field name value separator text 1856 */ 1857 protected String getFieldNameValueSeparator() { 1858 return fieldNameValueSeparator; 1859 } 1860 1861 /** 1862 * <p>Sets the field name value separator text.</p> 1863 * 1864 * <p><code>null</code> is accepted, but will be converted to 1865 * an empty String.</p> 1866 * 1867 * @param fieldNameValueSeparator the new field name value separator text 1868 */ 1869 protected void setFieldNameValueSeparator(String fieldNameValueSeparator) { 1870 if (fieldNameValueSeparator == null) { 1871 fieldNameValueSeparator = ""; 1872 } 1873 this.fieldNameValueSeparator = fieldNameValueSeparator; 1874 } 1875 1876 //--------------------------------------------------------------------- 1877 1878 /** 1879 * <p>Gets the field separator text.</p> 1880 * 1881 * @return the current field separator text 1882 */ 1883 protected String getFieldSeparator() { 1884 return fieldSeparator; 1885 } 1886 1887 /** 1888 * <p>Sets the field separator text.</p> 1889 * 1890 * <p><code>null</code> is accepted, but will be converted to 1891 * an empty String.</p> 1892 * 1893 * @param fieldSeparator the new field separator text 1894 */ 1895 protected void setFieldSeparator(String fieldSeparator) { 1896 if (fieldSeparator == null) { 1897 fieldSeparator = ""; 1898 } 1899 this.fieldSeparator = fieldSeparator; 1900 } 1901 1902 //--------------------------------------------------------------------- 1903 1904 /** 1905 * <p>Gets whether the field separator should be added at the start 1906 * of each buffer.</p> 1907 * 1908 * @return the fieldSeparatorAtStart flag 1909 * @since 2.0 1910 */ 1911 protected boolean isFieldSeparatorAtStart() { 1912 return fieldSeparatorAtStart; 1913 } 1914 1915 /** 1916 * <p>Sets whether the field separator should be added at the start 1917 * of each buffer.</p> 1918 * 1919 * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag 1920 * @since 2.0 1921 */ 1922 protected void setFieldSeparatorAtStart(final boolean fieldSeparatorAtStart) { 1923 this.fieldSeparatorAtStart = fieldSeparatorAtStart; 1924 } 1925 1926 //--------------------------------------------------------------------- 1927 1928 /** 1929 * <p>Gets whether the field separator should be added at the end 1930 * of each buffer.</p> 1931 * 1932 * @return fieldSeparatorAtEnd flag 1933 * @since 2.0 1934 */ 1935 protected boolean isFieldSeparatorAtEnd() { 1936 return fieldSeparatorAtEnd; 1937 } 1938 1939 /** 1940 * <p>Sets whether the field separator should be added at the end 1941 * of each buffer.</p> 1942 * 1943 * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag 1944 * @since 2.0 1945 */ 1946 protected void setFieldSeparatorAtEnd(final boolean fieldSeparatorAtEnd) { 1947 this.fieldSeparatorAtEnd = fieldSeparatorAtEnd; 1948 } 1949 1950 //--------------------------------------------------------------------- 1951 1952 /** 1953 * <p>Gets the text to output when <code>null</code> found.</p> 1954 * 1955 * @return the current text to output when null found 1956 */ 1957 protected String getNullText() { 1958 return nullText; 1959 } 1960 1961 /** 1962 * <p>Sets the text to output when <code>null</code> found.</p> 1963 * 1964 * <p><code>null</code> is accepted, but will be converted to 1965 * an empty String.</p> 1966 * 1967 * @param nullText the new text to output when null found 1968 */ 1969 protected void setNullText(String nullText) { 1970 if (nullText == null) { 1971 nullText = ""; 1972 } 1973 this.nullText = nullText; 1974 } 1975 1976 //--------------------------------------------------------------------- 1977 1978 /** 1979 * <p>Gets the start text to output when a <code>Collection</code>, 1980 * <code>Map</code> or array size is output.</p> 1981 * 1982 * <p>This is output before the size value.</p> 1983 * 1984 * @return the current start of size text 1985 */ 1986 protected String getSizeStartText() { 1987 return sizeStartText; 1988 } 1989 1990 /** 1991 * <p>Sets the start text to output when a <code>Collection</code>, 1992 * <code>Map</code> or array size is output.</p> 1993 * 1994 * <p>This is output before the size value.</p> 1995 * 1996 * <p><code>null</code> is accepted, but will be converted to 1997 * an empty String.</p> 1998 * 1999 * @param sizeStartText the new start of size text 2000 */ 2001 protected void setSizeStartText(String sizeStartText) { 2002 if (sizeStartText == null) { 2003 sizeStartText = ""; 2004 } 2005 this.sizeStartText = sizeStartText; 2006 } 2007 2008 //--------------------------------------------------------------------- 2009 2010 /** 2011 * <p>Gets the end text to output when a <code>Collection</code>, 2012 * <code>Map</code> or array size is output.</p> 2013 * 2014 * <p>This is output after the size value.</p> 2015 * 2016 * @return the current end of size text 2017 */ 2018 protected String getSizeEndText() { 2019 return sizeEndText; 2020 } 2021 2022 /** 2023 * <p>Sets the end text to output when a <code>Collection</code>, 2024 * <code>Map</code> or array size is output.</p> 2025 * 2026 * <p>This is output after the size value.</p> 2027 * 2028 * <p><code>null</code> is accepted, but will be converted to 2029 * an empty String.</p> 2030 * 2031 * @param sizeEndText the new end of size text 2032 */ 2033 protected void setSizeEndText(String sizeEndText) { 2034 if (sizeEndText == null) { 2035 sizeEndText = ""; 2036 } 2037 this.sizeEndText = sizeEndText; 2038 } 2039 2040 //--------------------------------------------------------------------- 2041 2042 /** 2043 * <p>Gets the start text to output when an <code>Object</code> is 2044 * output in summary mode.</p> 2045 * 2046 * <p>This is output before the size value.</p> 2047 * 2048 * @return the current start of summary text 2049 */ 2050 protected String getSummaryObjectStartText() { 2051 return summaryObjectStartText; 2052 } 2053 2054 /** 2055 * <p>Sets the start text to output when an <code>Object</code> is 2056 * output in summary mode.</p> 2057 * 2058 * <p>This is output before the size value.</p> 2059 * 2060 * <p><code>null</code> is accepted, but will be converted to 2061 * an empty String.</p> 2062 * 2063 * @param summaryObjectStartText the new start of summary text 2064 */ 2065 protected void setSummaryObjectStartText(String summaryObjectStartText) { 2066 if (summaryObjectStartText == null) { 2067 summaryObjectStartText = ""; 2068 } 2069 this.summaryObjectStartText = summaryObjectStartText; 2070 } 2071 2072 //--------------------------------------------------------------------- 2073 2074 /** 2075 * <p>Gets the end text to output when an <code>Object</code> is 2076 * output in summary mode.</p> 2077 * 2078 * <p>This is output after the size value.</p> 2079 * 2080 * @return the current end of summary text 2081 */ 2082 protected String getSummaryObjectEndText() { 2083 return summaryObjectEndText; 2084 } 2085 2086 /** 2087 * <p>Sets the end text to output when an <code>Object</code> is 2088 * output in summary mode.</p> 2089 * 2090 * <p>This is output after the size value.</p> 2091 * 2092 * <p><code>null</code> is accepted, but will be converted to 2093 * an empty String.</p> 2094 * 2095 * @param summaryObjectEndText the new end of summary text 2096 */ 2097 protected void setSummaryObjectEndText(String summaryObjectEndText) { 2098 if (summaryObjectEndText == null) { 2099 summaryObjectEndText = ""; 2100 } 2101 this.summaryObjectEndText = summaryObjectEndText; 2102 } 2103 2104 //---------------------------------------------------------------------------- 2105 2106 /** 2107 * <p>Default <code>ToStringStyle</code>.</p> 2108 * 2109 * <p>This is an inner class rather than using 2110 * <code>StandardToStringStyle</code> to ensure its immutability.</p> 2111 */ 2112 private static final class DefaultToStringStyle extends ToStringStyle { 2113 2114 /** 2115 * Required for serialization support. 2116 * 2117 * @see java.io.Serializable 2118 */ 2119 private static final long serialVersionUID = 1L; 2120 2121 /** 2122 * <p>Constructor.</p> 2123 * 2124 * <p>Use the static constant rather than instantiating.</p> 2125 */ 2126 DefaultToStringStyle() { 2127 super(); 2128 } 2129 2130 /** 2131 * <p>Ensure <code>Singleton</code> after serialization.</p> 2132 * 2133 * @return the singleton 2134 */ 2135 private Object readResolve() { 2136 return ToStringStyle.DEFAULT_STYLE; 2137 } 2138 2139 } 2140 2141 //---------------------------------------------------------------------------- 2142 2143 /** 2144 * <p><code>ToStringStyle</code> that does not print out 2145 * the field names.</p> 2146 * 2147 * <p>This is an inner class rather than using 2148 * <code>StandardToStringStyle</code> to ensure its immutability. 2149 */ 2150 private static final class NoFieldNameToStringStyle extends ToStringStyle { 2151 2152 private static final long serialVersionUID = 1L; 2153 2154 /** 2155 * <p>Constructor.</p> 2156 * 2157 * <p>Use the static constant rather than instantiating.</p> 2158 */ 2159 NoFieldNameToStringStyle() { 2160 super(); 2161 this.setUseFieldNames(false); 2162 } 2163 2164 /** 2165 * <p>Ensure <code>Singleton</code> after serialization.</p> 2166 * 2167 * @return the singleton 2168 */ 2169 private Object readResolve() { 2170 return ToStringStyle.NO_FIELD_NAMES_STYLE; 2171 } 2172 2173 } 2174 2175 //---------------------------------------------------------------------------- 2176 2177 /** 2178 * <p><code>ToStringStyle</code> that prints out the short 2179 * class name and no identity hashcode.</p> 2180 * 2181 * <p>This is an inner class rather than using 2182 * <code>StandardToStringStyle</code> to ensure its immutability.</p> 2183 */ 2184 private static final class ShortPrefixToStringStyle extends ToStringStyle { 2185 2186 private static final long serialVersionUID = 1L; 2187 2188 /** 2189 * <p>Constructor.</p> 2190 * 2191 * <p>Use the static constant rather than instantiating.</p> 2192 */ 2193 ShortPrefixToStringStyle() { 2194 super(); 2195 this.setUseShortClassName(true); 2196 this.setUseIdentityHashCode(false); 2197 } 2198 2199 /** 2200 * <p>Ensure <code>Singleton</ode> after serialization.</p> 2201 * @return the singleton 2202 */ 2203 private Object readResolve() { 2204 return ToStringStyle.SHORT_PREFIX_STYLE; 2205 } 2206 2207 } 2208 2209 //---------------------------------------------------------------------------- 2210 2211 /** 2212 * <p><code>ToStringStyle</code> that does not print out the 2213 * classname, identity hashcode, content start or field name.</p> 2214 * 2215 * <p>This is an inner class rather than using 2216 * <code>StandardToStringStyle</code> to ensure its immutability.</p> 2217 */ 2218 private static final class SimpleToStringStyle extends ToStringStyle { 2219 2220 private static final long serialVersionUID = 1L; 2221 2222 /** 2223 * <p>Constructor.</p> 2224 * 2225 * <p>Use the static constant rather than instantiating.</p> 2226 */ 2227 SimpleToStringStyle() { 2228 super(); 2229 this.setUseClassName(false); 2230 this.setUseIdentityHashCode(false); 2231 this.setUseFieldNames(false); 2232 this.setContentStart(""); 2233 this.setContentEnd(""); 2234 } 2235 2236 /** 2237 * <p>Ensure <code>Singleton</ode> after serialization.</p> 2238 * @return the singleton 2239 */ 2240 private Object readResolve() { 2241 return ToStringStyle.SIMPLE_STYLE; 2242 } 2243 2244 } 2245 2246 //---------------------------------------------------------------------------- 2247 2248 /** 2249 * <p><code>ToStringStyle</code> that outputs on multiple lines.</p> 2250 * 2251 * <p>This is an inner class rather than using 2252 * <code>StandardToStringStyle</code> to ensure its immutability.</p> 2253 */ 2254 private static final class MultiLineToStringStyle extends ToStringStyle { 2255 2256 private static final long serialVersionUID = 1L; 2257 2258 /** 2259 * <p>Constructor.</p> 2260 * 2261 * <p>Use the static constant rather than instantiating.</p> 2262 */ 2263 MultiLineToStringStyle() { 2264 super(); 2265 this.setContentStart("["); 2266 this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + " "); 2267 this.setFieldSeparatorAtStart(true); 2268 this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]"); 2269 } 2270 2271 /** 2272 * <p>Ensure <code>Singleton</code> after serialization.</p> 2273 * 2274 * @return the singleton 2275 */ 2276 private Object readResolve() { 2277 return ToStringStyle.MULTI_LINE_STYLE; 2278 } 2279 2280 } 2281 2282}