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.system; 017 018import java.util.function.Function; 019import java.util.function.IntFunction; // 6.4.4.2 (2016/04/01) 020import java.util.function.Supplier; // 6.4.4.2 (2016/04/01) 021 022/** 023 * 内部にStringBuilderを持った、文字列連結クラスです。 024 * 025 * 文字列連結時に、取り込む/取り込まないの判断を行う、boolean 付きの 026 * appendIf メソッドや、null値を無視する append など、用意しています。 027 * 028 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 029 * @og.rev 6.4.5.0 (2016/04/08) CharSequenceインタフェースの追加 030 * 031 * @og.group その他 032 * 033 * @version 6.0 034 * @author Kazuhiko Hasegawa 035 * @since JDK8.0, 036 */ 037public final class OgBuilder implements CharSequence { 038 private final StringBuilder buf = new StringBuilder( HybsConst.BUFFER_MIDDLE ); 039 040 /** 041 * デフォルトコンストラクター 042 * 043 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 044 */ 045 public OgBuilder() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 046 047 /** 048 * 引数の可変長文字列を追加する appendです。 049 * 050 * 引数の可変長文字列の個々の文字列が null の場合は、追加しません。 051 * 052 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 053 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 054 * 055 * @param arys 追加する可変長CharSequence 056 * @return 自分自身 057 * @og.rtnNotNull 058 */ 059 public OgBuilder append( final CharSequence... arys ) { 060 if( arys != null ) { 061 for( final CharSequence str : arys ) { 062 if( str != null ) { buf.append( str ); } 063 } 064 } 065 066 return this; 067 } 068 069 /** 070 * 連結文字列を、使用して、可変長引数のCharSequenceを連結して返します。 071 * 連結文字列が、null の場合は、CharSequenceをそのまま連結していきます。 072 * 連結するCharSequenceが null の場合は、連結しません。 073 * 連結文字列は、一番最後は出力されません。 074 * 075 * @og.rev 6.4.5.0 (2016/04/08) 新規追加 076 * 077 * @param delimiter 連結文字列 078 * @param arys 連結する可変長CharSequence 079 * 080 * @return 自分自身 081 * @og.rtnNotNull 082 */ 083 public OgBuilder join( final String delimiter , final CharSequence... arys ) { 084 if( delimiter == null ) { return append( arys ); } 085 086 if( arys != null ) { 087 boolean isAdd = false; 088 for( final CharSequence str : arys ) { 089 if( str != null && str.length() > 0 ) { 090 buf.append( str ).append( delimiter ); 091 isAdd = true; 092 } 093 } 094 if( isAdd ) { buf.setLength( buf.length()-delimiter.length() ); } // 最後に追加した delimiter を削除。 095 } 096 097 return this; 098 } 099 100 /** 101 * 引数の可変長文字列を内部バッファーから削除します。 102 * 103 * 引数の可変長文字列の個々の文字列が null の場合は、なにもしません。 104 * また、内部バッファーに存在しない場合も、何もしません。 105 * 106 * ※ 削除の指定は、CharSequenceではなく文字列です。 107 * 108 * @og.rev 6.4.5.0 (2016/04/08) 新規追加 109 * 110 * @param arys 削除する可変長文字列 111 * @return 自分自身 112 * @og.rtnNotNull 113 */ 114 public OgBuilder delete( final String... arys ) { 115 if( arys != null ) { 116 for( final String str : arys ) { 117 if( str != null ) { 118 final int len = str.length(); // 終了の位置を求めるのに使う。 119 int st; 120 while( ( st = buf.indexOf( str ) ) >= 0 ) { 121 buf.delete( st , st+len ); 122 } 123 } 124 } 125 } 126 127 return this; 128 } 129 130 /** 131 * 引数の可変長CharSequenceを追加し、最後に改行コードを追加する appendです。 132 * 133 * 引数の可変長CharSequenceの個々のCharSequenceが null の場合は、追加しません。 134 * 引数がnull値の場合は、改行コードのみ追加されます。 135 * 136 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 137 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 138 * 139 * @param arys 追加する文字列可変長(nullは追加しません) 140 * @return 自分自身 141 * @see #append( CharSequence... ) 142 * @og.rtnNotNull 143 */ 144 public OgBuilder appendCR( final CharSequence... arys ) { 145 return append( arys ).append( HybsConst.CR ); 146 } 147 148 /** 149 * 引数の可変長CharSequenceを追加する appendです。 150 * 151 * 引数の可変長CharSequenceの個々のCharSequenceの中に、一つでも null の場合は、 152 * すべて追加しません。 153 * 例えば、key="AAAA" のような文字列を構築したい場合、AAAA 部分が、nullの 154 * 場合は、key= の箇所も出しません。 155 * 156 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 157 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 158 * @og.rev 6.9.0.2 (2018/02/13) not null の対象に、ゼロ文字列も含むようにします。 159 * 160 * @param arys 追加する可変長CharSequence 161 * @return 自分自身 162 * @og.rtnNotNull 163 */ 164 public OgBuilder appendNN( final CharSequence... arys ) { 165 if( arys != null && arys.length > 0 ) { 166 final StringBuilder tmp = new StringBuilder( HybsConst.BUFFER_MIDDLE ); 167 for( final CharSequence str : arys ) { 168// if( str == null ) { return this; } // 一つでも null があれば、すぐに抜ける。 169 // 6.9.0.2 (2018/02/13) 一つでも nullか、ゼロ文字列 があれば、すぐに抜ける。 170 if( str == null || str.length() == 0 ) { return this; } 171 else { tmp.append( str ); } 172 } 173 buf.append( tmp ); 174 } 175 return this; 176 } 177 178 /** 179 * 文字列を追加するかどうか判定するフラグ付きのappendメソッドです。 180 * 181 * 引数の可変長CharSequenceの個々のCharSequenceが null の場合は、追加しません。 182 * 183 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 184 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 185 * 186 * @param flag 文字列を追加するかどうか判定するフラグ(trueの時のみ追加) 187 * @param arys 追加する可変長CharSequence 188 * @return 自分自身 189 * @og.rtnNotNull 190 */ 191 public OgBuilder appendIf( final boolean flag , final CharSequence... arys ) { 192 if( flag && arys != null ) { 193 for( final CharSequence str : arys ) { 194 if( str != null ) { buf.append( str ); } 195 } 196 } 197 198 return this; 199 } 200 201 /** 202 * 引数の可変長CharSequenceを追加し、最後に改行コードを追加する appendです。 203 * 204 * 引数の可変長CharSequenceの個々のCharSequenceが null の場合は、追加しません。 205 * 引数がnull値の場合は、改行コードのみ追加されます。 206 * 207 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 208 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 209 * 210 * @param flag 文字列を追加するかどうか判定するフラグ(trueの時のみ追加) 211 * @param arys 追加する可変長CharSequence 212 * @return 自分自身 213 * @see #appendIf( boolean,CharSequence... ) 214 * @og.rtnNotNull 215 */ 216 public OgBuilder appendIfCR( final boolean flag , final CharSequence... arys ) { 217 return appendIf( flag,arys ).append( HybsConst.CR ); 218 } 219 220 /** 221 * 関数を実行した結果を追加するかどうか判定するフラグ付きのappendメソッドです。 222 * 実行した結果が、null値の場合は、無視します。 223 * 引数が関数型インタフェースなので、遅延実行することが可能です。 224 * 225 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 226 * 227 * @param <T> 関数型インタフェース(Function)の引数(総称型) 228 * @param <R> 関数型インタフェース(Function)の戻り値(総称型) 229 * @param flag 追加するかどうか判定するフラグ(trueの時のみ追加) 230 * @param key 関数の引数(総称型) 231 * @param func 関数を実行した結果を追加する関数型(結果がnullの場合は追加しません) 232 * @return 自分自身 233 * @og.rtnNotNull 234 */ 235 public <T,R> OgBuilder appendIf( final boolean flag , final T key , final Function<? super T, ? extends R> func ) { 236 if( flag && func != null ) { 237 final R obj = func.apply( key ); 238 if( obj != null ) { buf.append( obj ); } 239 } 240 return this; 241 } 242 243 /** 244 * 開始から終了までの引数を有する関数を実行した結果を追加するときのappendメソッドです。 245 * 実行した結果が、null値の場合は、無視します。 246 * 引数が関数型インタフェースなので、遅延実行することが可能です。 247 * 関数の結果は、オブジェクトを返します。それを、内部でappendループします。 248 * 249 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 250 * @og.rev 6.4.4.2 (2016/04/01) IntFunction に変更。配列ではなく、オブジェクトに変更。 251 * 252 * @param <R> IntFunctionの戻り値の仮想型 253 * @param st ループカウンタの初期値(この値を含む) 254 * @param ed ループカウンタの終了値(この値を含まない) 255 * @param func 関数を実行した結果を追加する関数型(結果がnullの場合は追加しません) 256 * @return 自分自身 257 * @og.rtnNotNull 258 */ 259 public <R> OgBuilder appendRoop( final int st , final int ed , final IntFunction<R> func ) { 260 for( int i=st; i<ed; i++ ) { 261 final R obj = func.apply( i ); 262 if( obj != null ) { 263 buf.append( obj ); 264 } 265 } 266 return this; 267 } 268 269 /** 270 * 開始から終了までの引数を有する関数を実行した結果を追加するときのappendメソッドです。 271 * 連結文字列に null は指定できません。 272 * 連結文字列は、一番最後には使用しません。 273 * 274 * @og.rev 6.4.4.2 (2016/04/01) 連結文字列を指定。 275 * 276 * @param <R> IntFunctionの戻り値の仮想型 277 * @param st ループカウンタの初期値(この値を含む) 278 * @param ed ループカウンタの終了値(この値を含まない) 279 * @param delimiter 文字列連結する場合の文字列。nullは指定できません。 280 * @param func 関数を実行した結果を追加する関数型(結果がnullの場合は追加しません) 281 * @return 自分自身 282 * @og.rtnNotNull 283 */ 284 public <R> OgBuilder appendRoop( final int st , final int ed , final String delimiter , final IntFunction<R> func ) { 285 boolean fstFlg = true; 286 for( int i=st; i<ed; i++ ) { 287 final R obj = func.apply( i ); 288 if( obj != null ) { 289 if( fstFlg ) { 290 buf.append( obj ); 291 fstFlg = false; 292 } 293 else { 294 buf.append( delimiter ).append( obj ); 295 } 296 } 297 } 298 return this; 299 } 300 301 /** 302 * CharSequenceを追加するかどうか判定するフラグ付きのappendメソッドです。 303 * trueの場合は、第一引数を、falseの場合は、第二引数を追加します。 304 * 第二引数は、可変長CharSequenceです。 305 * ともに、CharSequenceがnullの場合は、無視します。 306 * 307 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 308 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 309 * 310 * @param flag CharSequenceを追加するかどうか判定するフラグ 311 * @param trueStr flagがtrueの場合に追加するCharSequence(一つだけ) 312 * @param falseStr flagがfalseの場合に追加する可変長CharSequence 313 * @return 自分自身 314 * @og.rtnNotNull 315 */ 316 public OgBuilder appendCase( final boolean flag , final CharSequence trueStr , final CharSequence... falseStr ) { 317 if( flag ) { 318 if( trueStr != null ) { buf.append( trueStr ); } 319 } 320 else { 321 if( falseStr != null ) { 322 for( final CharSequence str : falseStr ) { 323 if( str != null ) { buf.append( str ); } 324 } 325 } 326 } 327 328 return this; 329 } 330 331 /** 332 * CharSequenceを追加するかどうか判定するフラグ付きのappendメソッドです。 333 * trueの場合は、第一引数を、falseの場合は、第二引数を追加します。 334 * 第一引数、第二引数ともに、配列を返すSupplierクラスです。 335 * ともに、個々のCharSequenceがnullの場合は、無視します。 336 * 337 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 338 * @og.rev 6.4.4.2 (2016/04/01) 引数を、Supplierクラスに変更して、結果を複数指定できるようにします。 339 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 340 * 341 * @param flag CharSequenceを追加するかどうか判定するフラグ 342 * @param trueFunc flagがtrueの場合に実行するFunctionオブジェクト 343 * @param falseFunc flagがfalseの場合に追加するFunctionオブジェクト 344 * @return 自分自身 345 * @og.rtnNotNull 346 */ 347 public OgBuilder appendCase( final boolean flag 348 , final Supplier<CharSequence[]> trueFunc 349 , final Supplier<CharSequence[]> falseFunc ) { 350 if( flag ) { 351 final CharSequence[] tStrs = trueFunc.get(); 352 if( tStrs != null ) { 353 for( final CharSequence tStr : tStrs ) { 354 if( tStr != null ) { buf.append( tStr ); } 355 } 356 } 357 } 358 else { 359 final CharSequence[] fStrs = falseFunc.get(); 360 if( fStrs != null ) { 361 for( final CharSequence fStr : fStrs ) { 362 if( fStr != null ) { buf.append( fStr ); } 363 } 364 } 365 } 366 367 return this; 368 } 369 370 /** 371 * 内部のStringBuilderそのものを返します。 372 * 373 * StringBuilderを関数等に渡して追加処理する場合に、 374 * 内部のStringBuilderを渡して、処理させることが出来ます。 375 * 376 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 377 * 378 * @return 内部のStringBuilder 379 * @og.rtnNotNull 380 */ 381 public StringBuilder getBuilder() { 382 return buf; 383 } 384 385 /** 386 * 内部のStringBuilderをクリアします。 387 * 388 * 具体的には、StringBuilder#setLength(0) を実行します。 389 * 390 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 391 * 392 * @return 内部のStringBuilder 393 */ 394 public OgBuilder clear() { 395 buf.setLength(0); 396 return this; 397 } 398 399 // ********************************** 以下は、CharSequence インタフェース の実装 ********************************** 400 401 /** 402 * 指定されたインデックスのchar値を返します。 403 * 404 * インデックスは、0からlength() - 1の範囲になります。配列のインデックス付けの場合と同じように、 405 * シーケンスの最初のcharのインデックスは0、次の文字のインデックスは1と続きます。 406 * 407 * インデックスで指定されたchar値がサロゲートの場合、サロゲート値が返されます。 408 * 409 * @og.rev 6.4.5.0 (2016/04/08) 新規追加 410 * 411 * @param index 返されるchar値のインデックス 412 * @return 指定されたchar値 413 * @see java.lang.CharSequence#charAt(int) 414 */ 415 @Override // CharSequence 416 public char charAt( final int index ) { 417 return buf.charAt( index ); 418 } 419 420 /** 421 * この文字シーケンスの長さを返します。 422 * 423 * 長さはシーケンス内の16ビットcharの数に等しくなります。 424 * 425 * @og.rev 6.4.5.0 (2016/04/08) 新規追加 426 * 427 * @return このシーケンスのcharの数 428 * @see java.lang.CharSequence#length() 429 */ 430 @Override // CharSequence 431 public int length() { 432 return buf.length(); 433 } 434 435 /** 436 * この文字シーケンスの長さを返します。 437 * 438 * 長さはシーケンス内の16ビットcharの数に等しくなります。 439 * 440 * @og.rev 6.4.5.0 (2016/04/08) 新規追加 441 * 442 * @param start 開始インデックス(この値を含む) 443 * @param end 終了インデックス(この値を含まない) 444 * @return 指定されたサブシーケンス 445 * @see java.lang.CharSequence#subSequence(int,int) 446 */ 447 @Override // CharSequence 448 public CharSequence subSequence( final int start , final int end ) { 449 return buf.subSequence( start , end ); 450 } 451 452 /** 453 * このシーケンス内のデータを表す文字列を返します。 454 * 455 * 新しいStringオブジェクトが割り当てられ、現在このオブジェクトで表されている 456 * 文字シーケンスを含むように初期化されます。 457 * その後、このStringが返されます。その後このシーケンスが変更されても、Stringの内容には影響ありません。 458 * 459 * @og.rev 6.4.4.1 (2016/03/18) 新規追加 460 * 461 * @return この文字シーケンスの文字列表現。 462 * @see java.lang.CharSequence#toString() 463 * @og.rtnNotNull 464 */ 465 @Override // CharSequence 466 public String toString() { 467 return buf.toString(); 468 } 469}