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