001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.util;
017
018import java.util.Arrays ;
019
020import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
021import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
022
023/**
024 * ToString.java は、共通的に使用される toString() を簡素化するクラスです。
025 * デバッグ情報を出力する最も一般的な方法は、内部文字列の出力です。
026 * 通常、キーと値をペアで記述するため、StringBuilder で append しながら作成するにしても
027 * コーディング的にあまり見栄えの良い形にはなりません。
028 * ここでは、それらを簡易的に整形して出力できるように、メソッドを用意しました。
029 *
030 * @og.group ユーティリティ
031 *
032 * @version  4.0
033 * @author       Kazuhiko Hasegawa
034 * @since    JDK5.0,
035 */
036public final class ToString {
037
038        /** 4つ分のスペースです。 */
039        private static final String SPACE = "    " ;
040        /** 3つ分のカンマです。  */
041        private static final String COMMA = " , " ;
042
043        private final StringBuilder buf ;
044
045        /** 最後に改行記号を入れたかどうか。    */
046        private boolean lastCR = true ;
047
048        /** キー文字列の最大長(すべてASCII換算)       */
049        private int maxSize     ;
050
051        /**
052         * タイトルを指定するコンストラクター
053         * タイトルは、先頭にスペースなしで入れます。最後は改行ありです。
054         *
055         * @param title タイトル文字列
056         */
057        public ToString( final String title ) {
058                buf = new StringBuilder( BUFFER_MIDDLE );
059                buf.append( "TITLE = [" ).append( title ).append( ']' ).append( CR );           // 6.0.2.5 (2014/10/31) char を append する。
060                lastCR = true ;
061        }
062
063        /**
064         * 簡易的にオブジェクトを構築する static メソッド
065         * タイトルは、先頭にスペースなしで入れます。最後は改行ありです。
066         *
067         * @param       title タイトル文字列
068         *
069         * @return      ToStringオブジェクト
070         * @og.rtnNotNull
071         */
072        public static ToString title( final String title ) {
073                return new ToString( title );
074        }
075
076        /**
077         * 改行なしのキーと値のペアを設定します。
078         * 前回、改行で終わっている場合は、キーから始めます。
079         * そうでない場合、" , " を出力してから、書き始めます。
080         *
081         * @param       key     キー文字列
082         * @param       val     値文字列
083         *
084         * @return      自分自身
085         * @og.rtnNotNull
086         */
087        public ToString print( final String key,final Object val ) {
088                if( lastCR ) {  buf.append( SPACE ); }
089                else {                  buf.append( COMMA ); }
090                lastCR = false;
091
092                // 6.0.2.5 (2014/10/31) char を append する。
093                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
094                if( key == null ) {
095                        buf.append( "   [" ).append( String.valueOf( val ) ).append( ']' );
096                }
097                else {
098                        final int len = key.length();
099                        if( len > maxSize ) { maxSize = len; }
100                        buf.append( key ).append( " = [" ).append( String.valueOf( val ) ).append( ']' );
101                }
102
103                return this ;
104        }
105
106        /**
107         * 改行ありのキーと値のペアを設定します。
108         * 前回、改行で終わっている場合は、キーから始めます。
109         * そうでない場合、" , " を出力してから、書き始めます。
110         *
111         * @param       key     キー文字列
112         * @param       val     値文字列
113         *
114         * @return      自分自身
115         * @og.rtnNotNull
116         */
117        public ToString println( final String key,final Object val ) {
118                print( key,val );
119
120                buf.append( CR );
121                lastCR = true;
122
123                return this ;
124        }
125
126        /**
127         * 改行なしのキーと値配列のペアを設定します。
128         * 前回、改行で終わっている場合は、キーから始めます。
129         * そうでない場合、" , " を出力してから、書き始めます。
130         *
131         * @param       key     キー文字列
132         * @param       val     値配列
133         *
134         * @return      自分自身
135         * @og.rtnNotNull
136         */
137        public ToString print( final String key,final Object[] val ) {
138                final String str = Arrays.toString( val );
139
140                return print( key,str.substring( 1,str.length()-1 ) );
141        }
142
143        /**
144         * 改行ありのキーと値配列のペアを設定します。
145         * 前回、改行で終わっている場合は、キーから始めます。
146         * そうでない場合、" , " を出力してから、書き始めます。
147         *
148         * @param       key     キー文字列
149         * @param       val     値配列
150         *
151         * @return      自分自身
152         * @og.rtnNotNull
153         */
154        public ToString println( final String key,final Object[] val ) {
155                final String str = Arrays.toString( val );
156
157                return println( key,str.substring( 1,str.length()-1 ) );
158        }
159
160        /**
161         * 改行のみ設定します。
162         *
163         * @return      自分自身
164         * @og.rtnNotNull
165         */
166        public ToString println() {
167                buf.append( CR );
168                lastCR = true;
169
170                return this;
171        }
172
173        /**
174         * 改行付きの値のみ設定します。
175         *
176         * @param       val     値
177         *
178         * @return      自分自身
179         * @og.rtnNotNull
180         */
181        public ToString println( final Object val ) {
182                return println( null,val );
183        }
184
185        /**
186         * 改行付きの値のみ設定します。
187         *
188         * @param       val     値配列
189         *
190         * @return      自分自身
191         * @og.rtnNotNull
192         */
193        public ToString println( final Object[] val ) {
194                final String str = Arrays.toString( val );
195
196                return println( null,str.substring( 1,str.length()-1 ) );
197        }
198
199        /**
200         * 先頭のキーの位置を最大値に合わせて、整形します。
201         *
202         * @return      自分自身
203         * @og.rtnNotNull
204         */
205        public ToString fixForm() {
206                final String searchKey = CR + SPACE ;
207                final int    skLen = searchKey.length() ;
208
209                final char[] ch = new char[maxSize];
210                Arrays.fill( ch,' ' );
211                // 8.5.4.2 (2024/01/12) PMD 7.0.0 StringInstantiation 対応
212//              final String MAX_SPACE = new String( ch );
213                final String MAX_SPACE = String.valueOf( ch );
214
215                int adrs = buf.indexOf( searchKey );
216                while( adrs >= 0 ) {
217                        final int eq = buf.indexOf( "=",adrs );
218                        if( eq >= 0 && buf.charAt(adrs+skLen) != ' ' ) {
219                                final int nextAdrs  = buf.indexOf( searchKey,adrs+skLen );
220                                if( nextAdrs < 0 || eq < nextAdrs ) {
221                                        buf.insert( eq, MAX_SPACE.substring( eq-(adrs+skLen)-1 ) );
222                                }
223                        }
224                        adrs = buf.indexOf( searchKey,adrs+skLen );
225                }
226
227                return this;
228        }
229
230        /**
231         * 内部バッファを文字列にして返します。
232         *
233         * @return      内部バッファを文字列にして返します。
234         * @og.rtnNotNull
235         */
236        @Override
237        public String toString() {
238                return buf.toString() ;
239        }
240}