    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        /** ４つ分のスペースです。 */
    039        private static final String SPACE = "    " ;
    040        /** ３つ分のカンマです。  */
    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                final String MAX_SPACE = new String( ch );
    212
    213                int adrs = buf.indexOf( searchKey );
    214                while( adrs >= 0 ) {
    215                        final int eq = buf.indexOf( "=",adrs );
    216                        if( eq >= 0 && buf.charAt(adrs+skLen) != ' ' ) {
    217                                final int nextAdrs  = buf.indexOf( searchKey,adrs+skLen );
    218                                if( nextAdrs < 0 || eq < nextAdrs ) {
    219                                        buf.insert( eq, MAX_SPACE.substring( eq-(adrs+skLen)-1 ) );
    220                                }
    221                        }
    222                        adrs = buf.indexOf( searchKey,adrs+skLen );
    223                }
    224
    225                return this;
    226        }
    227
    228        /**
    229         * 内部バッファを文字列にして返します。
    230         *
    231         * @return      内部バッファを文字列にして返します。
    232         * @og.rtnNotNull
    233         */
    234        @Override
    235        public String toString() {
    236                return buf.toString() ;
    237        }
    238}