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 tagBody = 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部を指定すると、<tagName key="val" ・・・ >body</tagName> 形式になります。 074 * BODY部が、null の場合は、 <tagName key="val" ・・・ /> 形式になります。 075 * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。 076 * 077 * @deprecated {@link TagBuffer#addBody(String)} 078 * @param body タグのBODY部 079 */ 080 public void setBody( final String body ) { 081 if( cacheTag != null ) { 082 String errMsg = "makeTag() 実行後に、BODY部の値を書き換えることは出来ません。" ; 083 throw new RuntimeException( errMsg ); 084 } 085 086 this.tagBody = body; 087 } 088 089 /** 090 * タグの BODY部を追加登録します。 091 * 092 * すでに、登録済みの場合は、その値に、追記します。 093 * そうでない場合(初めての場合)は、その値をセットします。 094 * null を登録した場合は、何もしません。 095 * ※ 従来あった #setBody(String)の様に、null を登録した場合、Body を 096 * リセットする機能はありません。新しいオブジェクトを作成してください。 097 * 098 * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。 099 * 100 * @og.rev 5.8.4.1 (2015/02/20) 6.1.1.0逆移植 #setBody(String) の代替えメソッドとして、新規追加 101 * 102 * @param body タグのBODY部に追加する文字列 103 * 104 * @return 自分自身 105 * @og.rtnNotNull 106 */ 107 public TagBuffer addBody( final String body ) { 108 return addBody( body,true ); 109 } 110 111 /** 112 * タグの BODY部を追加登録します。 113 * 114 * すでに、#setBody(String) で、登録済みの場合は、その値に、追記します。 115 * そうでない場合は、#setBody(String) と同じ動作になります。 116 * null を登録した場合は、何もしません。 117 * 118 * flag に、false を指定すると、追加登録しません。これは、if( flag ) { tagBuffer.addBody( body ); } 119 * の様な判定処理を、tagBuffer.body( body,flag ); に簡素化するために使用できます。 120 * TagBuffer は、StringBuilderの様に、メソッドの戻り値は、自分自身のオブジェクトなので、 121 * 上記の flag を使用して、切れ目なく連結させることが可能になります。 122 * 123 * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。 124 * 125 * @og.rev 5.8.4.1 (2015/02/20) 6.1.1.0逆移植 戻り値に、自分自身を返すようにします。 126 * 127 * @param body タグのBODY部に追加する文字列 128 * @param flag タグのBODY部に追加かどうかを決めるフラグ(true:追加する/false:何もしない) 129 * 130 * @return 自分自身 131 * @og.rtnNotNull 132 */ 133 public TagBuffer addBody( final String body,final boolean flag ) { 134 if( cacheTag != null ) { 135 final String errMsg = "makeTag() 実行後に、BODY部の値を書き換えることは出来ません。" ; 136 throw new RuntimeException( errMsg ); 137 } 138 139 if( flag && body != null ) { 140 if( tagBody !=null ) { tagBody += body; } 141 else { tagBody = body; } 142 } 143 144 return this ; 145 } 146 147 /** 148 * タグの 属性(key="value")を登録します。 149 * 属性は、key="value" の文字列を作成します。key か、value のどちらかが null 150 * の場合は、登録しません。 151 * value に、ダブルコーテーション(")が含まれている場合は、属性値をシングルコーテーション 152 * でくくります。 153 * 両方含まれている場合は、シングルコーテーションをエスケープ文字に変換します。 154 * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。 155 * 156 * @og.rev 3.8.6.1 (2006/10/20) シングルとダブルが混在する場合は、シングルをエスケープする 157 * 158 * @param key 属性キー (null の場合は、なにもしない) 159 * @param val 属性値 (null の場合は、なにもしない) 160 */ 161 public void add( final String key,final String val ) { 162 if( cacheTag != null ) { 163 String errMsg = "makeTag() 実行後に、属性を追加することは出来ません。" ; 164 throw new RuntimeException( errMsg ); 165 } 166 167 if( key != null && val != null ) { 168 if( val.indexOf( '\"' ) >= 0 ) { 169 String temp = val ; 170 if( val.indexOf( "'" ) >= 0 ) { temp = val.replaceAll( "'","'" ); } 171 buf.append( key ).append( "='" ).append( temp ).append( "' " ); 172 } 173 else { 174 buf.append( key ).append( "=\"" ).append( val ).append( "\" " ); 175 } 176 } 177 } 178 179 /** 180 * タグの属性に、追加登録します。 181 * 文字列として、key="value" の形式データを与えてください。連結時は、後ろに 182 * スペースを一つ挟みますので、与える引数自体に連結用スペースを追加しておく 183 * 必要はありません。 184 * 通常は、tagName なしで作成した、Tagbuffer オブジェクトの makeTag() メソッドの 185 * 返り値を渡しますが、Attributes.getAttribute() の返り値でも使用できます。 186 * 引数が null の場合は、なにもしません。 187 * このメソッドは、makeTag() が呼ばれた後は、登録できなくなります。 188 * 189 * @param str タグバッファーを追加します。 190 * @see #makeTag() 191 * @see Attributes#getAttribute() 192 */ 193 public void add( final String str ) { 194 if( cacheTag != null ) { 195 String errMsg = "makeTag() 実行後に、属性を追加することは出来ません。" ; 196 throw new RuntimeException( errMsg ); 197 } 198 199 if( str != null ) { 200 buf.append( str ).append( " " ); 201 } 202 } 203 204 /** 205 * タグの 整形された文字列を 作成します。 206 * このメソッドは、tagName,body,属性より タグの完成形の文字列を作成します。 207 * 作成された文字列は、内部でキャッシュされます。 208 * BODY部を指定すると、<tagName key="val" ・・・ >body</tagName> 形式になります。 209 * BODY部が、null の場合は、 <tagName key="val" ・・・ /> 形式になります。 210 * タグ名を指定しない(null)と、完成形のタグは、作成できません。 211 * 属性リスト(key="value")の連結形式を返します。 212 * 213 * このメソッドの呼び出し以降では、setBody() も add() も実行できません。 214 * 215 * @return 整形された タグ文字列 216 */ 217 public String makeTag() { 218 if( cacheTag == null ) { 219 if( tagName != null ) { 220 if( tagBody == null ) { 221 buf.append( "/>" ); 222 } 223 else { 224 buf.append( ">" ).append( tagBody ); 225 buf.append( "</" ).append( tagName ).append( ">" ); 226 } 227 } 228 cacheTag = buf.toString(); 229 } 230 231 return cacheTag; 232 } 233 234 /** 235 * 行番号付きのタグの 整形された文字列を 作成します。 236 * このメソッドは、makeTag() の結果より、[I] 文字列を引数の行番号と変換します。 237 * これにより、動的に行番号つきの情報を属性に付与することが可能になります。 238 * 内部にキャッシュされる値は、[I] 記号を変換していない状態の文字列です。 239 * よって、このメソッドは、rowNo を変えて、何度でも呼び出すことは可能ですが、 240 * setBody() や add() は実行できません。 241 * 242 * @param rowNo 行番号([I] 文字列を変換します。) 243 * @param val 設定値([V] 文字列を変換します。) 244 * 245 * @return 整形された タグ文字列 246 */ 247 public String makeTag( final int rowNo,final String val ) { 248 String tag = makeTag(); 249 tag = StringUtil.replace( tag,"[I]",String.valueOf( rowNo ) ); 250 tag = StringUtil.replace( tag,"[V]",val ); 251 252 return tag ; 253 } 254}