001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.shared.ldap.util;
021    
022    
023    import java.io.Serializable;
024    import java.lang.reflect.Array;
025    import java.util.Collection;
026    import java.util.Map;
027    
028    
029    /**
030     * <p>
031     * Controls <code>String</code> formatting for {@link ToStringBuilder}. The
032     * main public interface is always via <code>ToStringBuilder</code>.
033     * </p>
034     * <p>
035     * These classes are intended to be used as <code>Singletons</code>. There is
036     * no need to instantiate a new style each time. A program will generally use
037     * one of the predefined constants on this class. Alternatively, the
038     * class can be used to set the individual settings. Thus most styles can be
039     * achieved without subclassing.
040     * </p>
041     * <p>
042     * If required, a subclass can override as many or as few of the methods as it
043     * requires. Each object type (from <code>boolean</code> to <code>long</code>
044     * to <code>Object</code> to <code>int[]</code>) has its own methods to
045     * output it. Most have two versions, detail and summary.
046     * <p>
047     * For example, the detail version of the array based methods will output the
048     * whole array, whereas the summary method will just output the array length.
049     * </p>
050     * 
051     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
052     */
053    public abstract class ToStringStyle implements Serializable
054    {
055    
056        static final long serialVersionUID = -3594451267200535036L;
057    
058        /**
059         * The default toString style.
060         */
061        public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
062    
063        /**
064         * The multi line toString style.
065         */
066        public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
067    
068        /**
069         * The no field names toString style.
070         */
071        public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
072    
073        /**
074         * The short prefix toString style.
075         */
076        public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
077    
078        /**
079         * The simple toString style.
080         */
081        public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
082    
083        /**
084         * Whether to use the field names, the default is <code>true</code>.
085         */
086        private boolean useFieldNames = true;
087    
088        /**
089         * Whether to use the class name, the default is <code>true</code>.
090         */
091        private boolean useClassName = true;
092    
093        /**
094         * Whether to use short class names, the default is <code>false</code>.
095         */
096        private boolean useShortClassName = false;
097    
098        /**
099         * Whether to use the identity hash code, the default is <code>true</code>.
100         */
101        private boolean useIdentityHashCode = true;
102    
103        /**
104         * The content start <code>'['</code>.
105         */
106        private String contentStart = "[";
107    
108        /**
109         * The content end <code>']'</code>.
110         */
111        private String contentEnd = "]";
112    
113        /**
114         * The field name value separator <code>'='</code>.
115         */
116        private String fieldNameValueSeparator = "=";
117    
118        /**
119         * Whether the field separator should be added before any other fields.
120         */
121        private boolean fieldSeparatorAtStart = false;
122    
123        /**
124         * Whether the field separator should be added after any other fields.
125         */
126        private boolean fieldSeparatorAtEnd = false;
127    
128        /**
129         * The field separator <code>','</code>.
130         */
131        private String fieldSeparator = ",";
132    
133        /**
134         * The array start <code>'{'</code>.
135         */
136        private String arrayStart = "{";
137    
138        /**
139         * The array separator <code>','</code>.
140         */
141        private String arraySeparator = ",";
142    
143        /**
144         * The detail for array content.
145         */
146        private boolean arrayContentDetail = true;
147    
148        /**
149         * The array end <code>'}'</code>.
150         */
151        private String arrayEnd = "}";
152    
153        /**
154         * The value to use when fullDetail is <code>null</code>, the default
155         * value is <code>true</code>.
156         */
157        private boolean defaultFullDetail = true;
158    
159        /**
160         * The <code>null</code> text <code>'&lt;null&gt;'</code>.
161         */
162        private String nullText = "<null>";
163    
164        /**
165         * The summary size text start <code>'<size'</code>.
166         */
167        private String sizeStartText = "<size=";
168    
169        /**
170         * The summary size text start <code>'&gt;'</code>.
171         */
172        private String sizeEndText = ">";
173    
174        /**
175         * The summary object text start <code>'&lt;'</code>.
176         */
177        private String summaryObjectStartText = "<";
178    
179        /**
180         * The summary object text start <code>'&gt;'</code>.
181         */
182        private String summaryObjectEndText = ">";
183    
184    
185        // ----------------------------------------------------------------------------
186    
187        /**
188         * <p>
189         * Constructor.
190         * </p>
191         */
192        protected ToStringStyle()
193        {
194            super();
195        }
196    
197    
198        // ----------------------------------------------------------------------------
199    
200        /**
201         * <p>
202         * Append to the <code>toString</code> the superclass toString.
203         * </p>
204         * <p>
205         * A <code>null</code> <code>superToString</code> is ignored.
206         * </p>
207         * 
208         * @param buffer
209         *            the <code>StringBuffer</code> to populate
210         * @param superToString
211         *            the <code>super.toString()</code>
212         * @since 2.0
213         */
214        public void appendSuper( StringBuffer buffer, String superToString )
215        {
216            appendToString( buffer, superToString );
217        }
218    
219    
220        /**
221         * <p>
222         * Append to the <code>toString</code> another toString.
223         * </p>
224         * <p>
225         * A <code>null</code> <code>toString</code> is ignored.
226         * </p>
227         * 
228         * @param buffer
229         *            the <code>StringBuffer</code> to populate
230         * @param toString
231         *            the additional <code>toString</code>
232         * @since 2.0
233         */
234        public void appendToString( StringBuffer buffer, String toString )
235        {
236            if ( toString != null )
237            {
238                int pos1 = toString.indexOf( contentStart ) + contentStart.length();
239                int pos2 = toString.lastIndexOf( contentEnd );
240                if ( pos1 != pos2 && pos1 >= 0 && pos2 >= 0 )
241                {
242                    String data = toString.substring( pos1, pos2 );
243                    if ( fieldSeparatorAtStart )
244                    {
245                        removeLastFieldSeparator( buffer );
246                    }
247                    buffer.append( data );
248                    appendFieldSeparator( buffer );
249                }
250            }
251        }
252    
253    
254        /**
255         * <p>
256         * Append to the <code>toString</code> the start of data indicator.
257         * </p>
258         * 
259         * @param buffer
260         *            the <code>StringBuffer</code> to populate
261         * @param object
262         *            the <code>Object</code> to build a <code>toString</code>
263         *            for
264         */
265        public void appendStart( StringBuffer buffer, Object object )
266        {
267            if ( object != null )
268            {
269                appendClassName( buffer, object );
270                appendIdentityHashCode( buffer, object );
271                appendContentStart( buffer );
272                if ( fieldSeparatorAtStart )
273                {
274                    appendFieldSeparator( buffer );
275                }
276            }
277        }
278    
279    
280        /**
281         * <p>
282         * Append to the <code>toString</code> the end of data indicator.
283         * </p>
284         * 
285         * @param buffer
286         *            the <code>StringBuffer</code> to populate
287         * @param object
288         *            the <code>Object</code> to build a <code>toString</code>
289         *            for.
290         */
291        public void appendEnd( StringBuffer buffer, Object object )
292        {
293            if ( this.fieldSeparatorAtEnd == false )
294            {
295                removeLastFieldSeparator( buffer );
296            }
297            appendContentEnd( buffer );
298        }
299    
300    
301        /**
302         * <p>
303         * Remove the last field separator from the buffer.
304         * </p>
305         * 
306         * @param buffer
307         *            the <code>StringBuffer</code> to populate
308         * @since 2.0
309         */
310        protected void removeLastFieldSeparator( StringBuffer buffer )
311        {
312            int len = buffer.length();
313            int sepLen = fieldSeparator.length();
314            if ( len > 0 && sepLen > 0 && len >= sepLen )
315            {
316                boolean match = true;
317                for ( int i = 0; i < sepLen; i++ )
318                {
319                    if ( buffer.charAt( len - 1 - i ) != fieldSeparator.charAt( sepLen - 1 - i ) )
320                    {
321                        match = false;
322                        break;
323                    }
324                }
325                if ( match )
326                {
327                    buffer.setLength( len - sepLen );
328                }
329            }
330        }
331    
332    
333        // ----------------------------------------------------------------------------
334    
335        /**
336         * <p>
337         * Append to the <code>toString</code> an <code>Object</code> value,
338         * printing the full <code>toString</code> of the <code>Object</code>
339         * passed in.
340         * </p>
341         * 
342         * @param buffer
343         *            the <code>StringBuffer</code> to populate
344         * @param fieldName
345         *            the field name
346         * @param value
347         *            the value to add to the <code>toString</code>
348         * @param fullDetail
349         *            <code>true</code> for detail, <code>false</code> for
350         *            summary info, <code>null</code> for style decides
351         */
352        public void append( StringBuffer buffer, String fieldName, Object value, Boolean fullDetail )
353        {
354            appendFieldStart( buffer, fieldName );
355    
356            if ( value == null )
357            {
358                appendNullText( buffer, fieldName );
359    
360            }
361            else
362            {
363                appendInternal( buffer, fieldName, value, isFullDetail( fullDetail ) );
364            }
365    
366            appendFieldEnd( buffer, fieldName );
367        }
368    
369    
370        /**
371         * <p>
372         * Append to the <code>toString</code> an <code>Object</code>,
373         * correctly interpreting its type.
374         * </p>
375         * <p>
376         * This method performs the main lookup by Class type to correctly route
377         * arrays, <code>Collections</code>, <code>Maps</code> and
378         * <code>Objects</code> to the appropriate method.
379         * </p>
380         * <p>
381         * Either detail or summary views can be specified.
382         * </p>
383         * <p>
384         * If a cycle is detected, an object will be appended with the
385         * <code>Object.toString()</code> format.
386         * </p>
387         * 
388         * @param buffer
389         *            the <code>StringBuffer</code> to populate
390         * @param fieldName
391         *            the field name, typically not used as already appended
392         * @param value
393         *            the value to add to the <code>toString</code>, not
394         *            <code>null</code>
395         * @param detail
396         *            output detail or not
397         */
398        protected void appendInternal( StringBuffer buffer, String fieldName, Object value, boolean detail )
399        {
400            if ( ReflectionToStringBuilder.isRegistered( value )
401                && !( value instanceof Number || value instanceof Boolean || value instanceof Character ) )
402            {
403                ObjectUtils.appendIdentityToString( buffer, value );
404    
405            }
406            else if ( value instanceof Collection )
407            {
408                if ( detail )
409                {
410                    appendDetail( buffer, fieldName, ( Collection ) value );
411                }
412                else
413                {
414                    appendSummarySize( buffer, fieldName, ( ( Collection ) value ).size() );
415                }
416    
417            }
418            else if ( value instanceof Map )
419            {
420                if ( detail )
421                {
422                    appendDetail( buffer, fieldName, ( Map ) value );
423                }
424                else
425                {
426                    appendSummarySize( buffer, fieldName, ( ( Map ) value ).size() );
427                }
428    
429            }
430            else if ( value instanceof long[] )
431            {
432                if ( detail )
433                {
434                    appendDetail( buffer, fieldName, ( long[] ) value );
435                }
436                else
437                {
438                    appendSummary( buffer, fieldName, ( long[] ) value );
439                }
440    
441            }
442            else if ( value instanceof int[] )
443            {
444                if ( detail )
445                {
446                    appendDetail( buffer, fieldName, ( int[] ) value );
447                }
448                else
449                {
450                    appendSummary( buffer, fieldName, ( int[] ) value );
451                }
452    
453            }
454            else if ( value instanceof short[] )
455            {
456                if ( detail )
457                {
458                    appendDetail( buffer, fieldName, ( short[] ) value );
459                }
460                else
461                {
462                    appendSummary( buffer, fieldName, ( short[] ) value );
463                }
464    
465            }
466            else if ( value instanceof byte[] )
467            {
468                if ( detail )
469                {
470                    appendDetail( buffer, fieldName, ( byte[] ) value );
471                }
472                else
473                {
474                    appendSummary( buffer, fieldName, ( byte[] ) value );
475                }
476    
477            }
478            else if ( value instanceof char[] )
479            {
480                if ( detail )
481                {
482                    appendDetail( buffer, fieldName, ( char[] ) value );
483                }
484                else
485                {
486                    appendSummary( buffer, fieldName, ( char[] ) value );
487                }
488    
489            }
490            else if ( value instanceof double[] )
491            {
492                if ( detail )
493                {
494                    appendDetail( buffer, fieldName, ( double[] ) value );
495                }
496                else
497                {
498                    appendSummary( buffer, fieldName, ( double[] ) value );
499                }
500    
501            }
502            else if ( value instanceof float[] )
503            {
504                if ( detail )
505                {
506                    appendDetail( buffer, fieldName, ( float[] ) value );
507                }
508                else
509                {
510                    appendSummary( buffer, fieldName, ( float[] ) value );
511                }
512    
513            }
514            else if ( value instanceof boolean[] )
515            {
516                if ( detail )
517                {
518                    appendDetail( buffer, fieldName, ( boolean[] ) value );
519                }
520                else
521                {
522                    appendSummary( buffer, fieldName, ( boolean[] ) value );
523                }
524    
525            }
526            else if ( value.getClass().isArray() )
527            {
528                if ( detail )
529                {
530                    appendDetail( buffer, fieldName, ( Object[] ) value );
531                }
532                else
533                {
534                    appendSummary( buffer, fieldName, ( Object[] ) value );
535                }
536    
537            }
538            else
539            {
540                if ( detail )
541                {
542                    appendDetail( buffer, fieldName, value );
543                }
544                else
545                {
546                    appendSummary( buffer, fieldName, value );
547                }
548            }
549        }
550    
551    
552        /**
553         * <p>
554         * Append to the <code>toString</code> an <code>Object</code> value,
555         * printing the full detail of the <code>Object</code>.
556         * </p>
557         * 
558         * @param buffer
559         *            the <code>StringBuffer</code> to populate
560         * @param fieldName
561         *            the field name, typically not used as already appended
562         * @param value
563         *            the value to add to the <code>toString</code>, not
564         *            <code>null</code>
565         */
566        protected void appendDetail( StringBuffer buffer, String fieldName, Object value )
567        {
568            buffer.append( value );
569        }
570    
571    
572        /**
573         * <p>
574         * Append to the <code>toString</code> a <code>Collection</code>.
575         * </p>
576         * 
577         * @param buffer
578         *            the <code>StringBuffer</code> to populate
579         * @param fieldName
580         *            the field name, typically not used as already appended
581         * @param coll
582         *            the <code>Collection</code> to add to the
583         *            <code>toString</code>, not <code>null</code>
584         */
585        protected void appendDetail( StringBuffer buffer, String fieldName, Collection coll )
586        {
587            buffer.append( coll );
588        }
589    
590    
591        /**
592         * <p>
593         * Append to the <code>toString</code> a <code>Map<code>.</p>
594         *
595         * @param buffer  the <code>StringBuffer</code> to populate
596         * @param fieldName  the field name, typically not used as already appended
597         * @param map  the <code>Map</code> to add to the <code>toString</code>,
598         *  not <code>null</code>
599         */
600        protected void appendDetail( StringBuffer buffer, String fieldName, Map map )
601        {
602            buffer.append( map );
603        }
604    
605    
606        /**
607         * <p>
608         * Append to the <code>toString</code> an <code>Object</code> value,
609         * printing a summary of the <code>Object</code>.
610         * </P>
611         * 
612         * @param buffer
613         *            the <code>StringBuffer</code> to populate
614         * @param fieldName
615         *            the field name, typically not used as already appended
616         * @param value
617         *            the value to add to the <code>toString</code>, not
618         *            <code>null</code>
619         */
620        protected void appendSummary( StringBuffer buffer, String fieldName, Object value )
621        {
622            buffer.append( summaryObjectStartText );
623            buffer.append( getShortClassName( value.getClass() ) );
624            buffer.append( summaryObjectEndText );
625        }
626    
627    
628        // ----------------------------------------------------------------------------
629    
630        /**
631         * <p>
632         * Append to the <code>toString</code> a <code>long</code> value.
633         * </p>
634         * 
635         * @param buffer
636         *            the <code>StringBuffer</code> to populate
637         * @param fieldName
638         *            the field name
639         * @param value
640         *            the value to add to the <code>toString</code>
641         */
642        public void append( StringBuffer buffer, String fieldName, long value )
643        {
644            appendFieldStart( buffer, fieldName );
645            appendDetail( buffer, fieldName, value );
646            appendFieldEnd( buffer, fieldName );
647        }
648    
649    
650        /**
651         * <p>
652         * Append to the <code>toString</code> a <code>long</code> value.
653         * </p>
654         * 
655         * @param buffer
656         *            the <code>StringBuffer</code> to populate
657         * @param fieldName
658         *            the field name, typically not used as already appended
659         * @param value
660         *            the value to add to the <code>toString</code>
661         */
662        protected void appendDetail( StringBuffer buffer, String fieldName, long value )
663        {
664            buffer.append( value );
665        }
666    
667    
668        // ----------------------------------------------------------------------------
669    
670        /**
671         * <p>
672         * Append to the <code>toString</code> an <code>int</code> value.
673         * </p>
674         * 
675         * @param buffer
676         *            the <code>StringBuffer</code> to populate
677         * @param fieldName
678         *            the field name
679         * @param value
680         *            the value to add to the <code>toString</code>
681         */
682        public void append( StringBuffer buffer, String fieldName, int value )
683        {
684            appendFieldStart( buffer, fieldName );
685            appendDetail( buffer, fieldName, value );
686            appendFieldEnd( buffer, fieldName );
687        }
688    
689    
690        /**
691         * <p>
692         * Append to the <code>toString</code> an <code>int</code> value.
693         * </p>
694         * 
695         * @param buffer
696         *            the <code>StringBuffer</code> to populate
697         * @param fieldName
698         *            the field name, typically not used as already appended
699         * @param value
700         *            the value to add to the <code>toString</code>
701         */
702        protected void appendDetail( StringBuffer buffer, String fieldName, int value )
703        {
704            buffer.append( value );
705        }
706    
707    
708        // ----------------------------------------------------------------------------
709    
710        /**
711         * <p>
712         * Append to the <code>toString</code> a <code>short</code> value.
713         * </p>
714         * 
715         * @param buffer
716         *            the <code>StringBuffer</code> to populate
717         * @param fieldName
718         *            the field name
719         * @param value
720         *            the value to add to the <code>toString</code>
721         */
722        public void append( StringBuffer buffer, String fieldName, short value )
723        {
724            appendFieldStart( buffer, fieldName );
725            appendDetail( buffer, fieldName, value );
726            appendFieldEnd( buffer, fieldName );
727        }
728    
729    
730        /**
731         * <p>
732         * Append to the <code>toString</code> a <code>short</code> value.
733         * </p>
734         * 
735         * @param buffer
736         *            the <code>StringBuffer</code> to populate
737         * @param fieldName
738         *            the field name, typically not used as already appended
739         * @param value
740         *            the value to add to the <code>toString</code>
741         */
742        protected void appendDetail( StringBuffer buffer, String fieldName, short value )
743        {
744            buffer.append( value );
745        }
746    
747    
748        // ----------------------------------------------------------------------------
749    
750        /**
751         * <p>
752         * Append to the <code>toString</code> a <code>byte</code> value.
753         * </p>
754         * 
755         * @param buffer
756         *            the <code>StringBuffer</code> to populate
757         * @param fieldName
758         *            the field name
759         * @param value
760         *            the value to add to the <code>toString</code>
761         */
762        public void append( StringBuffer buffer, String fieldName, byte value )
763        {
764            appendFieldStart( buffer, fieldName );
765            appendDetail( buffer, fieldName, value );
766            appendFieldEnd( buffer, fieldName );
767        }
768    
769    
770        /**
771         * <p>
772         * Append to the <code>toString</code> a <code>byte</code> value.
773         * </p>
774         * 
775         * @param buffer
776         *            the <code>StringBuffer</code> to populate
777         * @param fieldName
778         *            the field name, typically not used as already appended
779         * @param value
780         *            the value to add to the <code>toString</code>
781         */
782        protected void appendDetail( StringBuffer buffer, String fieldName, byte value )
783        {
784            buffer.append( value );
785        }
786    
787    
788        // ----------------------------------------------------------------------------
789    
790        /**
791         * <p>
792         * Append to the <code>toString</code> a <code>char</code> value.
793         * </p>
794         * 
795         * @param buffer
796         *            the <code>StringBuffer</code> to populate
797         * @param fieldName
798         *            the field name
799         * @param value
800         *            the value to add to the <code>toString</code>
801         */
802        public void append( StringBuffer buffer, String fieldName, char value )
803        {
804            appendFieldStart( buffer, fieldName );
805            appendDetail( buffer, fieldName, value );
806            appendFieldEnd( buffer, fieldName );
807        }
808    
809    
810        /**
811         * <p>
812         * Append to the <code>toString</code> a <code>char</code> value.
813         * </p>
814         * 
815         * @param buffer
816         *            the <code>StringBuffer</code> to populate
817         * @param fieldName
818         *            the field name, typically not used as already appended
819         * @param value
820         *            the value to add to the <code>toString</code>
821         */
822        protected void appendDetail( StringBuffer buffer, String fieldName, char value )
823        {
824            buffer.append( value );
825        }
826    
827    
828        // ----------------------------------------------------------------------------
829    
830        /**
831         * <p>
832         * Append to the <code>toString</code> a <code>double</code> value.
833         * </p>
834         * 
835         * @param buffer
836         *            the <code>StringBuffer</code> to populate
837         * @param fieldName
838         *            the field name
839         * @param value
840         *            the value to add to the <code>toString</code>
841         */
842        public void append( StringBuffer buffer, String fieldName, double value )
843        {
844            appendFieldStart( buffer, fieldName );
845            appendDetail( buffer, fieldName, value );
846            appendFieldEnd( buffer, fieldName );
847        }
848    
849    
850        /**
851         * <p>
852         * Append to the <code>toString</code> a <code>double</code> value.
853         * </p>
854         * 
855         * @param buffer
856         *            the <code>StringBuffer</code> to populate
857         * @param fieldName
858         *            the field name, typically not used as already appended
859         * @param value
860         *            the value to add to the <code>toString</code>
861         */
862        protected void appendDetail( StringBuffer buffer, String fieldName, double value )
863        {
864            buffer.append( value );
865        }
866    
867    
868        // ----------------------------------------------------------------------------
869    
870        /**
871         * <p>
872         * Append to the <code>toString</code> a <code>float</code> value.
873         * </p>
874         * 
875         * @param buffer
876         *            the <code>StringBuffer</code> to populate
877         * @param fieldName
878         *            the field name
879         * @param value
880         *            the value to add to the <code>toString</code>
881         */
882        public void append( StringBuffer buffer, String fieldName, float value )
883        {
884            appendFieldStart( buffer, fieldName );
885            appendDetail( buffer, fieldName, value );
886            appendFieldEnd( buffer, fieldName );
887        }
888    
889    
890        /**
891         * <p>
892         * Append to the <code>toString</code> a <code>float</code> value.
893         * </p>
894         * 
895         * @param buffer
896         *            the <code>StringBuffer</code> to populate
897         * @param fieldName
898         *            the field name, typically not used as already appended
899         * @param value
900         *            the value to add to the <code>toString</code>
901         */
902        protected void appendDetail( StringBuffer buffer, String fieldName, float value )
903        {
904            buffer.append( value );
905        }
906    
907    
908        // ----------------------------------------------------------------------------
909    
910        /**
911         * <p>
912         * Append to the <code>toString</code> a <code>boolean</code> value.
913         * </p>
914         * 
915         * @param buffer
916         *            the <code>StringBuffer</code> to populate
917         * @param fieldName
918         *            the field name
919         * @param value
920         *            the value to add to the <code>toString</code>
921         */
922        public void append( StringBuffer buffer, String fieldName, boolean value )
923        {
924            appendFieldStart( buffer, fieldName );
925            appendDetail( buffer, fieldName, value );
926            appendFieldEnd( buffer, fieldName );
927        }
928    
929    
930        /**
931         * <p>
932         * Append to the <code>toString</code> a <code>boolean</code> value.
933         * </p>
934         * 
935         * @param buffer
936         *            the <code>StringBuffer</code> to populate
937         * @param fieldName
938         *            the field name, typically not used as already appended
939         * @param value
940         *            the value to add to the <code>toString</code>
941         */
942        protected void appendDetail( StringBuffer buffer, String fieldName, boolean value )
943        {
944            buffer.append( value );
945        }
946    
947    
948        /**
949         * <p>
950         * Append to the <code>toString</code> an <code>Object</code> array.
951         * </p>
952         * 
953         * @param buffer
954         *            the <code>StringBuffer</code> to populate
955         * @param fieldName
956         *            the field name
957         * @param array
958         *            the array to add to the toString
959         * @param fullDetail
960         *            <code>true</code> for detail, <code>false</code> for
961         *            summary info, <code>null</code> for style decides
962         */
963        public void append( StringBuffer buffer, String fieldName, Object[] array, Boolean fullDetail )
964        {
965            appendFieldStart( buffer, fieldName );
966    
967            if ( array == null )
968            {
969                appendNullText( buffer, fieldName );
970    
971            }
972            else if ( isFullDetail( fullDetail ) )
973            {
974                appendDetail( buffer, fieldName, array );
975    
976            }
977            else
978            {
979                appendSummary( buffer, fieldName, array );
980            }
981    
982            appendFieldEnd( buffer, fieldName );
983        }
984    
985    
986        // ----------------------------------------------------------------------------
987    
988        /**
989         * <p>
990         * Append to the <code>toString</code> the detail of an
991         * <code>Object</code> array.
992         * </p>
993         * 
994         * @param buffer
995         *            the <code>StringBuffer</code> to populate
996         * @param fieldName
997         *            the field name, typically not used as already appended
998         * @param array
999         *            the array to add to the <code>toString</code>, not
1000         *            <code>null</code>
1001         */
1002        protected void appendDetail( StringBuffer buffer, String fieldName, Object[] array )
1003        {
1004            buffer.append( arrayStart );
1005            for ( int i = 0; i < array.length; i++ )
1006            {
1007                Object item = array[i];
1008                if ( i > 0 )
1009                {
1010                    buffer.append( arraySeparator );
1011                }
1012                if ( item == null )
1013                {
1014                    appendNullText( buffer, fieldName );
1015    
1016                }
1017                else
1018                {
1019                    appendInternal( buffer, fieldName, item, arrayContentDetail );
1020                }
1021            }
1022            buffer.append( arrayEnd );
1023        }
1024    
1025    
1026        /**
1027         * <p>
1028         * Append to the <code>toString</code> the detail of an array type.
1029         * </p>
1030         * 
1031         * @param buffer
1032         *            the <code>StringBuffer</code> to populate
1033         * @param fieldName
1034         *            the field name, typically not used as already appended
1035         * @param array
1036         *            the array to add to the <code>toString</code>, not
1037         *            <code>null</code>
1038         * @since 2.0
1039         */
1040        protected void reflectionAppendArrayDetail( StringBuffer buffer, String fieldName, Object array )
1041        {
1042            buffer.append( arrayStart );
1043            int length = Array.getLength( array );
1044            for ( int i = 0; i < length; i++ )
1045            {
1046                Object item = Array.get( array, i );
1047                if ( i > 0 )
1048                {
1049                    buffer.append( arraySeparator );
1050                }
1051                if ( item == null )
1052                {
1053                    appendNullText( buffer, fieldName );
1054    
1055                }
1056                else
1057                {
1058                    appendInternal( buffer, fieldName, item, arrayContentDetail );
1059                }
1060            }
1061            buffer.append( arrayEnd );
1062        }
1063    
1064    
1065        /**
1066         * <p>
1067         * Append to the <code>toString</code> a summary of an <code>Object</code>
1068         * array.
1069         * </p>
1070         * 
1071         * @param buffer
1072         *            the <code>StringBuffer</code> to populate
1073         * @param fieldName
1074         *            the field name, typically not used as already appended
1075         * @param array
1076         *            the array to add to the <code>toString</code>, not
1077         *            <code>null</code>
1078         */
1079        protected void appendSummary( StringBuffer buffer, String fieldName, Object[] array )
1080        {
1081            appendSummarySize( buffer, fieldName, array.length );
1082        }
1083    
1084    
1085        // ----------------------------------------------------------------------------
1086    
1087        /**
1088         * <p>
1089         * Append to the <code>toString</code> a <code>long</code> array.
1090         * </p>
1091         * 
1092         * @param buffer
1093         *            the <code>StringBuffer</code> to populate
1094         * @param fieldName
1095         *            the field name
1096         * @param array
1097         *            the array to add to the <code>toString</code>
1098         * @param fullDetail
1099         *            <code>true</code> for detail, <code>false</code> for
1100         *            summary info, <code>null</code> for style decides
1101         */
1102        public void append( StringBuffer buffer, String fieldName, long[] array, Boolean fullDetail )
1103        {
1104            appendFieldStart( buffer, fieldName );
1105    
1106            if ( array == null )
1107            {
1108                appendNullText( buffer, fieldName );
1109    
1110            }
1111            else if ( isFullDetail( fullDetail ) )
1112            {
1113                appendDetail( buffer, fieldName, array );
1114    
1115            }
1116            else
1117            {
1118                appendSummary( buffer, fieldName, array );
1119            }
1120    
1121            appendFieldEnd( buffer, fieldName );
1122        }
1123    
1124    
1125        /**
1126         * <p>
1127         * Append to the <code>toString</code> the detail of a <code>long</code>
1128         * array.
1129         * </p>
1130         * 
1131         * @param buffer
1132         *            the <code>StringBuffer</code> to populate
1133         * @param fieldName
1134         *            the field name, typically not used as already appended
1135         * @param array
1136         *            the array to add to the <code>toString</code>, not
1137         *            <code>null</code>
1138         */
1139        protected void appendDetail( StringBuffer buffer, String fieldName, long[] array )
1140        {
1141            buffer.append( arrayStart );
1142            for ( int i = 0; i < array.length; i++ )
1143            {
1144                if ( i > 0 )
1145                {
1146                    buffer.append( arraySeparator );
1147                }
1148                appendDetail( buffer, fieldName, array[i] );
1149            }
1150            buffer.append( arrayEnd );
1151        }
1152    
1153    
1154        /**
1155         * <p>
1156         * Append to the <code>toString</code> a summary of a <code>long</code>
1157         * array.
1158         * </p>
1159         * 
1160         * @param buffer
1161         *            the <code>StringBuffer</code> to populate
1162         * @param fieldName
1163         *            the field name, typically not used as already appended
1164         * @param array
1165         *            the array to add to the <code>toString</code>, not
1166         *            <code>null</code>
1167         */
1168        protected void appendSummary( StringBuffer buffer, String fieldName, long[] array )
1169        {
1170            appendSummarySize( buffer, fieldName, array.length );
1171        }
1172    
1173    
1174        // ----------------------------------------------------------------------------
1175    
1176        /**
1177         * <p>
1178         * Append to the <code>toString</code> an <code>int</code> array.
1179         * </p>
1180         * 
1181         * @param buffer
1182         *            the <code>StringBuffer</code> to populate
1183         * @param fieldName
1184         *            the field name
1185         * @param array
1186         *            the array to add to the <code>toString</code>
1187         * @param fullDetail
1188         *            <code>true</code> for detail, <code>false</code> for
1189         *            summary info, <code>null</code> for style decides
1190         */
1191        public void append( StringBuffer buffer, String fieldName, int[] array, Boolean fullDetail )
1192        {
1193            appendFieldStart( buffer, fieldName );
1194    
1195            if ( array == null )
1196            {
1197                appendNullText( buffer, fieldName );
1198    
1199            }
1200            else if ( isFullDetail( fullDetail ) )
1201            {
1202                appendDetail( buffer, fieldName, array );
1203    
1204            }
1205            else
1206            {
1207                appendSummary( buffer, fieldName, array );
1208            }
1209    
1210            appendFieldEnd( buffer, fieldName );
1211        }
1212    
1213    
1214        /**
1215         * <p>
1216         * Append to the <code>toString</code> the detail of an <code>int</code>
1217         * array.
1218         * </p>
1219         * 
1220         * @param buffer
1221         *            the <code>StringBuffer</code> to populate
1222         * @param fieldName
1223         *            the field name, typically not used as already appended
1224         * @param array
1225         *            the array to add to the <code>toString</code>, not
1226         *            <code>null</code>
1227         */
1228        protected void appendDetail( StringBuffer buffer, String fieldName, int[] array )
1229        {
1230            buffer.append( arrayStart );
1231            for ( int i = 0; i < array.length; i++ )
1232            {
1233                if ( i > 0 )
1234                {
1235                    buffer.append( arraySeparator );
1236                }
1237                appendDetail( buffer, fieldName, array[i] );
1238            }
1239            buffer.append( arrayEnd );
1240        }
1241    
1242    
1243        /**
1244         * <p>
1245         * Append to the <code>toString</code> a summary of an <code>int</code>
1246         * array.
1247         * </p>
1248         * 
1249         * @param buffer
1250         *            the <code>StringBuffer</code> to populate
1251         * @param fieldName
1252         *            the field name, typically not used as already appended
1253         * @param array
1254         *            the array to add to the <code>toString</code>, not
1255         *            <code>null</code>
1256         */
1257        protected void appendSummary( StringBuffer buffer, String fieldName, int[] array )
1258        {
1259            appendSummarySize( buffer, fieldName, array.length );
1260        }
1261    
1262    
1263        // ----------------------------------------------------------------------------
1264    
1265        /**
1266         * <p>
1267         * Append to the <code>toString</code> a <code>short</code> array.
1268         * </p>
1269         * 
1270         * @param buffer
1271         *            the <code>StringBuffer</code> to populate
1272         * @param fieldName
1273         *            the field name
1274         * @param array
1275         *            the array to add to the <code>toString</code>
1276         * @param fullDetail
1277         *            <code>true</code> for detail, <code>false</code> for
1278         *            summary info, <code>null</code> for style decides
1279         */
1280        public void append( StringBuffer buffer, String fieldName, short[] array, Boolean fullDetail )
1281        {
1282            appendFieldStart( buffer, fieldName );
1283    
1284            if ( array == null )
1285            {
1286                appendNullText( buffer, fieldName );
1287    
1288            }
1289            else if ( isFullDetail( fullDetail ) )
1290            {
1291                appendDetail( buffer, fieldName, array );
1292    
1293            }
1294            else
1295            {
1296                appendSummary( buffer, fieldName, array );
1297            }
1298    
1299            appendFieldEnd( buffer, fieldName );
1300        }
1301    
1302    
1303        /**
1304         * <p>
1305         * Append to the <code>toString</code> the detail of a <code>short</code>
1306         * array.
1307         * </p>
1308         * 
1309         * @param buffer
1310         *            the <code>StringBuffer</code> to populate
1311         * @param fieldName
1312         *            the field name, typically not used as already appended
1313         * @param array
1314         *            the array to add to the <code>toString</code>, not
1315         *            <code>null</code>
1316         */
1317        protected void appendDetail( StringBuffer buffer, String fieldName, short[] array )
1318        {
1319            buffer.append( arrayStart );
1320            for ( int i = 0; i < array.length; i++ )
1321            {
1322                if ( i > 0 )
1323                {
1324                    buffer.append( arraySeparator );
1325                }
1326                appendDetail( buffer, fieldName, array[i] );
1327            }
1328            buffer.append( arrayEnd );
1329        }
1330    
1331    
1332        /**
1333         * <p>
1334         * Append to the <code>toString</code> a summary of a <code>short</code>
1335         * array.
1336         * </p>
1337         * 
1338         * @param buffer
1339         *            the <code>StringBuffer</code> to populate
1340         * @param fieldName
1341         *            the field name, typically not used as already appended
1342         * @param array
1343         *            the array to add to the <code>toString</code>, not
1344         *            <code>null</code>
1345         */
1346        protected void appendSummary( StringBuffer buffer, String fieldName, short[] array )
1347        {
1348            appendSummarySize( buffer, fieldName, array.length );
1349        }
1350    
1351    
1352        // ----------------------------------------------------------------------------
1353    
1354        /**
1355         * <p>
1356         * Append to the <code>toString</code> a <code>byte</code> array.
1357         * </p>
1358         * 
1359         * @param buffer
1360         *            the <code>StringBuffer</code> to populate
1361         * @param fieldName
1362         *            the field name
1363         * @param array
1364         *            the array to add to the <code>toString</code>
1365         * @param fullDetail
1366         *            <code>true</code> for detail, <code>false</code> for
1367         *            summary info, <code>null</code> for style decides
1368         */
1369        public void append( StringBuffer buffer, String fieldName, byte[] array, Boolean fullDetail )
1370        {
1371            appendFieldStart( buffer, fieldName );
1372    
1373            if ( array == null )
1374            {
1375                appendNullText( buffer, fieldName );
1376    
1377            }
1378            else if ( isFullDetail( fullDetail ) )
1379            {
1380                appendDetail( buffer, fieldName, array );
1381    
1382            }
1383            else
1384            {
1385                appendSummary( buffer, fieldName, array );
1386            }
1387    
1388            appendFieldEnd( buffer, fieldName );
1389        }
1390    
1391    
1392        /**
1393         * <p>
1394         * Append to the <code>toString</code> the detail of a <code>byte</code>
1395         * array.
1396         * </p>
1397         * 
1398         * @param buffer
1399         *            the <code>StringBuffer</code> to populate
1400         * @param fieldName
1401         *            the field name, typically not used as already appended
1402         * @param array
1403         *            the array to add to the <code>toString</code>, not
1404         *            <code>null</code>
1405         */
1406        protected void appendDetail( StringBuffer buffer, String fieldName, byte[] array )
1407        {
1408            buffer.append( arrayStart );
1409            for ( int i = 0; i < array.length; i++ )
1410            {
1411                if ( i > 0 )
1412                {
1413                    buffer.append( arraySeparator );
1414                }
1415                appendDetail( buffer, fieldName, array[i] );
1416            }
1417            buffer.append( arrayEnd );
1418        }
1419    
1420    
1421        /**
1422         * <p>
1423         * Append to the <code>toString</code> a summary of a <code>byte</code>
1424         * array.
1425         * </p>
1426         * 
1427         * @param buffer
1428         *            the <code>StringBuffer</code> to populate
1429         * @param fieldName
1430         *            the field name, typically not used as already appended
1431         * @param array
1432         *            the array to add to the <code>toString</code>, not
1433         *            <code>null</code>
1434         */
1435        protected void appendSummary( StringBuffer buffer, String fieldName, byte[] array )
1436        {
1437            appendSummarySize( buffer, fieldName, array.length );
1438        }
1439    
1440    
1441        // ----------------------------------------------------------------------------
1442    
1443        /**
1444         * <p>
1445         * Append to the <code>toString</code> a <code>char</code> array.
1446         * </p>
1447         * 
1448         * @param buffer
1449         *            the <code>StringBuffer</code> to populate
1450         * @param fieldName
1451         *            the field name
1452         * @param array
1453         *            the array to add to the <code>toString</code>
1454         * @param fullDetail
1455         *            <code>true</code> for detail, <code>false</code> for
1456         *            summary info, <code>null</code> for style decides
1457         */
1458        public void append( StringBuffer buffer, String fieldName, char[] array, Boolean fullDetail )
1459        {
1460            appendFieldStart( buffer, fieldName );
1461    
1462            if ( array == null )
1463            {
1464                appendNullText( buffer, fieldName );
1465    
1466            }
1467            else if ( isFullDetail( fullDetail ) )
1468            {
1469                appendDetail( buffer, fieldName, array );
1470    
1471            }
1472            else
1473            {
1474                appendSummary( buffer, fieldName, array );
1475            }
1476    
1477            appendFieldEnd( buffer, fieldName );
1478        }
1479    
1480    
1481        /**
1482         * <p>
1483         * Append to the <code>toString</code> the detail of a <code>char</code>
1484         * array.
1485         * </p>
1486         * 
1487         * @param buffer
1488         *            the <code>StringBuffer</code> to populate
1489         * @param fieldName
1490         *            the field name, typically not used as already appended
1491         * @param array
1492         *            the array to add to the <code>toString</code>, not
1493         *            <code>null</code>
1494         */
1495        protected void appendDetail( StringBuffer buffer, String fieldName, char[] array )
1496        {
1497            buffer.append( arrayStart );
1498            for ( int i = 0; i < array.length; i++ )
1499            {
1500                if ( i > 0 )
1501                {
1502                    buffer.append( arraySeparator );
1503                }
1504                appendDetail( buffer, fieldName, array[i] );
1505            }
1506            buffer.append( arrayEnd );
1507        }
1508    
1509    
1510        /**
1511         * <p>
1512         * Append to the <code>toString</code> a summary of a <code>char</code>
1513         * array.
1514         * </p>
1515         * 
1516         * @param buffer
1517         *            the <code>StringBuffer</code> to populate
1518         * @param fieldName
1519         *            the field name, typically not used as already appended
1520         * @param array
1521         *            the array to add to the <code>toString</code>, not
1522         *            <code>null</code>
1523         */
1524        protected void appendSummary( StringBuffer buffer, String fieldName, char[] array )
1525        {
1526            appendSummarySize( buffer, fieldName, array.length );
1527        }
1528    
1529    
1530        // ----------------------------------------------------------------------------
1531    
1532        /**
1533         * <p>
1534         * Append to the <code>toString</code> a <code>double</code> array.
1535         * </p>
1536         * 
1537         * @param buffer
1538         *            the <code>StringBuffer</code> to populate
1539         * @param fieldName
1540         *            the field name
1541         * @param array
1542         *            the array to add to the toString
1543         * @param fullDetail
1544         *            <code>true</code> for detail, <code>false</code> for
1545         *            summary info, <code>null</code> for style decides
1546         */
1547        public void append( StringBuffer buffer, String fieldName, double[] array, Boolean fullDetail )
1548        {
1549            appendFieldStart( buffer, fieldName );
1550    
1551            if ( array == null )
1552            {
1553                appendNullText( buffer, fieldName );
1554    
1555            }
1556            else if ( isFullDetail( fullDetail ) )
1557            {
1558                appendDetail( buffer, fieldName, array );
1559    
1560            }
1561            else
1562            {
1563                appendSummary( buffer, fieldName, array );
1564            }
1565    
1566            appendFieldEnd( buffer, fieldName );
1567        }
1568    
1569    
1570        /**
1571         * <p>
1572         * Append to the <code>toString</code> the detail of a <code>double</code>
1573         * array.
1574         * </p>
1575         * 
1576         * @param buffer
1577         *            the <code>StringBuffer</code> to populate
1578         * @param fieldName
1579         *            the field name, typically not used as already appended
1580         * @param array
1581         *            the array to add to the <code>toString</code>, not
1582         *            <code>null</code>
1583         */
1584        protected void appendDetail( StringBuffer buffer, String fieldName, double[] array )
1585        {
1586            buffer.append( arrayStart );
1587            for ( int i = 0; i < array.length; i++ )
1588            {
1589                if ( i > 0 )
1590                {
1591                    buffer.append( arraySeparator );
1592                }
1593                appendDetail( buffer, fieldName, array[i] );
1594            }
1595            buffer.append( arrayEnd );
1596        }
1597    
1598    
1599        /**
1600         * <p>
1601         * Append to the <code>toString</code> a summary of a <code>double</code>
1602         * array.
1603         * </p>
1604         * 
1605         * @param buffer
1606         *            the <code>StringBuffer</code> to populate
1607         * @param fieldName
1608         *            the field name, typically not used as already appended
1609         * @param array
1610         *            the array to add to the <code>toString</code>, not
1611         *            <code>null</code>
1612         */
1613        protected void appendSummary( StringBuffer buffer, String fieldName, double[] array )
1614        {
1615            appendSummarySize( buffer, fieldName, array.length );
1616        }
1617    
1618    
1619        // ----------------------------------------------------------------------------
1620    
1621        /**
1622         * <p>
1623         * Append to the <code>toString</code> a <code>float</code> array.
1624         * </p>
1625         * 
1626         * @param buffer
1627         *            the <code>StringBuffer</code> to populate
1628         * @param fieldName
1629         *            the field name
1630         * @param array
1631         *            the array to add to the toString
1632         * @param fullDetail
1633         *            <code>true</code> for detail, <code>false</code> for
1634         *            summary info, <code>null</code> for style decides
1635         */
1636        public void append( StringBuffer buffer, String fieldName, float[] array, Boolean fullDetail )
1637        {
1638            appendFieldStart( buffer, fieldName );
1639    
1640            if ( array == null )
1641            {
1642                appendNullText( buffer, fieldName );
1643    
1644            }
1645            else if ( isFullDetail( fullDetail ) )
1646            {
1647                appendDetail( buffer, fieldName, array );
1648    
1649            }
1650            else
1651            {
1652                appendSummary( buffer, fieldName, array );
1653            }
1654    
1655            appendFieldEnd( buffer, fieldName );
1656        }
1657    
1658    
1659        /**
1660         * <p>
1661         * Append to the <code>toString</code> the detail of a <code>float</code>
1662         * array.
1663         * </p>
1664         * 
1665         * @param buffer
1666         *            the <code>StringBuffer</code> to populate
1667         * @param fieldName
1668         *            the field name, typically not used as already appended
1669         * @param array
1670         *            the array to add to the <code>toString</code>, not
1671         *            <code>null</code>
1672         */
1673        protected void appendDetail( StringBuffer buffer, String fieldName, float[] array )
1674        {
1675            buffer.append( arrayStart );
1676            for ( int i = 0; i < array.length; i++ )
1677            {
1678                if ( i > 0 )
1679                {
1680                    buffer.append( arraySeparator );
1681                }
1682                appendDetail( buffer, fieldName, array[i] );
1683            }
1684            buffer.append( arrayEnd );
1685        }
1686    
1687    
1688        /**
1689         * <p>
1690         * Append to the <code>toString</code> a summary of a <code>float</code>
1691         * array.
1692         * </p>
1693         * 
1694         * @param buffer
1695         *            the <code>StringBuffer</code> to populate
1696         * @param fieldName
1697         *            the field name, typically not used as already appended
1698         * @param array
1699         *            the array to add to the <code>toString</code>, not
1700         *            <code>null</code>
1701         */
1702        protected void appendSummary( StringBuffer buffer, String fieldName, float[] array )
1703        {
1704            appendSummarySize( buffer, fieldName, array.length );
1705        }
1706    
1707    
1708        // ----------------------------------------------------------------------------
1709    
1710        /**
1711         * <p>
1712         * Append to the <code>toString</code> a <code>boolean</code> array.
1713         * </p>
1714         * 
1715         * @param buffer
1716         *            the <code>StringBuffer</code> to populate
1717         * @param fieldName
1718         *            the field name
1719         * @param array
1720         *            the array to add to the toString
1721         * @param fullDetail
1722         *            <code>true</code> for detail, <code>false</code> for
1723         *            summary info, <code>null</code> for style decides
1724         */
1725        public void append( StringBuffer buffer, String fieldName, boolean[] array, Boolean fullDetail )
1726        {
1727            appendFieldStart( buffer, fieldName );
1728    
1729            if ( array == null )
1730            {
1731                appendNullText( buffer, fieldName );
1732    
1733            }
1734            else if ( isFullDetail( fullDetail ) )
1735            {
1736                appendDetail( buffer, fieldName, array );
1737    
1738            }
1739            else
1740            {
1741                appendSummary( buffer, fieldName, array );
1742            }
1743    
1744            appendFieldEnd( buffer, fieldName );
1745        }
1746    
1747    
1748        /**
1749         * <p>
1750         * Append to the <code>toString</code> the detail of a
1751         * <code>boolean</code> array.
1752         * </p>
1753         * 
1754         * @param buffer
1755         *            the <code>StringBuffer</code> to populate
1756         * @param fieldName
1757         *            the field name, typically not used as already appended
1758         * @param array
1759         *            the array to add to the <code>toString</code>, not
1760         *            <code>null</code>
1761         */
1762        protected void appendDetail( StringBuffer buffer, String fieldName, boolean[] array )
1763        {
1764            buffer.append( arrayStart );
1765            for ( int i = 0; i < array.length; i++ )
1766            {
1767                if ( i > 0 )
1768                {
1769                    buffer.append( arraySeparator );
1770                }
1771                appendDetail( buffer, fieldName, array[i] );
1772            }
1773            buffer.append( arrayEnd );
1774        }
1775    
1776    
1777        /**
1778         * <p>
1779         * Append to the <code>toString</code> a summary of a <code>boolean</code>
1780         * array.
1781         * </p>
1782         * 
1783         * @param buffer
1784         *            the <code>StringBuffer</code> to populate
1785         * @param fieldName
1786         *            the field name, typically not used as already appended
1787         * @param array
1788         *            the array to add to the <code>toString</code>, not
1789         *            <code>null</code>
1790         */
1791        protected void appendSummary( StringBuffer buffer, String fieldName, boolean[] array )
1792        {
1793            appendSummarySize( buffer, fieldName, array.length );
1794        }
1795    
1796    
1797        // ----------------------------------------------------------------------------
1798    
1799        /**
1800         * <p>
1801         * Append to the <code>toString</code> the class name.
1802         * </p>
1803         * 
1804         * @param buffer
1805         *            the <code>StringBuffer</code> to populate
1806         * @param object
1807         *            the <code>Object</code> whose name to output
1808         */
1809        protected void appendClassName( StringBuffer buffer, Object object )
1810        {
1811            if ( useClassName && object != null )
1812            {
1813                if ( useShortClassName )
1814                {
1815                    buffer.append( getShortClassName( object.getClass() ) );
1816                }
1817                else
1818                {
1819                    buffer.append( object.getClass().getName() );
1820                }
1821            }
1822        }
1823    
1824    
1825        /**
1826         * <p>
1827         * Append the {@link System#identityHashCode(java.lang.Object)}.
1828         * </p>
1829         * 
1830         * @param buffer
1831         *            the <code>StringBuffer</code> to populate
1832         * @param object
1833         *            the <code>Object</code> whose id to output
1834         */
1835        protected void appendIdentityHashCode( StringBuffer buffer, Object object )
1836        {
1837            if ( this.isUseIdentityHashCode() && object != null )
1838            {
1839                buffer.append( '@' );
1840                buffer.append( Integer.toHexString( System.identityHashCode( object ) ) );
1841            }
1842        }
1843    
1844    
1845        /**
1846         * <p>
1847         * Append to the <code>toString</code> the content start.
1848         * </p>
1849         * 
1850         * @param buffer
1851         *            the <code>StringBuffer</code> to populate
1852         */
1853        protected void appendContentStart( StringBuffer buffer )
1854        {
1855            buffer.append( contentStart );
1856        }
1857    
1858    
1859        /**
1860         * <p>
1861         * Append to the <code>toString</code> the content end.
1862         * </p>
1863         * 
1864         * @param buffer
1865         *            the <code>StringBuffer</code> to populate
1866         */
1867        protected void appendContentEnd( StringBuffer buffer )
1868        {
1869            buffer.append( contentEnd );
1870        }
1871    
1872    
1873        /**
1874         * <p>
1875         * Append to the <code>toString</code> an indicator for <code>null</code>.
1876         * </p>
1877         * <p>
1878         * The default indicator is <code>'&lt;null&gt;'</code>.
1879         * </p>
1880         * 
1881         * @param buffer
1882         *            the <code>StringBuffer</code> to populate
1883         * @param fieldName
1884         *            the field name, typically not used as already appended
1885         */
1886        protected void appendNullText( StringBuffer buffer, String fieldName )
1887        {
1888            buffer.append( nullText );
1889        }
1890    
1891    
1892        /**
1893         * <p>
1894         * Append to the <code>toString</code> the field separator.
1895         * </p>
1896         * 
1897         * @param buffer
1898         *            the <code>StringBuffer</code> to populate
1899         */
1900        protected void appendFieldSeparator( StringBuffer buffer )
1901        {
1902            buffer.append( fieldSeparator );
1903        }
1904    
1905    
1906        /**
1907         * <p>
1908         * Append to the <code>toString</code> the field start.
1909         * </p>
1910         * 
1911         * @param buffer
1912         *            the <code>StringBuffer</code> to populate
1913         * @param fieldName
1914         *            the field name
1915         */
1916        protected void appendFieldStart( StringBuffer buffer, String fieldName )
1917        {
1918            if ( useFieldNames && fieldName != null )
1919            {
1920                buffer.append( fieldName );
1921                buffer.append( fieldNameValueSeparator );
1922            }
1923        }
1924    
1925    
1926        /**
1927         * <p>
1928         * Append to the <code>toString<code> the field end.</p>
1929         * 
1930         * @param buffer  the <code>StringBuffer</code> to populate
1931         * @param fieldName  the field name, typically not used as already appended
1932         */
1933        protected void appendFieldEnd( StringBuffer buffer, String fieldName )
1934        {
1935            appendFieldSeparator( buffer );
1936        }
1937    
1938    
1939        /**
1940         * <p>
1941         * Append to the <code>toString</code> a size summary.
1942         * </p>
1943         * <p>
1944         * The size summary is used to summarize the contents of
1945         * <code>Collections</code>, <code>Maps</code> and arrays.
1946         * </p>
1947         * <p>
1948         * The output consists of a prefix, the passed in size and a suffix.
1949         * </p>
1950         * <p>
1951         * The default format is <code>'&lt;size=n&gt;'<code>.</p>
1952         *
1953         * @param buffer  the <code>StringBuffer</code> to populate
1954         * @param fieldName  the field name, typically not used as already appended
1955         * @param size  the size to append
1956         */
1957        protected void appendSummarySize( StringBuffer buffer, String fieldName, int size )
1958        {
1959            buffer.append( sizeStartText );
1960            buffer.append( size );
1961            buffer.append( sizeEndText );
1962        }
1963    
1964    
1965        /**
1966         * <p>
1967         * Is this field to be output in full detail.
1968         * </p>
1969         * <p>
1970         * This method converts a detail request into a detail level. The calling
1971         * code may request full detail (<code>true</code>), but a subclass
1972         * might ignore that and always return <code>false</code>. The calling
1973         * code may pass in <code>null</code> indicating that it doesn't care
1974         * about the detail level. In this case the default detail level is used.
1975         * </p>
1976         * 
1977         * @param fullDetailRequest
1978         *            the detail level requested
1979         * @return whether full detail is to be shown
1980         */
1981        protected boolean isFullDetail( Boolean fullDetailRequest )
1982        {
1983            if ( fullDetailRequest == null )
1984            {
1985                return defaultFullDetail;
1986            }
1987            return fullDetailRequest.booleanValue();
1988        }
1989    
1990    
1991        /**
1992         * <p>
1993         * Gets the short class name for a class.
1994         * </p>
1995         * <p>
1996         * The short class name is the classname excluding the package name.
1997         * </p>
1998         * 
1999         * @param cls
2000         *            the <code>Class</code> to get the short name of
2001         * @return the short name
2002         */
2003        protected String getShortClassName( Class cls )
2004        {
2005            return ClassUtils.getShortClassName( cls );
2006        }
2007    
2008    
2009        // Setters and getters for the customizable parts of the style
2010        // These methods are not expected to be overridden, except to make public
2011        // (They are not public so that immutable subclasses can be written)
2012        // ---------------------------------------------------------------------
2013    
2014        /**
2015         * <p>
2016         * Gets whether to use the class name.
2017         * </p>
2018         * 
2019         * @return the current useClassName flag
2020         */
2021        protected boolean isUseClassName()
2022        {
2023            return useClassName;
2024        }
2025    
2026    
2027        /**
2028         * <p>
2029         * Sets whether to use the class name.
2030         * </p>
2031         * 
2032         * @param useClassName
2033         *            the new useClassName flag
2034         */
2035        protected void setUseClassName( boolean useClassName )
2036        {
2037            this.useClassName = useClassName;
2038        }
2039    
2040    
2041        // ---------------------------------------------------------------------
2042    
2043        /**
2044         * <p>
2045         * Gets whether to output short or long class names.
2046         * </p>
2047         * 
2048         * @return the current useShortClassName flag
2049         * @since 2.0
2050         */
2051        protected boolean isUseShortClassName()
2052        {
2053            return useShortClassName;
2054        }
2055    
2056    
2057        /**
2058         * <p>
2059         * Gets whether to output short or long class names.
2060         * </p>
2061         * 
2062         * @return the current shortClassName flag
2063         * @deprecated Use {@link #isUseShortClassName()} Method will be removed in
2064         *             Commons Lang 3.0.
2065         */
2066        protected boolean isShortClassName()
2067        {
2068            return useShortClassName;
2069        }
2070    
2071    
2072        /**
2073         * <p>
2074         * Sets whether to output short or long class names.
2075         * </p>
2076         * 
2077         * @param useShortClassName
2078         *            the new useShortClassName flag
2079         * @since 2.0
2080         */
2081        protected void setUseShortClassName( boolean useShortClassName )
2082        {
2083            this.useShortClassName = useShortClassName;
2084        }
2085    
2086    
2087        /**
2088         * <p>
2089         * Sets whether to output short or long class names.
2090         * </p>
2091         * 
2092         * @param shortClassName
2093         *            the new shortClassName flag
2094         * @deprecated Use {@link #setUseShortClassName(boolean)} Method will be
2095         *             removed in Commons Lang 3.0.
2096         */
2097        protected void setShortClassName( boolean shortClassName )
2098        {
2099            this.useShortClassName = shortClassName;
2100        }
2101    
2102    
2103        // ---------------------------------------------------------------------
2104    
2105        /**
2106         * <p>
2107         * Gets whether to use the identity hash code.
2108         * </p>
2109         * 
2110         * @return the current useIdentityHashCode flag
2111         */
2112        protected boolean isUseIdentityHashCode()
2113        {
2114            return useIdentityHashCode;
2115        }
2116    
2117    
2118        /**
2119         * <p>
2120         * Sets whether to use the identity hash code.
2121         * </p>
2122         * 
2123         * @param useIdentityHashCode
2124         *            the new useIdentityHashCode flag
2125         */
2126        protected void setUseIdentityHashCode( boolean useIdentityHashCode )
2127        {
2128            this.useIdentityHashCode = useIdentityHashCode;
2129        }
2130    
2131    
2132        // ---------------------------------------------------------------------
2133    
2134        /**
2135         * <p>
2136         * Gets whether to use the field names passed in.
2137         * </p>
2138         * 
2139         * @return the current useFieldNames flag
2140         */
2141        protected boolean isUseFieldNames()
2142        {
2143            return useFieldNames;
2144        }
2145    
2146    
2147        /**
2148         * <p>
2149         * Sets whether to use the field names passed in.
2150         * </p>
2151         * 
2152         * @param useFieldNames
2153         *            the new useFieldNames flag
2154         */
2155        protected void setUseFieldNames( boolean useFieldNames )
2156        {
2157            this.useFieldNames = useFieldNames;
2158        }
2159    
2160    
2161        // ---------------------------------------------------------------------
2162    
2163        /**
2164         * <p>
2165         * Gets whether to use full detail when the caller doesn't specify.
2166         * </p>
2167         * 
2168         * @return the current defaultFullDetail flag
2169         */
2170        protected boolean isDefaultFullDetail()
2171        {
2172            return defaultFullDetail;
2173        }
2174    
2175    
2176        /**
2177         * <p>
2178         * Sets whether to use full detail when the caller doesn't specify.
2179         * </p>
2180         * 
2181         * @param defaultFullDetail
2182         *            the new defaultFullDetail flag
2183         */
2184        protected void setDefaultFullDetail( boolean defaultFullDetail )
2185        {
2186            this.defaultFullDetail = defaultFullDetail;
2187        }
2188    
2189    
2190        // ---------------------------------------------------------------------
2191    
2192        /**
2193         * <p>
2194         * Gets whether to output array content detail.
2195         * </p>
2196         * 
2197         * @return the current array content detail setting
2198         */
2199        protected boolean isArrayContentDetail()
2200        {
2201            return arrayContentDetail;
2202        }
2203    
2204    
2205        /**
2206         * <p>
2207         * Sets whether to output array content detail.
2208         * </p>
2209         * 
2210         * @param arrayContentDetail
2211         *            the new arrayContentDetail flag
2212         */
2213        protected void setArrayContentDetail( boolean arrayContentDetail )
2214        {
2215            this.arrayContentDetail = arrayContentDetail;
2216        }
2217    
2218    
2219        // ---------------------------------------------------------------------
2220    
2221        /**
2222         * <p>
2223         * Gets the array start text.
2224         * </p>
2225         * 
2226         * @return the current array start text
2227         */
2228        protected String getArrayStart()
2229        {
2230            return arrayStart;
2231        }
2232    
2233    
2234        /**
2235         * <p>
2236         * Sets the array start text.
2237         * </p>
2238         * <p>
2239         * <code>null</code> is accepted, but will be converted to an empty
2240         * String.
2241         * </p>
2242         * 
2243         * @param arrayStart
2244         *            the new array start text
2245         */
2246        protected void setArrayStart( String arrayStart )
2247        {
2248            if ( arrayStart == null )
2249            {
2250                arrayStart = "";
2251            }
2252            this.arrayStart = arrayStart;
2253        }
2254    
2255    
2256        // ---------------------------------------------------------------------
2257    
2258        /**
2259         * <p>
2260         * Gets the array end text.
2261         * </p>
2262         * 
2263         * @return the current array end text
2264         */
2265        protected String getArrayEnd()
2266        {
2267            return arrayEnd;
2268        }
2269    
2270    
2271        /**
2272         * <p>
2273         * Sets the array end text.
2274         * </p>
2275         * <p>
2276         * <code>null</code> is accepted, but will be converted to an empty
2277         * String.
2278         * </p>
2279         * 
2280         * @param arrayEnd
2281         *            the new array end text
2282         */
2283        protected void setArrayEnd( String arrayEnd )
2284        {
2285            if ( arrayStart == null )
2286            {
2287                arrayStart = "";
2288            }
2289            this.arrayEnd = arrayEnd;
2290        }
2291    
2292    
2293        // ---------------------------------------------------------------------
2294    
2295        /**
2296         * <p>
2297         * Gets the array separator text.
2298         * </p>
2299         * 
2300         * @return the current array separator text
2301         */
2302        protected String getArraySeparator()
2303        {
2304            return arraySeparator;
2305        }
2306    
2307    
2308        /**
2309         * <p>
2310         * Sets the array separator text.
2311         * </p>
2312         * <p>
2313         * <code>null</code> is accepted, but will be converted to an empty
2314         * String.
2315         * </p>
2316         * 
2317         * @param arraySeparator
2318         *            the new array separator text
2319         */
2320        protected void setArraySeparator( String arraySeparator )
2321        {
2322            if ( arraySeparator == null )
2323            {
2324                arraySeparator = "";
2325            }
2326            this.arraySeparator = arraySeparator;
2327        }
2328    
2329    
2330        // ---------------------------------------------------------------------
2331    
2332        /**
2333         * <p>
2334         * Gets the content start text.
2335         * </p>
2336         * 
2337         * @return the current content start text
2338         */
2339        protected String getContentStart()
2340        {
2341            return contentStart;
2342        }
2343    
2344    
2345        /**
2346         * <p>
2347         * Sets the content start text.
2348         * </p>
2349         * <p>
2350         * <code>null</code> is accepted, but will be converted to an empty
2351         * String.
2352         * </p>
2353         * 
2354         * @param contentStart
2355         *            the new content start text
2356         */
2357        protected void setContentStart( String contentStart )
2358        {
2359            if ( contentStart == null )
2360            {
2361                contentStart = "";
2362            }
2363            this.contentStart = contentStart;
2364        }
2365    
2366    
2367        // ---------------------------------------------------------------------
2368    
2369        /**
2370         * <p>
2371         * Gets the content end text.
2372         * </p>
2373         * 
2374         * @return the current content end text
2375         */
2376        protected String getContentEnd()
2377        {
2378            return contentEnd;
2379        }
2380    
2381    
2382        /**
2383         * <p>
2384         * Sets the content end text.
2385         * </p>
2386         * <p>
2387         * <code>null</code> is accepted, but will be converted to an empty
2388         * String.
2389         * </p>
2390         * 
2391         * @param contentEnd
2392         *            the new content end text
2393         */
2394        protected void setContentEnd( String contentEnd )
2395        {
2396            if ( contentEnd == null )
2397            {
2398                contentEnd = "";
2399            }
2400            this.contentEnd = contentEnd;
2401        }
2402    
2403    
2404        // ---------------------------------------------------------------------
2405    
2406        /**
2407         * <p>
2408         * Gets the field name value separator text.
2409         * </p>
2410         * 
2411         * @return the current field name value separator text
2412         */
2413        protected String getFieldNameValueSeparator()
2414        {
2415            return fieldNameValueSeparator;
2416        }
2417    
2418    
2419        /**
2420         * <p>
2421         * Sets the field name value separator text.
2422         * </p>
2423         * <p>
2424         * <code>null</code> is accepted, but will be converted to an empty
2425         * String.
2426         * </p>
2427         * 
2428         * @param fieldNameValueSeparator
2429         *            the new field name value separator text
2430         */
2431        protected void setFieldNameValueSeparator( String fieldNameValueSeparator )
2432        {
2433            if ( fieldNameValueSeparator == null )
2434            {
2435                fieldNameValueSeparator = "";
2436            }
2437            this.fieldNameValueSeparator = fieldNameValueSeparator;
2438        }
2439    
2440    
2441        // ---------------------------------------------------------------------
2442    
2443        /**
2444         * <p>
2445         * Gets the field separator text.
2446         * </p>
2447         * 
2448         * @return the current field separator text
2449         */
2450        protected String getFieldSeparator()
2451        {
2452            return fieldSeparator;
2453        }
2454    
2455    
2456        /**
2457         * <p>
2458         * Sets the field separator text.
2459         * </p>
2460         * <p>
2461         * <code>null</code> is accepted, but will be converted to an empty
2462         * String.
2463         * </p>
2464         * 
2465         * @param fieldSeparator
2466         *            the new field separator text
2467         */
2468        protected void setFieldSeparator( String fieldSeparator )
2469        {
2470            if ( fieldSeparator == null )
2471            {
2472                fieldSeparator = "";
2473            }
2474            this.fieldSeparator = fieldSeparator;
2475        }
2476    
2477    
2478        // ---------------------------------------------------------------------
2479    
2480        /**
2481         * <p>
2482         * Gets whether the field separator should be added at the start of each
2483         * buffer.
2484         * </p>
2485         * 
2486         * @return the fieldSeparatorAtStart flag
2487         * @since 2.0
2488         */
2489        protected boolean isFieldSeparatorAtStart()
2490        {
2491            return fieldSeparatorAtStart;
2492        }
2493    
2494    
2495        /**
2496         * <p>
2497         * Sets whether the field separator should be added at the start of each
2498         * buffer.
2499         * </p>
2500         * 
2501         * @param fieldSeparatorAtStart
2502         *            the fieldSeparatorAtStart flag
2503         * @since 2.0
2504         */
2505        protected void setFieldSeparatorAtStart( boolean fieldSeparatorAtStart )
2506        {
2507            this.fieldSeparatorAtStart = fieldSeparatorAtStart;
2508        }
2509    
2510    
2511        // ---------------------------------------------------------------------
2512    
2513        /**
2514         * <p>
2515         * Gets whether the field separator should be added at the end of each
2516         * buffer.
2517         * </p>
2518         * 
2519         * @return fieldSeparatorAtEnd flag
2520         * @since 2.0
2521         */
2522        protected boolean isFieldSeparatorAtEnd()
2523        {
2524            return fieldSeparatorAtEnd;
2525        }
2526    
2527    
2528        /**
2529         * <p>
2530         * Sets whether the field separator should be added at the end of each
2531         * buffer.
2532         * </p>
2533         * 
2534         * @param fieldSeparatorAtEnd
2535         *            the fieldSeparatorAtEnd flag
2536         * @since 2.0
2537         */
2538        protected void setFieldSeparatorAtEnd( boolean fieldSeparatorAtEnd )
2539        {
2540            this.fieldSeparatorAtEnd = fieldSeparatorAtEnd;
2541        }
2542    
2543    
2544        // ---------------------------------------------------------------------
2545    
2546        /**
2547         * <p>
2548         * Gets the text to output when <code>null</code> found.
2549         * </p>
2550         * 
2551         * @return the current text to output when null found
2552         */
2553        protected String getNullText()
2554        {
2555            return nullText;
2556        }
2557    
2558    
2559        /**
2560         * <p>
2561         * Sets the text to output when <code>null</code> found.
2562         * </p>
2563         * <p>
2564         * <code>null</code> is accepted, but will be converted to an empty
2565         * String.
2566         * </p>
2567         * 
2568         * @param nullText
2569         *            the new text to output when null found
2570         */
2571        protected void setNullText( String nullText )
2572        {
2573            if ( nullText == null )
2574            {
2575                nullText = "";
2576            }
2577            this.nullText = nullText;
2578        }
2579    
2580    
2581        // ---------------------------------------------------------------------
2582    
2583        /**
2584         * <p>
2585         * Gets the start text to output when a <code>Collection</code>,
2586         * <code>Map</code> or array size is output.
2587         * </p>
2588         * <p>
2589         * This is output before the size value.
2590         * </p>
2591         * 
2592         * @return the current start of size text
2593         */
2594        protected String getSizeStartText()
2595        {
2596            return sizeStartText;
2597        }
2598    
2599    
2600        /**
2601         * <p>
2602         * Sets the start text to output when a <code>Collection</code>,
2603         * <code>Map</code> or array size is output.
2604         * </p>
2605         * <p>
2606         * This is output before the size value.
2607         * </p>
2608         * <p>
2609         * <code>null</code> is accepted, but will be converted to an empty
2610         * String.
2611         * </p>
2612         * 
2613         * @param sizeStartText
2614         *            the new start of size text
2615         */
2616        protected void setSizeStartText( String sizeStartText )
2617        {
2618            if ( sizeStartText == null )
2619            {
2620                sizeStartText = "";
2621            }
2622            this.sizeStartText = sizeStartText;
2623        }
2624    
2625    
2626        // ---------------------------------------------------------------------
2627    
2628        /**
2629         * <p>
2630         * Gets the end text to output when a <code>Collection</code>,
2631         * <code>Map</code> or array size is output.
2632         * </p>
2633         * <p>
2634         * This is output after the size value.
2635         * </p>
2636         * 
2637         * @return the current end of size text
2638         */
2639        protected String getSizeEndText()
2640        {
2641            return sizeEndText;
2642        }
2643    
2644    
2645        /**
2646         * <p>
2647         * Sets the end text to output when a <code>Collection</code>,
2648         * <code>Map</code> or array size is output.
2649         * </p>
2650         * <p>
2651         * This is output after the size value.
2652         * </p>
2653         * <p>
2654         * <code>null</code> is accepted, but will be converted to an empty
2655         * String.
2656         * </p>
2657         * 
2658         * @param sizeEndText
2659         *            the new end of size text
2660         */
2661        protected void setSizeEndText( String sizeEndText )
2662        {
2663            if ( sizeEndText == null )
2664            {
2665                sizeEndText = "";
2666            }
2667            this.sizeEndText = sizeEndText;
2668        }
2669    
2670    
2671        // ---------------------------------------------------------------------
2672    
2673        /**
2674         * <p>
2675         * Gets the start text to output when an <code>Object</code> is output in
2676         * summary mode.
2677         * </p>
2678         * <p>
2679         * This is output before the size value.
2680         * </p>
2681         * 
2682         * @return the current start of summary text
2683         */
2684        protected String getSummaryObjectStartText()
2685        {
2686            return summaryObjectStartText;
2687        }
2688    
2689    
2690        /**
2691         * <p>
2692         * Sets the start text to output when an <code>Object</code> is output in
2693         * summary mode.
2694         * </p>
2695         * <p>
2696         * This is output before the size value.
2697         * </p>
2698         * <p>
2699         * <code>null</code> is accepted, but will be converted to an empty
2700         * String.
2701         * </p>
2702         * 
2703         * @param summaryObjectStartText
2704         *            the new start of summary text
2705         */
2706        protected void setSummaryObjectStartText( String summaryObjectStartText )
2707        {
2708            if ( summaryObjectStartText == null )
2709            {
2710                summaryObjectStartText = "";
2711            }
2712            this.summaryObjectStartText = summaryObjectStartText;
2713        }
2714    
2715    
2716        // ---------------------------------------------------------------------
2717    
2718        /**
2719         * <p>
2720         * Gets the end text to output when an <code>Object</code> is output in
2721         * summary mode.
2722         * </p>
2723         * <p>
2724         * This is output after the size value.
2725         * </p>
2726         * 
2727         * @return the current end of summary text
2728         */
2729        protected String getSummaryObjectEndText()
2730        {
2731            return summaryObjectEndText;
2732        }
2733    
2734    
2735        /**
2736         * <p>
2737         * Sets the end text to output when an <code>Object</code> is output in
2738         * summary mode.
2739         * </p>
2740         * <p>
2741         * This is output after the size value.
2742         * </p>
2743         * <p>
2744         * <code>null</code> is accepted, but will be converted to an empty
2745         * String.
2746         * </p>
2747         * 
2748         * @param summaryObjectEndText
2749         *            the new end of summary text
2750         */
2751        protected void setSummaryObjectEndText( String summaryObjectEndText )
2752        {
2753            if ( summaryObjectEndText == null )
2754            {
2755                summaryObjectEndText = "";
2756            }
2757            this.summaryObjectEndText = summaryObjectEndText;
2758        }
2759    
2760        // ----------------------------------------------------------------------------
2761    
2762        /**
2763         * <p>
2764         * Default <code>ToStringStyle</code>.
2765         * </p>
2766         * <p>
2767         * This is an inner class rather than using
2768         * <code>StandardToStringStyle</code> to ensure its immutability.
2769         * </p>
2770         */
2771        private static final class DefaultToStringStyle extends ToStringStyle
2772        {
2773    
2774            static final long serialVersionUID = -3594451267200535036L;
2775    
2776    
2777            /**
2778             * <p>
2779             * Constructor.
2780             * </p>
2781             * <p>
2782             * Use the static constant rather than instantiating.
2783             * </p>
2784             */
2785            private DefaultToStringStyle()
2786            {
2787                super();
2788            }
2789    
2790    
2791            /**
2792             * <p>
2793             * Ensure <code>Singleton</code> after serialization.
2794             * </p>
2795             * 
2796             * @return the singleton
2797             */
2798            private Object readResolve()
2799            {
2800                return ToStringStyle.DEFAULT_STYLE;
2801            }
2802    
2803        }
2804    
2805        // ----------------------------------------------------------------------------
2806    
2807        /**
2808         * <p>
2809         * <code>ToStringStyle</code> that does not print out the field names.
2810         * </p>
2811         * <p>
2812         * This is an inner class rather than using
2813         * <code>StandardToStringStyle</code> to ensure its immutability.
2814         */
2815        private static final class NoFieldNameToStringStyle extends ToStringStyle
2816        {
2817    
2818            static final long serialVersionUID = -3594451267200535036L;
2819    
2820    
2821            /**
2822             * <p>
2823             * Constructor.
2824             * </p>
2825             * <p>
2826             * Use the static constant rather than instantiating.
2827             * </p>
2828             */
2829            private NoFieldNameToStringStyle()
2830            {
2831                super();
2832                this.setUseFieldNames( false );
2833            }
2834    
2835    
2836            /**
2837             * <p>
2838             * Ensure <code>Singleton</code> after serialization.
2839             * </p>
2840             * 
2841             * @return the singleton
2842             */
2843            private Object readResolve()
2844            {
2845                return ToStringStyle.NO_FIELD_NAMES_STYLE;
2846            }
2847    
2848        }
2849    
2850        // ----------------------------------------------------------------------------
2851    
2852        /**
2853         * <p>
2854         * <code>ToStringStyle</code> that prints out the short class name and no
2855         * identity hashcode.
2856         * </p>
2857         * <p>
2858         * This is an inner class rather than using
2859         * <code>StandardToStringStyle</code> to ensure its immutability.
2860         * </p>
2861         */
2862        private static final class ShortPrefixToStringStyle extends ToStringStyle
2863        {
2864    
2865            static final long serialVersionUID = -3594451267200535036L;
2866    
2867    
2868            /**
2869             * <p>
2870             * Constructor.
2871             * </p>
2872             * <p>
2873             * Use the static constant rather than instantiating.
2874             * </p>
2875             */
2876            private ShortPrefixToStringStyle()
2877            {
2878                super();
2879                this.setUseShortClassName( true );
2880                this.setUseIdentityHashCode( false );
2881            }
2882    
2883    
2884            /**
2885             * <p>
2886             * Ensure <code>Singleton</ode> after serialization.</p>
2887             * @return the singleton
2888             */
2889            private Object readResolve()
2890            {
2891                return ToStringStyle.SHORT_PREFIX_STYLE;
2892            }
2893    
2894        }
2895    
2896        /**
2897         * <p>
2898         * <code>ToStringStyle</code> that does not print out the classname,
2899         * identity hashcode, content start or field name.
2900         * </p>
2901         * <p>
2902         * This is an inner class rather than using
2903         * <code>StandardToStringStyle</code> to ensure its immutability.
2904         * </p>
2905         */
2906        private static final class SimpleToStringStyle extends ToStringStyle
2907        {
2908    
2909            static final long serialVersionUID = -3594451267200535036L;
2910    
2911    
2912            /**
2913             * <p>
2914             * Constructor.
2915             * </p>
2916             * <p>
2917             * Use the static constant rather than instantiating.
2918             * </p>
2919             */
2920            private SimpleToStringStyle()
2921            {
2922                super();
2923                this.setUseClassName( false );
2924                this.setUseIdentityHashCode( false );
2925                this.setUseFieldNames( false );
2926                this.setContentStart( "" );
2927                this.setContentEnd( "" );
2928            }
2929    
2930    
2931            /**
2932             * <p>
2933             * Ensure <code>Singleton</ode> after serialization.</p>
2934             * @return the singleton
2935             */
2936            private Object readResolve()
2937            {
2938                return ToStringStyle.SIMPLE_STYLE;
2939            }
2940    
2941        }
2942    
2943        // ----------------------------------------------------------------------------
2944    
2945        /**
2946         * <p>
2947         * <code>ToStringStyle</code> that outputs on multiple lines.
2948         * </p>
2949         * <p>
2950         * This is an inner class rather than using
2951         * <code>StandardToStringStyle</code> to ensure its immutability.
2952         * </p>
2953         */
2954        private static final class MultiLineToStringStyle extends ToStringStyle
2955        {
2956    
2957            static final long serialVersionUID = -3594451267200535036L;
2958    
2959    
2960            /**
2961             * <p>
2962             * Constructor.
2963             * </p>
2964             * <p>
2965             * Use the static constant rather than instantiating.
2966             * </p>
2967             */
2968            private MultiLineToStringStyle()
2969            {
2970                super();
2971                this.setContentStart( "[" );
2972                this.setFieldSeparator( SystemUtils.LINE_SEPARATOR + "  " );
2973                this.setFieldSeparatorAtStart( true );
2974                this.setContentEnd( SystemUtils.LINE_SEPARATOR + "]" );
2975            }
2976    
2977    
2978            /**
2979             * <p>
2980             * Ensure <code>Singleton</code> after serialization.
2981             * </p>
2982             * 
2983             * @return the singleton
2984             */
2985            private Object readResolve()
2986            {
2987                return ToStringStyle.MULTI_LINE_STYLE;
2988            }
2989    
2990        }
2991    
2992        // ----------------------------------------------------------------------------
2993    
2994        // Removed, as the XML style needs more work for escaping characters,
2995        // arrays,
2996        // collections, maps and embedded beans.
2997        // /**
2998        // * ToStringStyle that outputs in XML style
2999        // */
3000        // private static class XMLToStringStyle extends ToStringStyle {
3001        //        
3002        // /**
3003        // * Constructor - use the static constant rather than instantiating.
3004        // */
3005        // private XMLToStringStyle() {
3006        // super();
3007        // nullText = "null";
3008        // sizeStartText = "size=";
3009        // sizeEndText = "";
3010        // }
3011        //        
3012        // /**
3013        // * @see ToStringStyle#appendStart(StringBuffer, Object)
3014        // */
3015        // public void appendStart(StringBuffer buffer, Object object) {
3016        // buffer.append('<');
3017        // buffer.append(getShortClassName(object.getClass()));
3018        // buffer.append(" class=\"");
3019        // appendClassName(buffer, object);
3020        // buffer.append("\" hashCode=\"");
3021        // appendIdentityHashCode(buffer, object);
3022        // buffer.append("\">");
3023        // buffer.append(SystemUtils.LINE_SEPARATOR);
3024        // buffer.append(" ");
3025        // }
3026        //
3027        // /**
3028        // * @see ToStringStyle#appendFieldStart(StringBuffer, String)
3029        // */
3030        // protected void appendFieldStart(StringBuffer buffer, String fieldName) {
3031        // buffer.append('<');
3032        // buffer.append(fieldName);
3033        // buffer.append('>');
3034        // }
3035        //
3036        // /**
3037        // * @see ToStringStyle#appendFieldEnd(StringBuffer, String)
3038        // */
3039        // protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
3040        // buffer.append("</");
3041        // buffer.append(fieldName);
3042        // buffer.append('>');
3043        // buffer.append(SystemUtils.LINE_SEPARATOR);
3044        // buffer.append(" ");
3045        // }
3046        //
3047        // /**
3048        // * @see ToStringStyle#appendEnd(StringBuffer, Object)
3049        // */
3050        // public void appendEnd(StringBuffer buffer, Object object) {
3051        // int len = buffer.length();
3052        // if (len > 2 && buffer.charAt(len - 1) == ' ' && buffer.charAt(len - 2) ==
3053        // ' ') {
3054        // buffer.setLength(len - 2);
3055        // }
3056        // buffer.append("</");
3057        // buffer.append(getShortClassName(object.getClass()));
3058        // buffer.append("\">");
3059        // }
3060        //
3061        // }
3062    
3063    }