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.db; 017 018import java.sql.Connection; 019import java.sql.PreparedStatement; 020import java.sql.ParameterMetaData; 021import java.sql.SQLException; 022import java.util.Arrays; 023 024import org.opengion.fukurou.util.StringUtil; 025import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 026import org.opengion.fukurou.system.Closer; 027import org.opengion.fukurou.model.Formatter; 028import org.opengion.fukurou.model.ArrayDataModel; 029import org.opengion.fukurou.model.DataModel; // 8.2.1.0 (2022/07/15) 030import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 031import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 032 033/** 034 * DBTableModel インターフェースを継承した TableModel の実装クラスです。 035 * sql文を execute( query ) する事により、データベースを検索した結果を 036 * DBTableModel に割り当てます。 037 * 038 * メソッドを宣言しています 039 * DBTableModel インターフェースは、データベースの検索結果(Resultset)をラップする 040 * インターフェースとして使用して下さい。 041 * 042 * @og.rev 5.2.2.0 (2010/11/01) パッケージ移動(hayabusa.db ⇒ fukurou.db) 043 * @og.group DB/Shell制御 044 * 045 * @version 4.0 046 * @author Kazuhiko Hasegawa 047 * @since JDK5.0, 048 */ 049// 8.5.5.1 (2024/02/29) spotbugs CT_CONSTRUCTOR_THROW(コンストラクタで、Excweptionを出さない) class を final にすれば、警告は消える。 050// public class DBSimpleTable { 051public final class DBSimpleTable { 052 053 private final String[] names ; // データ配列に対応するカラム配列(names) 054 private String[] keys ; // 登録に使用するカラムキー配列(keys) 055 private int[] keysNo ; // 登録に使用するカラムキー配列番号 056 private String table ; // 登録テーブル名 057 private String where ; // where 条件式[カラム名]を含む 058 private int[] whereNo ; // [カラム名]に対応するデータ配列番号 059 private String[] constrain ; // key に対応した制約条件 060 061 private String connID ; // 登録に使用するコネクションID 062 private boolean useWhere ; // where が設定されると true にセットされます。 063 064 private Connection conn ; 065 private PreparedStatement pstmt ; 066 private ParameterMetaData pMeta ; // 5.1.2.0 (2010/01/01) setObject に、Type を渡す。(PostgreSQL対応) 067 private String query ; // エラーメッセージ用の変数 068 private int execCnt ; 069 private ApplicationInfo appInfo ; // 3.8.7.0 (2006/12/15) 070 private boolean useParamMetaData; // 5.1.2.0 (2010/01/01) setObject に、Type を渡す。(PostgreSQL対応) 071 072 /** 073 * データ配列のカラム名称配列を指定してオブジェクトを構築します。 074 * 075 * @param nm カラム名称配列 076 * @throws RuntimeException tbl が null の場合 077 */ 078 public DBSimpleTable( final String[] nm ) { 079 if( nm == null ) { 080 final String errMsg = "データ配列のカラム名称に null は設定できません。"; 081 throw new OgRuntimeException( errMsg ); 082 } 083 084 names = new String[nm.length]; 085 System.arraycopy( nm,0,names,0,names.length ); 086 } 087 088 /** 089 * 登録に使用するカラムキー配列(keys)を登録します。 090 * 091 * 引数のkey配列が null の場合は、names と同じカラム名称配列(names)が使用されます。 092 * キー配列(keys)は、一度しか登録できません。また、addConstrain等のメソッド 093 * 呼び出しを先に実行すると、カラム名称配列(names)が設定されてしまう為、 094 * その後にこのメソッドを呼び出すとエラーが発生します。 095 * 096 * @param key 登録カラム名称配列(可変長引数) 097 * @see #addConstrain( String ,String ) 098 * @throws RuntimeException すでに キー配列(keys)が登録済み/作成済みの場合 099 */ 100 public void setKeys( final String... key ) { 101 if( keys != null ) { 102 final String errMsg = "すでに キー配列(keys)が登録済みです。"; 103 throw new OgRuntimeException( errMsg ); 104 } 105 106 if( key != null && key.length > 0 ) { // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 107 final int size = key.length; 108 keys = new String[size]; 109 System.arraycopy( key,0,keys,0,size ); 110 111 constrain = new String[size]; 112 Arrays.fill( constrain,"?" ); 113 114 keysNo = new int[size]; 115 for( int i=0; i<size; i++ ) { 116 final int address = findAddress( names,keys[i] ); 117 if( address >= 0 ) { 118 keysNo[i] = address; 119 } 120 else { 121 final String errMsg = "指定の key は、カラム配列(names)に存在しません" 122 + " key[" + i + "]=" + key[i] 123 + " names=" + StringUtil.array2csv( names ) ; 124 throw new OgRuntimeException( errMsg ); 125 } 126 } 127 } 128 } 129 130 /** 131 * カラム名称配列(names)と同じキー配列(keys)を作成します。 132 * 133 * これは、キー配列(keys) が作成されなかった場合の処理です。 134 * keys が null の場合のみ、処理を実行します。 135 * 136 * @see #setKeys( String[] ) 137 */ 138 private void makeKeys() { 139 // キー配列(keys) が未設定の場合は、カラム名称配列(names)が設定されます。 140 if( keys == null ) { 141 keys = names; 142 final int size = keys.length; 143 144 constrain = new String[size]; 145 Arrays.fill( constrain,"?" ); 146 147 keysNo = new int[size]; 148 for( int i=0; i<size; i++ ) { 149 keysNo[i] = i; 150 } 151 } 152 } 153 154 /** 155 * Insert/Update/Delete 時の登録するテーブル名。 156 * 157 * @param tbl テーブル名 158 * @throws RuntimeException tbl が null の場合 159 */ 160 public void setTable( final String tbl ) { 161 if( tbl == null ) { 162 final String errMsg = "table に null は設定できません。"; // 5.1.8.0 (2010/07/01) errMsg 修正 163 throw new OgRuntimeException( errMsg ); 164 } 165 166 table = tbl; 167 } 168 169 /** 170 * データベースの接続先IDを設定します。 171 * 172 * @param conn 接続先ID 173 */ 174 public void setConnectionID( final String conn ) { 175 connID = conn; 176 } 177 178 /** 179 * アクセスログ取得の為、ApplicationInfoオブジェクトを設定します。 180 * 181 * @og.rev 3.8.7.0 (2006/12/15) 新規追加 182 * 183 * @param appInfo アプリ情報オブジェクト 184 */ 185 public void setApplicationInfo( final ApplicationInfo appInfo ) { 186 this.appInfo = appInfo; 187 } 188 189 /** 190 * Insert/Update/Delete 時の PreparedStatement の引数(クエスチョンマーク)制約。 191 * 192 * 制約条件(val)は、そのまま引数に使用されます。通常、? で表される 193 * パラメータに、文字長を制限する場合、SUBSTRB( ?,1,100 ) という 194 * val 変数を与えます。 195 * また、キー一つに対して、値を複数登録したい場合にも、使用できます。 196 * 例えば、NVAL( ?,? ) のような場合、キー一つに値2つを割り当てます。 197 * 値配列の並び順は、キー配列(keys)に対する(?の個数)に対応します。 198 * 注意:カラム名称配列(names)ではありません。また、先にキー配列(keys)を登録 199 * しておかないと、キー配列登録時にエラーが発生します。 200 * 制約条件は、処理するQUERYに対して適用されますので、 201 * key または、val が null の場合は、RuntimeException を Throwします。 202 * 203 * @param key 制約をかけるキー 204 * @param val 制約条件式 205 * @see #setKeys( String[] ) 206 * @throws RuntimeException key または、val が null の場合 207 */ 208 public void addConstrain( final String key,final String val ) { 209 if( key == null || val == null ) { 210 final String errMsg = "key または、val に null は設定できません。" 211 + " key=[" + key + "] , val=[" + val + "]" ; 212 throw new OgRuntimeException( errMsg ); 213 } 214 215 // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。 216 if( keys == null ) { makeKeys(); } 217 218 // 制約条件のアドレスは、カラム名称配列(names)でなく、キー配列(keys)を使用します。 219 final int address = findAddress( keys,key ); 220 if( address >= 0 ) { 221 constrain[address] = val; 222 } 223 else { 224 final String errMsg = "指定の key は、キー配列(keys)に存在しません" 225 + " key=[" + key + "] , val=[" + val + "]" 226 + " keys=" + StringUtil.array2csv( keys ) ; 227 throw new OgRuntimeException( errMsg ); 228 } 229 } 230 231 /** 232 * Update/Delete 時のキーとなるWHERE 条件のカラム名を設定します。 233 * 234 * 通常の WHERE 句の書き方と同じで、カラム配列(names)に対応する設定値(values)の値を 235 * 割り当てたい箇所に[カラム名] を記述します。文字列の場合、設定値をセットする 236 * ときに、シングルコーテーションを使用しますが、[カラム名]で指定する場合は、 237 * その前後に、(')シングルコーテーションは、不要です。 238 * WHERE条件は、登録に使用するキー配列(keys)に現れない条件で行を特定することがありますので 239 * カラム名称配列(names)を元にカラム名のアドレスを求めます。 240 * [カラム名]は、? に置き換えて、PreparedStatement として、実行される形式に変換されます。 241 * 例:FGJ='1' and CLM=[CLM] and SYSTEM_ID in ([SYSID],'**') 242 * 243 * @og.rev 4.3.4.0 (2008/12/01) キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てる 244 * @og.rev 5.0.2.0 (2009/11/01) バグ修正(keysはデータセットのキーなので、where句のカラムに含まれて入いるわけではない) 245 * @og.rev 6.4.1.2 (2016/01/22) PMD refactoring. where は、null をセットするのではなく、useWhere の設定で判定する。 246 * @og.rev 6.4.3.4 (2016/03/11) Formatterに新しいコンストラクターを追加する。 247 * @og.rev 6.9.5.0 (2018/04/23) カラム名が存在しない場合に、Exception を throw するかどうかを指定可能にする。 248 * 249 * @param wh WHERE条件のカラム名 250 * @throws RuntimeException [カラム名]がカラム配列(names)に存在しない場合 251 */ 252 public void setWhere( final String wh ) { 253 254 // 6.4.1.2 (2016/01/22) PMD refactoring. 255 if( wh == null || wh.isEmpty() ) { 256 useWhere= false; 257 } 258 else { 259 // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。 260 // 5.0.2.0 (2009/11/01) 261// final ArrayDataModel data = new ArrayDataModel( names ); 262// final ArrayDataModel data = new ArrayDataModel( names,true ); // 6.9.5.0 (2018/04/23) カラム名が存在しない場合に、Exception を throw する 263 final DataModel<String> data = new ArrayDataModel( names,true ); // 8.2.1.0 (2022/07/15) 264 final Formatter format = new Formatter( data,wh ); // 6.4.3.4 (2016/03/11) 265 where = format.getQueryFormatString(); 266 whereNo = format.getClmNos(); 267 useWhere= true; 268 } 269 } 270 271 /** 272 * データをインサートする場合に使用するSQL文を作成します。 273 * 274 * @og.rev 6.2.3.0 (2015/05/01) CSV形式の作成を、String#join( CharSequence , CharSequence... )を使用。 275 * 276 * @return インサートSQL 277 * @og.rtnNotNull 278 */ 279 private String getInsertSQL() { 280 // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。 281 if( keys == null ) { makeKeys(); } 282 283 // 6.2.3.0 (2015/05/01) CSV形式の作成を、String#join( CharSequence , CharSequence... )を使用。 284 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ) 285 .append( "INSERT INTO " ).append( table ) 286 .append( " ( " ) 287 .append( String.join( "," , keys ) ) // 6.2.3.0 (2015/05/01) 288 .append( " ) VALUES ( " ) 289 .append( String.join( "," , constrain ) ) // 6.2.3.0 (2015/05/01) 290 .append( " )" ); 291 292 useWhere = false; 293 294 return sql.toString(); 295 } 296 297 /** 298 * データをアップデートする場合に使用するSQL文を作成します。 299 * 300 * @og.rev 6.4.1.2 (2016/01/22) PMD refactoring. where は、null をセットするのではなく、useWhere の設定で判定する。 301 * 302 * @return アップデートSQL 303 * @og.rtnNotNull 304 */ 305 private String getUpdateSQL() { 306 // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。 307 if( keys == null ) { makeKeys(); } 308 309 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ) 310 .append( "UPDATE " ).append( table ).append( " SET " ) 311 .append( keys[0] ).append( " = " ).append( constrain[0] ); 312 313 for( int i=1; i<keys.length; i++ ) { 314 sql.append( " , " ) 315 .append( keys[i] ).append( " = " ).append( constrain[i] ); 316 } 317 318 // 6.4.1.2 (2016/01/22) PMD refactoring. 319 if( useWhere ) { 320 sql.append( " WHERE " ).append( where ); 321 } 322 323 return sql.toString(); 324 } 325 326 /** 327 * データをデリートする場合に使用するSQL文を作成します。 328 * 329 * @og.rev 5.0.2.0 (2009/11/01) バグ修正(削除時はkeysは必要ない) 330 * @og.rev 6.4.1.2 (2016/01/22) PMD refactoring. where は、null をセットするのではなく、useWhere の設定で判定する。 331 * 332 * @return デリートSQL 333 * @og.rtnNotNull 334 */ 335 private String getDeleteSQL() { 336 // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。 337 // 5.0.2.0 (2009/11/01) 338 keys = new String[0]; 339 340 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ) 341 .append( "DELETE FROM " ).append( table ); 342 343 // 6.4.1.2 (2016/01/22) PMD refactoring. 344 if( useWhere ) { 345 sql.append( " WHERE " ).append( where ); 346 } 347 348 return sql.toString(); 349 } 350 351 /** 352 * Insert 処理の開始を宣言します。 353 * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。 354 * このメソッドと、close() メソッドは必ずセットで処理してください。 355 * 356 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 357 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 358 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 359 * 360 * @throws SQLException Connection のオープンに失敗した場合 361 */ 362 public void startInsert() throws SQLException { 363 execCnt = 0; 364 query = getInsertSQL(); 365 conn = ConnectionFactory.connection( connID,appInfo ); 366 pstmt = conn.prepareStatement( query ); 367 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 368 useParamMetaData = ConnectionFactory.useParameterMetaData( connID ); // 5.3.8.0 (2011/08/01) 369 if( useParamMetaData ) { 370 pMeta = pstmt.getParameterMetaData(); 371 } 372 } 373 374 /** 375 * Update 処理の開始を宣言します。 376 * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。 377 * このメソッドと、close() メソッドは必ずセットで処理してください。 378 * 379 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 380 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 381 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 382 * 383 * @throws SQLException Connection のオープンに失敗した場合 384 */ 385 public void startUpdate() throws SQLException { 386 execCnt = 0; 387 query = getUpdateSQL(); 388 conn = ConnectionFactory.connection( connID,appInfo ); 389 pstmt = conn.prepareStatement( query ); 390 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 391 useParamMetaData = ConnectionFactory.useParameterMetaData( connID ); // 5.3.8.0 (2011/08/01) 392 if( useParamMetaData ) { 393 pMeta = pstmt.getParameterMetaData(); 394 } 395 } 396 397 /** 398 * Delete 処理の開始を宣言します。 399 * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。 400 * このメソッドと、close() メソッドは必ずセットで処理してください。 401 * 402 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 403 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 404 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 405 * 406 * @throws SQLException Connection のオープンに失敗した場合 407 */ 408 public void startDelete() throws SQLException { 409 execCnt = 0; 410 query = getDeleteSQL(); 411 conn = ConnectionFactory.connection( connID,appInfo ); 412 pstmt = conn.prepareStatement( query ); 413 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 414 useParamMetaData = ConnectionFactory.useParameterMetaData( connID ); // 5.3.8.0 (2011/08/01) 415 if( useParamMetaData ) { 416 pMeta = pstmt.getParameterMetaData(); 417 } 418 } 419 420 /** 421 * データ配列を渡して実際のDB処理を実行します。 422 * 423 * この処理の前に、startXXXX をコールしておき、INSER,UPDATE,DELETEのどの 424 * 処理を行うか、宣言しておく必要があります。 425 * 戻り値は、この処理での処理件数です。 426 * 最終件数は、close( boolean ) 時に取得します。 427 * 428 * @og.rev 4.0.0.0 (2007/11/28) SQLException をきちんと伝播させます。 429 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 430 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData 時の setNull 対応(PostgreSQL対応) 431 * 432 * @param values カラム配列(names)に対応する設定値配列(可変長引数) 433 * 434 * @return ここでの処理件数 435 * 436 * @see #close( boolean ) 437 * @throws SQLException Connection のクロースに失敗した場合 438 * @throws RuntimeException Connection DB処理の実行に失敗した場合 439 */ 440 public int execute( final String... values ) throws SQLException { 441 final int cnt; 442 try { 443 int clmNo = 1; // JDBC のカラム番号は、1から始まる。 444 445 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 446 if( useParamMetaData ) { 447 // keys に値を割り当てます。 448 for( int i=0; i<keys.length; i++ ) { 449 final int type = pMeta.getParameterType( clmNo ); 450 // 5.3.8.0 (2011/08/01) setNull 対応 451 final String val = values[keysNo[i]]; 452 if( val == null || val.isEmpty() ) { 453 pstmt.setNull( clmNo++, type ); 454 } 455 else { 456 pstmt.setObject( clmNo++,val,type ); 457 } 458 } 459 460 // where 条件を使用する場合は、値を割り当てます。 461 if( useWhere ) { 462 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach 463// for( int i=0; i<whereNo.length; i++ ) { 464 for( final int wNo : whereNo ) { 465 final int type = pMeta.getParameterType( clmNo ); 466 // 5.3.8.0 (2011/08/01) setNull 対応 467// final String val = values[whereNo[i]]; 468 final String val = values[wNo]; 469 if( val == null || val.isEmpty() ) { 470 pstmt.setNull( clmNo++, type ); 471 } 472 else { 473 pstmt.setObject( clmNo++,val,type ); 474 } 475 } 476 } 477 } 478 else { 479 // keys に値を割り当てます。 480 for( int i=0; i<keys.length; i++ ) { 481 pstmt.setObject( clmNo++,values[keysNo[i]] ); 482 } 483 484 // where 条件を使用する場合は、値を割り当てます。 485 if( useWhere ) { 486 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach 487// for( int i=0; i<whereNo.length; i++ ) { 488// pstmt.setObject( clmNo++,values[whereNo[i]] ); 489// } 490 for( final int wNo : whereNo ) { 491 pstmt.setObject( clmNo++,values[wNo] ); 492 } 493 } 494 } 495 496 cnt = pstmt.executeUpdate(); 497 execCnt += cnt; 498 } 499 catch( final SQLException ex) { 500 Closer.stmtClose( pstmt ); 501 pMeta = null; // 5.1.2.0 (2010/01/01) 502 if( conn != null ) { 503 conn.rollback(); 504 ConnectionFactory.remove( conn,connID ); 505 conn = null; 506 } 507 final String errMsg = "DB処理の実行に失敗しました。" + CR 508 + " query=[" + query + "]" + CR 509 + " values=" + StringUtil.array2csv( values ); 510 throw new OgRuntimeException( errMsg ,ex ); 511 } 512 return cnt; 513 } 514 515 /** 516 * DB処理をクロースします。 517 * 518 * 引数には、commit させる場合は、true を、rollback させる場合は、false をセットします。 519 * 戻り値は、今まで処理された合計データ件数です。 520 * この処理は、SQLException を内部で RuntimeException に変換している為、catch 節は 521 * 不要ですが、必ず finally 節で呼び出してください。そうしないと、リソースリークの 522 * 原因になります。 523 * 524 * @og.rev 5.1.2.0 (2010/01/01) pMeta のクリア 525 * 526 * @param commitFlag コミットフラグ [true:commitする/false:rollbacする] 527 * 528 * @return 今までの合計処理件数 529 */ 530 public int close( final boolean commitFlag ) { 531 try { 532// if( conn != null ) { // 8.1.1.2 (2022/02/25) Modify 533 if( conn != null && !conn.isClosed() ) { 534 if( commitFlag ) { conn.commit(); } 535 else { conn.rollback(); } 536 } 537 } 538 catch( final SQLException ex) { 539 ConnectionFactory.remove( conn,connID ); 540 conn = null; 541 final String errMsg = "DB処理を確定(COMMIT)できませんでした。" + CR 542 + " query=[" + query + "]" + CR ; 543 throw new OgRuntimeException( errMsg,ex ); 544 } 545 finally { 546 Closer.stmtClose( pstmt ); 547 pMeta = null; // 5.1.2.0 (2010/01/01) 548 ConnectionFactory.close( conn,connID ); 549 conn = null; 550 } 551 552 return execCnt; 553 } 554 555 /** 556 * 文字列配列中の値とマッチするアドレスを検索します。 557 * 文字列配列がソートされていない為、バイナリサーチが使えません。よって、 558 * 総当りでループ検索しています。 559 * 総数が多い場合は、遅くなる為、マップにセットして使用することを検討ください。 560 * 561 * @param data ターゲットの文字列配列中 562 * @param key 検索する文字列 563 * 564 * @return ターゲットの添え字(存在しない場合は、-1) 565 */ 566 private int findAddress( final String[] data,final String key ) { 567 int address = -1; 568 if( data != null && key != null ) { 569 for( int i=0; i<data.length; i++ ) { 570 if( key.equalsIgnoreCase( data[i] ) ) { 571 address = i; 572 break; 573 } 574 } 575 } 576 return address; 577 } 578}