    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
    018/**
    019 * TagBuffer.java は、共通的に使用される 簡易タグ作成クラスです。
    020 * タグヘッダーは、オブジェクト作成時に登録する為、後の変更は出来ません。
    021 * BODY部や、属性は、一度登録すると書き換えできません。
    022 * また、同一属性チェックは行いません。登録した属性のキーや、値を取り出すことも出来ません。
    023 * あくまで、タグ文字列をストレートに作成することに特化したクラスです。
    024 * これらの高度な機能が必要であれば、{@link org.opengion.fukurou.util.Attributes } をご参照ください。
    025 *
    026 * makeTag() メソッドを呼び出した時点で、内部にタグ文字列をキャッシュします。
    027 * それ以降の変更は、出来ません。
    028 *
    029 * 内部的には、構造化されていません。あくまで、文字列連結(StringBuilder)の
    030 * 簡易クラスとして、使用してください。
    031 *
    032 * @og.group ユーティリティ
    033 *
    034 * @version  4.0
    035 * @author       Kazuhiko Hasegawa
    036 * @since    JDK5.0,
    037 */
    038public final class TagBuffer {
    039        private final StringBuilder buf = new StringBuilder(100);
    040        private final String tagName ;
    041        private       String body     = null;
    042        private       String cacheTag = null;
    043
    044        /**
    045         * デフォルトコンストラクター
    046         * このコンストラクターを使用すると、タグ名を指定できないため、
    047         * 完成形のタグは、作成できません。属性リスト(key="value")の
    048         * 連結形式を得る場合にのみ、使用して下さい。
    049         *
    050         */
    051        public TagBuffer() {
    052                this.tagName = null;
    053        }
    054
    055        /**
    056         * コンストラクター
    057         * タグ名に null を指定すると、デフォルトコンストラクターと同様に、
    058         * 完成形のタグは、作成できません。属性リスト(key="value")の
    059         * 連結形式を得る場合にのみ、タグ名 にnull を指定して下さい。
    060         *
    061         * @param       tagName  タグ名称
    062         */
    063        public TagBuffer( final String tagName ) {
    064                this.tagName = tagName;
    065                if( tagName != null ) {
    066                        buf.append( "<" ).append( tagName ).append( " " );
    067                }
    068        }
    069
    070        /**
    071         * タグの BODY部を登録します。
    072         * 登録しない場合は、BODY部のないタグ(空要素タグ)を生成します。
    073         * BODY部を指定すると、&lt;tagName key="val" ･･･ &gt;body&lt;/tagName&gt; 形式になります。
    074         * BODY部が、null の場合は、 &lt;tagName key="val" ･･･ /&gt; 形式になります。
    075         * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。
    076         *
    077         * @param       body     タグのBODY部
    078         */
    079        public void setBody( final String body ) {
    080                if( cacheTag != null ) {
    081                        String errMsg = "makeTag() 実行後に、BODY部の値を書き換えることは出来ません。" ;
    082                        throw new RuntimeException( errMsg );
    083                }
    084
    085                this.body = body;
    086        }
    087
    088        /**
    089         * タグの 属性(key="value")を登録します。
    090         * 属性は、key="value" の文字列を作成します。key か、value のどちらかが null
    091         * の場合は、登録しません。
    092         * value に、ダブルコーテーション(")が含まれている場合は、属性値をシングルコーテーション
    093         * でくくります。
    094         * 両方含まれている場合は、シングルコーテーションをエスケープ文字に変換します。
    095         * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。
    096         *
    097         * @og.rev 3.8.6.1 (2006/10/20) シングルとダブルが混在する場合は、シングルをエスケープする
    098         *
    099         * @param       key      属性キー (null の場合は、なにもしない)
    100         * @param       val      属性値 (null の場合は、なにもしない)
    101         */
    102        public void add( final String key,final String val ) {
    103                if( cacheTag != null ) {
    104                        String errMsg = "makeTag() 実行後に、属性を追加することは出来ません。" ;
    105                        throw new RuntimeException( errMsg );
    106                }
    107
    108                if( key != null && val != null ) {
    109                        if( val.indexOf( '\"' ) >= 0 ) {
    110                                String temp = val ;
    111                                if( val.indexOf( "'" ) >= 0 ) { temp = val.replaceAll( "'","&#39;" ); }
    112                                buf.append( key ).append( "='" ).append( temp ).append( "' " );
    113                        }
    114                        else {
    115                                buf.append( key ).append( "=\"" ).append( val ).append( "\" " );
    116                        }
    117                }
    118        }
    119
    120        /**
    121         * タグの属性に、追加登録します。
    122         * 文字列として、key="value" の形式データを与えてください。連結時は、後ろに
    123         * スペースを一つ挟みますので、与える引数自体に連結用スペースを追加しておく
    124         * 必要はありません。
    125         * 通常は、tagName なしで作成した、Tagbuffer オブジェクトの makeTag() メソッドの
    126         * 返り値を渡しますが、Attributes.getAttribute() の返り値でも使用できます。
    127         * 引数が null の場合は、なにもしません。
    128         * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。
    129         *
    130         * @param       str     タグバッファーを追加します。
    131         * @see         #makeTag()
    132         * @see         Attributes#getAttribute()
    133         */
    134        public void add( final String str ) {
    135                if( cacheTag != null ) {
    136                        String errMsg = "makeTag() 実行後に、属性を追加することは出来ません。" ;
    137                        throw new RuntimeException( errMsg );
    138                }
    139
    140                if( str != null ) {
    141                        buf.append( str ).append( " " );
    142                }
    143        }
    144
    145        /**
    146         * タグの 整形された文字列を 作成します。
    147         * このメソッドは、tagName,body,属性より タグの完成形の文字列を作成します。
    148         * 作成された文字列は、内部でキャッシュされます。
    149         * BODY部を指定すると、&lt;tagName key="val" ･･･ &gt;body&lt;/tagName&gt; 形式になります。
    150         * BODY部が、null の場合は、 &lt;tagName key="val" ･･･ /&gt; 形式になります。
    151         * タグ名を指定しない(null)と、完成形のタグは、作成できません。
    152         * 属性リスト(key="value")の連結形式を返します。
    153         *
    154         * このメソッドの呼び出し以降では、setBody() も add() も実行できません。
    155         *
    156         * @return      整形された タグ文字列
    157         */
    158        public String makeTag() {
    159                if( cacheTag == null ) {
    160                        if( tagName != null ) {
    161                                if( body == null ) {
    162                                        buf.append( "/>" );
    163                                }
    164                                else {
    165                                        buf.append( ">" ).append( body );
    166                                        buf.append( "</" ).append( tagName ).append( ">" );
    167                                }
    168                        }
    169                        cacheTag = buf.toString();
    170                }
    171
    172                return cacheTag;
    173        }
    174
    175        /**
    176         * 行番号付きのタグの 整形された文字列を 作成します。
    177         * このメソッドは、makeTag() の結果より、[I] 文字列を引数の行番号と変換します。
    178         * これにより、動的に行番号つきの情報を属性に付与することが可能になります。
    179         * 内部にキャッシュされる値は、[I] 記号を変換していない状態の文字列です。
    180         * よって、このメソッドは、rowNo を変えて、何度でも呼び出すことは可能ですが、
    181         * setBody() や add() は実行できません。
    182         *
    183         * @param       rowNo   行番号([I] 文字列を変換します。)
    184         * @param       val     設定値([V] 文字列を変換します。)
    185         *
    186         * @return      整形された タグ文字列
    187         */
    188        public String makeTag( final int rowNo,final String val ) {
    189                String tag = makeTag();
    190                tag = StringUtil.replace( tag,"[I]",String.valueOf( rowNo ) );
    191                tag = StringUtil.replace( tag,"[V]",val );
    192
    193                return tag ;
    194        }
    195}