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