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