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.hayabusa.taglib; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBConstValue; 021import org.opengion.fukurou.util.StringUtil; 022import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 023 024import static org.opengion.fukurou.util.StringUtil.nval; 025 026import java.util.Map; 027import java.util.LinkedHashMap; 028import java.util.Locale; // 6.4.1.2 (2016/01/22) 029 030/** 031 * TableUpdateTag にパラメーターを渡す為のタグクラスです。 032 * 033 * 汎用的なデータベース登録処理を行えるタグ tableUpdate タグを新規作成します。 034 * これは、具体的なSLQを作成する tableUpdateParam タグと組み合わせて使用できます。 035 * tableUpdate タグは、queryType に JDBCTableUpdate を指定します。基本的にこれだけ 036 * です。tableUpdateParam では、sqlType に、INSERT,COPY,UPDATE,MODIFY,DELETE の 037 * どれかを指定する事で、SQL文のタイプを指定します。COPY,MODIFY は command と 038 * 関連を持たす為に追加しているタイプで、UPDATE,INSERT と同じ処理を行います。 039 * tableUpdateParam の table には、作成したい SQL のテーブルを指定します。 040 * where 属性は、検索結果の DBTableModel の更新時に使用する条件を指定します。 041 * 042 * @og.formSample 043 * ●形式:<og:tableUpdate command="{@command}" queryType="JDBCTableUpdate" > 044 * <og:tableUpdateParam 045 * sqlType = "{@sqlType}" // INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE 046 * table = "{@TABLE_NAME}" // 処理対象のテーブル名 047 * names = "{@names}" // 処理対象のカラム名 048 * omitNames = "{@omitNames}" // 処理対象外のカラム名 049 * where = "{@where}" // 処理対象を特定するキー 050 * whereNames = "{@whereNames}" // 処理対象を特定するキー条件(where句)をCSV形式 051 * constKeys = "{@constKeys}" // 処理カラム名の中の固定情報カラム名 052 * constVals = "{@constVals}" // 処理カラム名の中の固定情報設定値 053 * asNames = "{@asNames}" // 別名を付けたカラム名(select A as B from TBL の B を指定) 054 * orgNames = "{@orgNames}" // tableの実際のカラム名(select A as B from TBL の A を指定) 055 * funcKeys = "{@funcKeys}" // 関数等を設定するカラム名 056 * funcVals = "{@funcVals}" // 関数等の設定値 057 * logicalDelete = "{@logicalDelete}" // sqlTypeがDELETEの場合にもUPDATE文を発行 058 * /> 059 * </og:tableUpdate> 060 * 061 * ●body:なし 062 * 063 * ●Tag定義: 064 * <og:tableUpdateParam 065 * sqlType ○【TAG】BODY部に書かれている SQLタイプを指定します(INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE)(必須) 066 * table ○【TAG】処理対象のテーブル名を指定します(必須) 067 * names 【TAG】処理対象のカラム名をCSV形式で複数指定します 068 * omitNames 【TAG】処理対象外のカラム名をCSV形式で複数指定します 069 * where 【TAG】処理対象を特定するキー条件(where句)を指定します 070 * whereNames 【TAG】処理対象を特定するキー条件(where句)をCSV形式で複数指定します 071 * insertOnly 【TAG】true に設定すると、sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない(初期値:false) 7.4.1.0 (2021/04/23) 072 * constKeys 【TAG】設定値を固定値と置き換える対象となるカラム名をCSV形式で複数指定します 073 * constVals 【TAG】設定値を固定値と置き換える対象となる設定値をCSV形式で複数指定します 074 * funcKeys 【TAG】関数等を設定するカラム名をCSV形式で複数指定します 075 * funcVals 【TAG】関数等の設定値をCSV形式で複数指定します 076 * asNames 【TAG】別名を付けたカラム名(select A as B from TBL の B を指定)をCSV形式で複数指定します 077 * orgNames 【TAG】tableの実際のカラム名(select A as B from TBL の A を指定)をCSV形式で複数指定します 078 * quotCheck 【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_SQL_INJECTION_CHECK[=true]) 079 * constObjKey 【TAG】固定情報カラムの処理オブジェクトを特定するキーを設定します(初期値:SYSTEM_ID) 080 * logicalDelete 【TAG】sqlType="DELETE"の場合に論理削除(UPDATE)を行うかどうかを指定します(初期値:false) 081 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 082 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 083 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 084 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 085 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 086 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 087 * /> 088 * 089 * ●使用例 090 * ・【entry.jsp】 091 * <og:tableUpdate command="{@command}" queryType="JDBCTableUpdate" > 092 * <og:tableUpdateParam 093 * sqlType = "{@sqlType}" 094 * table = "{@MEM.TABLE_NAME}" 095 * where = "ROWID = [ROWID]" 096 * /> 097 * </og:tableUpdate> 098 * 099 * @og.rev 3.8.8.0 (2007/12/22) 新規作成 100 * @og.rev 4.1.2.0 (2008/03/12) 実装の大幅な修正 101 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 102 * @og.group DB登録 103 * 104 * @version 4.0 105 * @author Kazuhiko Hasegawa 106 * @since JDK5.0, 107 */ 108public class TableUpdateParamTag extends CommonTagSupport { 109 /** このプログラムのVERSION文字列を設定します。 {@value} */ 110 private static final String VERSION = "8.3.0.3 (2022/08/26)" ; 111 private static final long serialVersionUID = 830320220826L ; 112 113 /** sqlType属性に設定できる値 {@value} */ 114// public static final String SQL_TYPE = "|INSERT|COPY|UPDATE|MODIFY|DELETE|" ; 115 public static final String SQL_TYPE = "|INSERT|COPY|UPDATE|MODIFY|DELETE|MERGE|" ; // 7.2.9.1 (2020/10/23) 116 117 // 3.8.0.4 (2005/08/08) 印刷時に使用するシステムID 118 private static final String SYSTEM_ID =HybsSystem.sys( "SYSTEM_ID" ); 119 120 // 4.3.6.0 (2009/05/01) デフォルトで利用するconstObjのシステムリソース名 121 private static final String DEFAULT_CONST_OBJ = HybsSystem.sys( "DEFAULT_CONST_CLASS" ); 122 123 private String sqlType ; // INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE 124 private String table ; // 処理対象のテーブル名 125 private String[] names ; // 処理対象のカラム名 126 private String omitNames = ",ROWID,ROWNUM,WRITABLE,"; // 処理対象外のカラム名 127 private String where ; // 処理対象を特定するキー 128 private String whereNames ; // 5.5.8.5 (2012/11/27) 処理対象を特定するCSV形式のカラム名 129 private boolean insertOnly; // 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 130 private String[] constKeys ; // 処理カラム名の中の固定情報カラム名 131 private String[] constVals ; // 処理カラム名の中の固定情報設定値 132 private String[] funcKeys ; // 5.5.1.9 (2012/04/19) 関数等を設定するカラム名 133 private String[] funcVals ; // 5.5.1.9 (2012/04/19) 関数等の設定値 134 private String[] asNames ; // 5.5.1.9 (2012/04/19) 別名を付けたカラム名(select A as B from TBL の B を指定) 135 private String[] orgNames ; // 5.5.1.9 (2012/04/19) tableの実際のカラム名(select A as B from TBL の A を指定) 136 private String constObjKey = SYSTEM_ID; // 固定情報カラムの処理オブジェクトを特定するキー 137 private boolean quotCheck = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" ); 138 private boolean logicalDelete; // 4.3.7.0 (2009/06/01) sqlTypeがDELETEの場合にもUPDATE文を発行 139 140 /** 141 * デフォルトコンストラクター 142 * 143 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 144 */ 145 public TableUpdateParamTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 146 147 /** 148 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 149 * 150 * @og.rev 5.5.1.9 (2012/04/19) エラーチェックを先に行います。 151 * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応 152 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 153 * 154 * @return 後続処理の指示( SKIP_BODY ) 155 */ 156 @Override 157 public int doStartTag() { 158 if( !useTag() ) { return SKIP_BODY ; } // 6.3.4.0 (2015/08/01) 159 160 // constKeys,constVals の個数チェック 161 if( constKeys != null ) { 162 if( constVals == null || constKeys.length != constVals.length ) { 163// final String errMsg = "<b>constKeys と、constVals の個数が異なります。</b><br />" 164 final String errMsg = "<b>constKeys と、constVals の個数が異なります。</b><br>" // 7.0.1.0 (2018/10/15) 165 + " constKeys=[" + StringUtil.array2csv( constKeys ) + "]" 166 + " constVals=[" + StringUtil.array2csv( constVals ) + "]" ; 167 throw new HybsSystemException( errMsg ); 168 } 169 } 170 171 // funcKeys,funcVals の個数チェック 172 if( funcKeys != null ) { 173 if( funcVals == null || funcKeys.length != funcVals.length ) { 174// final String errMsg = "<b>funcKeys と、funcVals の個数が異なります。</b><br />" 175 final String errMsg = "<b>funcKeys と、funcVals の個数が異なります。</b><br>" // 7.0.1.0 (2018/10/15) 176 + " funcKeys=[" + StringUtil.array2csv( funcKeys ) + "]" 177 + " funcVals=[" + StringUtil.array2csv( funcVals ) + "]" ; 178 throw new HybsSystemException( errMsg ); 179 } 180 } 181 182 // asNames,orgNames の個数チェック 183 if( orgNames != null ) { 184 if( asNames == null || orgNames.length != asNames.length ) { 185// final String errMsg = "<b>orgNames と、asNames の個数が異なります。</b><br />" 186 final String errMsg = "<b>orgNames と、asNames の個数が異なります。</b><br>" // 7.0.1.0 (2018/10/15) 187 + " orgNames=[" + StringUtil.array2csv( orgNames ) + "]" 188 + " asNames=[" + StringUtil.array2csv( asNames ) + "]" ; 189 throw new HybsSystemException( errMsg ); 190 } 191 } 192 193 return SKIP_BODY ; // Body を評価しない 194 } 195 196 /** 197 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 198 * 199 * @og.rev 4.3.7.0 (2009/06/01) 論理削除対応 200 * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応 201 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 202 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 203 * @og.rev 8.3.0.3 (2022/08/26) sqlType="MERGE" の場合、UPDATE文 に追加関連固定カラムキーが追加される不具合対応 204 * 205 * @return 後続処理の指示 206 */ 207 @Override 208 public int doEndTag() { 209 debugPrint(); 210// if( !useTag() ) { return EVAL_PAGE ; } // 6.3.4.0 (2015/08/01) 211 if( !useTag() || sqlType == null ) { return EVAL_PAGE ; } // 7.2.9.1 (2020/10/23) sqlType == null の時は、何もしない。 212 213 final TableUpdateTag updateTag = (TableUpdateTag)findAncestorWithClass( this,TableUpdateTag.class ); 214 if( updateTag == null ) { 215 final String errMsg = "<b>" + getTagName() + "タグは、TableUpdateTagの内側(要素)に記述してください。</b>"; 216 throw new HybsSystemException( errMsg ); 217 } 218 219 final String upSqlType = updateTag.getSqlType() ; 220 221 // 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 222 final boolean useInsert = "INSERT,COPY,MERGE".contains( sqlType ) ; 223 final boolean useUpdate = "UPDATE,MODIFY,MERGE".contains( sqlType ) || "DELETE".contains( sqlType ) && logicalDelete ; 224 final boolean useDelete = "DELETE".equals( sqlType ) && !logicalDelete ; 225 final boolean useMerge = "MERGE".contains( sqlType ) ; // 8.3.0.3 (2022/08/26) Add 226 227 if( upSqlType == null || upSqlType.equals( sqlType ) ) { 228 // 通常の names カラム配列を設定します。 229 if( names == null ) { names = updateTag.getNames(); } 230 final NamesData namesData = makeNamesData( names ); 231 232 // 8.3.0.3 (2022/08/26) Modify 233 if( useInsert ) { 234// updateTag.setQuery( "INSERT",getInsertSQL( namesData ) ); 235 final NamesData namesData1 = useMerge ? namesData.newInstance() : namesData; 236 updateTag.setQuery( "INSERT",getInsertSQL( namesData1 ) ); 237 } 238 if( useUpdate ) { 239 if( insertOnly ) { // 7.4.1.0 (2021/04/23) 240 updateTag.setQuery( "SELECT",getSelectSQL() ); 241 } 242 // 8.3.0.3 (2022/08/26) Modify 243 else { 244// updateTag.setQuery( "UPDATE",getUpdateSQL( namesData ) ); 245 final NamesData namesData2 = useMerge ? namesData.newInstance() : namesData; 246 updateTag.setQuery( "UPDATE",getUpdateSQL( namesData2 ) ); 247 } 248 } 249 if( useDelete ) { 250 updateTag.setQuery( "DELETE",getDeleteSQL() ); 251 } 252 } 253 254// // 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 255// if( upSqlType == null || upSqlType.equals( sqlType ) || ) { 256// String query = null; 257// if( "INSERT".equalsIgnoreCase( sqlType ) || "COPY".equalsIgnoreCase( sqlType ) ) { 258// query = getInsertSQL( namesData ); 259// } 260// else if( "UPDATE".equalsIgnoreCase( sqlType ) || "MODIFY".equalsIgnoreCase( sqlType ) 261// || ( "DELETE".equalsIgnoreCase( sqlType ) && logicalDelete ) ) { // 4.3.7.0 (2009/06/01) 262// query = getUpdateSQL( namesData ); 263// } 264// else if( "DELETE".equalsIgnoreCase( sqlType ) ) { 265// query = getDeleteSQL(); 266// } 267// 268// jspPrint( query ); 269// } 270 271 return EVAL_PAGE ; 272 } 273 274 /** 275 * タグリブオブジェクトをリリースします。 276 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 277 * 278 * @og.rev 4.3.7.0 (2009/06/01) logicalDelete属性追加 279 * @og.rev 5.5.1.9 (2012/04/19) asNames、orgNames、funcKeys、funcVals属性追加 280 * @og.rev 5.5.8.5 (2012/11/27) 処理対象を特定するCSV形式のカラム名 281 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 282 */ 283 @Override 284 protected void release2() { 285 super.release2(); // 3.5.6.0 (2004/06/18) 追加(抜けていた) 286 sqlType = null; // INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE 287 table = null; // 処理対象のテーブル名 288 names = null; // 処理対象のカラム名 289 omitNames = ",ROWID,ROWNUM,WRITABLE,"; // 処理対象外のカラム名 290 where = null; // 処理対象を特定するキー 291 whereNames = null; // 5.5.8.5 (2012/11/27) 処理対象を特定するCSV形式のカラム名 292 insertOnly = false; // 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 293 constKeys = null; // 処理カラム名の中の固定情報カラム名 294 constVals = null; // 処理カラム名の中の固定情報設定値 295 quotCheck = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" ); 296 constObjKey = SYSTEM_ID; // 固定情報カラムの処理オブジェクトを特定するキー 297 logicalDelete = false; // 4.3.7.0 (2009/06/01) 298 funcKeys = null; // 5.5.1.9 (2012/04/19) 関数等を設定するカラム名 299 funcVals = null; // 5.5.1.9 (2012/04/19) 関数等の設定値 300 asNames = null; // 5.5.1.9 (2012/04/19) 別名を付けたカラム名(select A as B from TBL の B を指定) 301 orgNames = null; // 5.5.1.9 (2012/04/19) tableの実際のカラム名(select A as B from TBL の A を指定) 302 } 303 304 /** 305 * 【TAG】BODY部に書かれている SQLタイプを指定します。 306 * 307 * @og.tag 308 * SQLタイプは、INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE の中から指定する 309 * 必要があります。これらは、内部に書かれるSQLの形式を指定するのに使用します。 310 * 内部処理は、DBTableModelの改廃コード(A,C,D)に対して使用される 311 * SQL を選択する場合の情報に使用されます。 312 * なお、COPY と MODIFY は、command で指定できる簡易機能として用意しています。 313 * 上位の TableUpdateTag の sqlType 属性 と同じsqlType 属性の場合のみ、SQL文を 314 * 合成・出力します。(上位のsqlTypeがnullの場合は、無条件実行します。) 315 * 指定のタイプが、異なる場合は、なにも処理を行いません。 316 * 317 * @param type SQLタイプ [INSERT/COPY/UPDATE/MODIFY/DELETE/MERGE] 318 */ 319 public void setSqlType( final String type ) { 320 sqlType = nval( getRequestParameter( type ),sqlType ); 321 if( sqlType != null && SQL_TYPE.indexOf( "|" + sqlType + "|" ) < 0 ) { 322 sqlType = null; 323 } 324 } 325 326 /** 327 * 【TAG】処理対象のテーブル名を指定します。 328 * 329 * @og.tag 330 * テーブル名を指定することで、sqlTypeに応じた QUERYを生成することが出来ます。 331 * 生成する場合のカラムを特定する場合は、names 属性で指定できます。 332 * また、WHERE条件は、where属性で指定します。 333 * 334 * @param tbl テーブル名 335 * @see #setNames( String ) 336 * @see #setWhere( String ) 337 * @see #setSqlType( String ) 338 */ 339 public void setTable( final String tbl ) { 340 table = nval( getRequestParameter( tbl ),table ); 341 } 342 343 /** 344 * 【TAG】処理対象のカラム名をCSV形式で複数指定します。 345 * 346 * @og.tag 347 * 生成するQUERYのカラム名をCSV形式(CSV)で複数指定します。 348 * 指定がない場合は、DBTableModel の全カラム(※)を使用して、QUERYを構築します。 349 * 一般に、テーブル結合してDBTableModelを構築した場合は、登録すべきカラムを 350 * 指定する必要があります。 351 * (※)正確には、DBTableModel の全カラムのうち、ROWID,ROWNUM,WRITABLE カラムは 352 * 無視します。 353 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 354 * 355 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 356 * 357 * @param nms カラム名 (CSV形式) 358 * @see #setTable( String ) 359 * @see #setOmitNames( String ) 360 */ 361 public void setNames( final String nms ) { 362 names = StringUtil.csv2Array( getRequestParameter( nms ) ); 363 if( names.length == 0 ) { names = null; } 364 } 365 366 /** 367 * 【TAG】処理対象外のカラム名をCSV形式で複数指定します。 368 * 369 * @og.tag 370 * 生成するQUERYのカラム名に指定しないカラム名をCSV形式(CSV)で複数指定します。 371 * 指定がない場合は、DBTableModel の全カラム(※)を使用して、QUERYを構築します。 372 * テーブル結合などで、処理したくないカラム数の方が少ない場合に、names ですべてを 373 * 指定するより少ない記述ですみます。 374 * (※)正確には、DBTableModel の全カラムのうち、ROWID,ROWNUM,WRITABLE カラムは 375 * 無視します。 376 * 377 * @param nms カラム名 (CSV形式) 378 * @see #setTable( String ) 379 * @see #setNames( String ) 380 */ 381 public void setOmitNames( final String nms ) { 382 omitNames = omitNames + nval( getRequestParameter( nms ),"" ) + ","; 383 } 384 385 /** 386 * 【TAG】処理対象を特定するキー条件(where句)を指定します。 387 * 388 * @og.tag 389 * 生成するQUERYのwhere 句を指定します。通常の WHERE 句の書き方と同じで、 390 * DBTableModelの値を割り当てたい箇所に[カラム名] を記述します。 391 * 文字列の場合、設定値をセットするときに、シングルコーテーションを 392 * 使用しますが、[カラム名]で指定する場合は、その前後に、(')シングル 393 * コーテーションは、不要です。 394 * {@XXXX}変数を使用する場合は、パース時に固定文字に置き換えられる為、 395 * 文字列指定時の(')シングルコーテーションが必要になります。 396 * ※ 5.5.8.5 (2012/11/27) whereNames 属性と併用した場合は、where が、and を付けて、文字列結合されます。 397 * 例:FGJ='1' and CLM=[CLM] and SYSTEM_ID in ([SYSID],'**') and KBSAKU='{@KBSAKU}' 398 * 399 * @param wr 検索条件 (where句) 400 */ 401 public void setWhere( final String wr ) { 402 where = nval( getRequestParameter( wr ),where ); 403 } 404 405 /** 406 * 【TAG】処理対象を特定するキー条件(where句)をCSV形式で複数指定します。 407 * 408 * @og.tag 409 * 生成するQUERYのwhere 句を指定する方法として、複数のカラム名をCSV指定し、内部で 410 * KEY=[KEY] 文字列を作成します。 411 * ここでは、カラム名は、データベースのカラム名と同じで、かつ、DBTableModel にも 412 * 同じカラムのデータが存在していること、という条件付きとします。 413 * また、where 条件との併用を行いますが、こちらの条件が先に使用され、where 条件は、 414 * and を付けて、文字列結合されます。 415 * 例: CLM,SYSTEM_ID,KBSAKU ⇒ CLM=[CLM] and SYSTEM_ID=[SYSTEM_ID] and KBSAKU=[KBSAKU] 416 * 417 * @og.rev 5.5.8.5 (2012/11/27) 新規追加 418 * 419 * @param wrnm 検索条件カラム (where句)作成のためのカラム名(CSV形式) 420 */ 421 public void setWhereNames( final String wrnm ) { 422 whereNames = nval( getRequestParameter( wrnm ),whereNames ); 423 } 424 425 /** 426 *【TAG】true に設定すると、sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない(初期値:false)。 427 * 428 * @og.tag 429 * true に設定すると、sqlType="MERGE" 時に、where条件で、検索して、存在しない場合は、追加します。 430 * 存在する場合は、何もしません。 431 * 何もしない(更新しない)ところが、通常のMERGEと異なる箇所です。 432 * 動作としては、UPDATEの代わりに、SELECT で判定します。 433 * 初期値は、false で、あれば更新、なければ追加処理を行います。 434 * 435 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 436 * 437 * @param flag "true" に設定すると、sqlType="MERGE" 時に、where条件で検索 438 */ 439 public void setInsertOnly( final String flag ) { 440 insertOnly = nval( getRequestParameter( flag ),insertOnly ); 441 } 442 443 /** 444 * 【TAG】設定値を固定値と置き換える対象となるカラム名をCSV形式で複数指定します。 445 * 446 * @og.tag 447 * names 属性のカラムや table 属性より、QUERYを作成して、DBTableModelの値を 448 * 割り当てる場合、DBTableModelの値ではなく、外部から指定した固定値を 449 * 割り当てたい場合に、そのカラム名をCSV形式(CSV)で複数指定します。 450 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 451 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 452 * 453 * @param keys 固定値カラム (CSV形式) 454 * @see #setConstVals( String ) 455 */ 456 public void setConstKeys( final String keys ) { 457 constKeys = getCSVParameter( keys ); 458 } 459 460 /** 461 * 【TAG】設定値を固定値と置き換える対象となる設定値をCSV形式で複数指定します。 462 * 463 * @og.tag 464 * names 属性のカラムや table 属性より、QUERYを作成して、DBTableModelの 465 * 値を割り当てる場合、DBTableModelの値ではなく、外部から指定した固定値を 466 * 割り当てたい場合に、そのカラム名に対応する設定値をCSV形式(CSV)で 467 * 複数指定します。ここで指定する設定値は、constKeys 属性と対応させます。 468 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 469 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 470 * 471 * @param vals 設定値(CSV形式) 472 * @see #setConstKeys( String ) 473 */ 474 public void setConstVals( final String vals ) { 475 constVals = getCSVParameter( vals ); 476 } 477 478 /** 479 * 【TAG】関数等を設定するカラム名をCSV形式で複数指定します。 480 * 481 * @og.tag 482 * constVals 属性で設定する値は、必ずシングルクオートが付与されます。 483 * その場合、関数などを設定したい場合でも、文字列として設定しようとします。 484 * ここで指定するカラム名(funcKeys)自身は、constKeys と同じ書式です。 485 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 486 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 487 * 488 * @og.rev 5.5.1.9 (2012/04/19) 新規追加 489 * 490 * @param keys 関数カラム (CSV形式) 491 * @see #setFuncVals( String ) 492 */ 493 public void setFuncKeys( final String keys ) { 494 funcKeys = getCSVParameter( keys ); 495 } 496 497 /** 498 * 【TAG】関数等の設定値をCSV形式で複数指定します。 499 * 500 * @og.tag 501 * funcKeys 属性に対応する 関数などの設定値を割り当てます。 502 * constVals 属性との違いは、funcVals の設定値は、そのままの形で、SQL文の 503 * 構築に使われます。 504 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 505 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 506 * 507 * @og.rev 5.5.1.9 (2012/04/19) 新規追加 508 * 509 * @param vals 関数設定値 (CSV形式) 510 * @see #setFuncKeys( String ) 511 */ 512 public void setFuncVals( final String vals ) { 513 funcVals = getCSVParameter( vals ); 514 } 515 516 /** 517 * 【TAG】別名を付けたカラム名(select A as B from TBL の B を指定)をCSV形式で複数指定します。 518 * 519 * @og.tag 520 * SELECT 文を記述したとき、別名を付けていたり、SELECTしたテーブルと別のテーブルに 521 * DBTableModelの値を書き込む場合、DBTableModel の持っているカラム名と、実際に 522 * 書き込むカラム名が異なります。そのようなケースに、元の別名カラムを指定します。 523 * orgNames属性の並び順と、asNames属性の並び順を合わせておく必要があります。 524 * このカラム名は、DBTableModel には持っているが、テーブル側には持っていない値 525 * なので、内部的に omitNames 属性に値を設定します。利用者は、omitNames に 526 * 書き込む必要はありません。 527 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 528 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 529 * 530 * @og.rev 5.5.1.9 (2012/04/19) 新規追加 531 * 532 * @param keys 別名カラム (CSV形式) 533 * @see #setOrgNames( String ) 534 */ 535 public void setAsNames( final String keys ) { 536 asNames = getCSVParameter( keys ); 537 } 538 539 /** 540 * 【TAG】tableの実際のカラム名(select A as B from TBL の A を指定)をCSV形式で複数指定します。 541 * 542 * @og.tag 543 * SELECT 文を記述したとき、別名を付けていたり、SELECTしたテーブルと別のテーブルに 544 * DBTableModelの値を書き込む場合、DBTableModel の持っているカラム名と、実際に 545 * 書き込むカラム名が異なります。そのようなケースに、テーブルの実カラムを指定します。 546 * orgNames属性の並び順と、asNames属性の並び順を合わせておく必要があります。 547 * このカラム名は、DBTableModel には持っていませんが、テーブル側には持っている値 548 * なので、このカラム名で、SQL文を構築します。 UPDATE TBL SET A=[B] WHERE … となります。 549 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 550 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 551 * 552 * @og.rev 5.5.1.9 (2012/04/19) 新規追加 553 * 554 * @param keys 実カラム (CSV形式) 555 * @see #setAsNames( String ) 556 */ 557 public void setOrgNames( final String keys ) { 558 orgNames = getCSVParameter( keys ); 559 } 560 561 /** 562 * 【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します 563 * (初期値:USE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])。 564 * 565 * @og.tag 566 * SQLインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに 567 * 渡す文字列にシングルクォート(') を許さない設定にすれば、ある程度は防止できます。 568 * 数字タイプの引数には、 or 5=5 などのシングルクォートを使用しないコードを埋めても、 569 * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、 570 * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。 571 * (') が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。 572 * (初期値:システム定数のUSE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])。 573 * 574 * @param flag クォートチェック [true:する/それ以外:しない] 575 * @see org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK 576 */ 577 public void setQuotCheck( final String flag ) { 578 quotCheck = nval( getRequestParameter( flag ),quotCheck ); 579 } 580 581 /** 582 * 【TAG】固定情報カラムの処理オブジェクトを特定するキーを設定します(初期値:SYSTEM_ID)。 583 * 584 * @og.tag 585 * 固定情報カラム をシステム単位にJavaクラスで管理できます。 586 * そのクラスオブジェクトは、org.opengion.hayabusa.db.DBConstValue インターフェースを 587 * 継承した、plugin クラスになります。 588 * そのクラスを特定するキーワードを指定します。 589 * 初期値は、SYSTEM_ID でシステム単位にクラスを作成します。 590 * もし、他のシステムと共通の場合は、継承だけさせることも可能です。 591 * 対応したDBConstValueクラスがプラグインとして存在しない場合は、 592 * システムリソースのDEFAULT_CONST_CLASSで指定されたクラスが利用されます。 593 * 固定情報カラムを使用しない場合は、constObjKey="" をセットしてください。 594 * 595 * 初期値は、SYSTEM_ID です。 596 * 597 * @og.rev 6.9.8.0 (2018/05/28) 固定情報カラムを使用しない場合は、constObjKey="" をセット。 598 * 599 * @param key 固定カラムキー 600 */ 601 public void setConstObjKey( final String key ) { 602// constObjKey = nval( getRequestParameter( key ),constObjKey ); 603 final String objKey = getRequestParameter( key ); 604 if( objKey != null ) { constObjKey = objKey; } 605 } 606 607 /** 608 * 【TAG】sqlType="DELETE"の場合に論理削除(UPDATE)を行うかどうかを指定します(初期値:false)。 609 * 610 * @og.tag 611 * sqlType="DELETE"の場合に論理削除(UPDATE)を行うかどうかを指定します。 612 * trueが指定された場合は、DELETE文ではなく、UPDATE文が発行されます。 613 * falseが指定された場合は、DELETE文が発行されます。 614 * さらに論理削除を行う場合、org.opengion.hayabusa.db.DBConstValue インターフェースに 615 * 定義されている、getLogicalDeleteKeys()及びgetLogicalDeleteValsを実装することで、 616 * 論理削除する際のフラグの更新方法を統一的に管理することが可能になります。 617 * 初期値は、false(物理削除する)です 618 * 619 * @param flag 論理削除可否 [true:UPDATE文/false:DELETE文] 620 */ 621 public void setLogicalDelete( final String flag ) { 622 logicalDelete = nval( getRequestParameter( flag ),logicalDelete ); 623 } 624 625 /** 626 * データをインサートする場合に使用するSQL文を作成します。 627 * 628 * @og.rev 4.1.2.1 (2008/03/17) DBConstValue による固定値セットを採用 629 * @og.rev 4.3.6.4 (2009/05/01) デフォルト設定をシステムリソースで設定可能にする 630 * @og.rev 5.3.4.0 (2011/04/01) DEFAULT_CONST_OBJの初期値変更(null→ゼロ文字列) 631 * @og.rev 6.2.3.0 (2015/05/01) CSV形式の作成を、String#join( CharSequence , CharSequence... )を使用。 632 * 633 * @param namesData NamesDataオブジェクト 634 * 635 * @return インサートSQL 636 * @og.rtnNotNull 637 */ 638 private String getInsertSQL( final NamesData namesData ) { 639 String cls = HybsSystem.sys( "DBConstValue_" + constObjKey ) ; 640 641 // 4.3.6.4 (2009/05/01) 標準の追加 642 if( cls == null){ 643 cls = DEFAULT_CONST_OBJ; 644 } 645 646 if( cls != null && !cls.isEmpty() ) { 647 final DBConstValue constVal = HybsSystem.newInstance( cls ); 648 // 4.2.1.0 (2008/04/16) 初期化追加 649 constVal.init( table,getUser().getUserID(),getGUIInfoAttri( "KEY" ) ); 650 final String[] keys = constVal.getInsertKeys(); 651 final String[] vals = constVal.getInsertVals(); 652 namesData.add( keys,vals ); 653 } 654 655 final String[] nms = namesData.getNames(); 656 final String[] vls = namesData.getVals(); 657 658 // 6.2.3.0 (2015/05/01) CSV形式の作成を、String#join( CharSequence , CharSequence... )を使用。 659 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ) 660 .append( "INSERT INTO " ).append( table ) 661 .append( " ( " ) 662 .append( String.join( "," , nms ) ) // 6.2.3.0 (2015/05/01) 663 .append( " ) VALUES ( " ) 664 .append( String.join( "," , vls ) ) // 6.2.3.0 (2015/05/01) 665 .append( " )" ); 666 667 return sql.toString(); 668 } 669 670 /** 671 * データをアップデートする場合に使用するSQL文を作成します。 672 * 673 * where と whereNames が同時に指定された場合は、whereNames が先に処理され 674 * where 条件は、and 結合されます。 675 * 676 * @og.rev 4.1.2.1 (2008/03/17) DBConstValue による固定値セットを採用 677 * @og.rev 4.3.6.4 (2009/05/01) デフォルト設定をシステムリソースで設定可能にする 678 * @og.rev 4.3.7.0 (2009/06/01) 論理削除対応 679 * @og.rev 5.3.7.0 (2011/07/01) DEFAULT_CONST_OBJの初期値変更(null→ゼロ文字列) 対応忘れ 680 * @og.rev 5.5.8.5 (2012/11/27) whereNames 対応 681 * 682 * @param namesData NamesDataオブジェクト 683 * 684 * @return アップデートSQL 685 * @og.rtnNotNull 686 */ 687 private String getUpdateSQL( final NamesData namesData ) { 688 String cls = HybsSystem.sys( "DBConstValue_" + constObjKey ) ; 689 690 // 4.3.6.4 (2009/05/01) 標準の追加 691 if( cls == null){ 692 cls = DEFAULT_CONST_OBJ; 693 } 694 695 if( cls != null && !cls.isEmpty() ) { // 5.3.7.0 (2011/07/01) 696 final DBConstValue constVal = HybsSystem.newInstance( cls ); 697 // 4.2.1.0 (2008/04/16) 初期化追加 698 constVal.init( table,getUser().getUserID(),getGUIInfoAttri( "KEY" ) ); 699 // 4.3.7.0 (2009/06/01) 論理削除対応 700 String[] keys = null; 701 String[] vals = null; 702 if( "DELETE".equalsIgnoreCase( sqlType ) ) { 703 keys = constVal.getLogicalDeleteKeys(); 704 vals = constVal.getLogicalDeleteVals(); 705 } 706 else { 707 keys = constVal.getUpdateKeys(); 708 vals = constVal.getUpdateVals(); 709 } 710 namesData.add( keys,vals ); 711 } 712 713 final String[] nms = namesData.getNames(); 714 final String[] vls = namesData.getVals(); 715 716 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ) 717 .append( "UPDATE " ).append( table ).append( " SET " ) 718 .append( nms[0] ).append( '=' ).append( vls[0] ); // 6.0.2.5 (2014/10/31) char を append する。 719 720 for( int i=1; i<nms.length; i++ ) { 721 sql.append( ',' ).append( nms[i] ).append( '=' ).append( vls[i] ); // 6.0.2.5 (2014/10/31) char を append する。 722 } 723 724 // 5.5.8.5 (2012/11/27) whereNames 対応 725 String whereAnd = " WHERE " ; 726 if( whereNames != null && whereNames.length() > 0 ) { 727 final String[] wnms = whereNames.split(","); 728 sql.append( whereAnd ).append( wnms[0] ).append( "=[" ).append( wnms[0] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 729 730 for( int i=1; i<wnms.length; i++ ) { 731 sql.append( " AND " ).append( wnms[i] ).append( "=[" ).append( wnms[i] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 732 } 733 whereAnd = " AND " ; // whereNames 優先。ここを通らなければ、初期値のまま、" WHERE " が使われる 734 } 735 736 // 5.5.8.5 (2012/11/27) whereNames 対応。whereNames が登録されていれば、AND で繋げる。 737 if( where != null && where.length() > 0 ) { 738 sql.append( whereAnd ).append( where ); 739 } 740 741 return sql.toString(); 742 } 743 744 /** 745 * データをデリートする場合に使用するSQL文を作成します。 746 * 747 * where と whereNames が同時に指定された場合は、whereNames が先に処理され 748 * where 条件は、and 結合されます。 749 * 750 * @og.rev 5.5.8.5 (2012/11/27) whereNames 対応 751 * 752 * @return デリートSQL 753 * @og.rtnNotNull 754 */ 755 private String getDeleteSQL() { 756 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ); 757 sql.append( "DELETE FROM " ).append( table ); 758 759 // 5.5.8.5 (2012/11/27) whereNames 対応 760 String whereAnd = " WHERE " ; 761 if( whereNames != null && whereNames.length() > 0 ) { 762 final String[] wnms = whereNames.split(","); 763 sql.append( whereAnd ).append( wnms[0] ).append( "=[" ).append( wnms[0] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 764 765 for( int i=1; i<wnms.length; i++ ) { 766 sql.append( " AND " ).append( wnms[i] ).append( "=[" ).append( wnms[i] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 767 } 768 whereAnd = " AND " ; // whereNames 優先。ここを通らなければ、初期値のまま、" WHERE " が使われる 769 } 770 771 // 5.5.8.5 (2012/11/27) whereNames 対応。whereNames が登録されていれば、AND で繋げる。 772 if( where != null && where.length() > 0 ) { 773 sql.append( whereAnd ).append( where ); 774 } 775 return sql.toString(); 776 } 777 778 /** 779 * データを検索する場合に使用するSQL文を作成します。 780 * 781 * where と whereNames が同時に指定された場合は、whereNames が先に処理され 782 * where 条件は、and 結合されます。 783 * 784 * これは、sqlType="MERGE" 時に、insertOnly="true" が指定された時に、呼ばれます。 785 * 786 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 787 * 788 * @return 検索SQL 789 * @og.rtnNotNull 790 */ 791 private String getSelectSQL() { 792 final StringBuilder sql = new StringBuilder( BUFFER_MIDDLE ); 793 sql.append( "SELECT count(*) FROM " ).append( table ); 794 795 // 5.5.8.5 (2012/11/27) whereNames 対応 796 String whereAnd = " WHERE " ; 797 if( whereNames != null && whereNames.length() > 0 ) { 798 final String[] wnms = whereNames.split(","); 799 sql.append( whereAnd ).append( wnms[0] ).append( "=[" ).append( wnms[0] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 800 801 for( int i=1; i<wnms.length; i++ ) { 802 sql.append( " AND " ).append( wnms[i] ).append( "=[" ).append( wnms[i] ).append( ']' ); // 6.0.2.5 (2014/10/31) char を append する。 803 } 804 whereAnd = " AND " ; // whereNames 優先。ここを通らなければ、初期値のまま、" WHERE " が使われる 805 } 806 807 // 5.5.8.5 (2012/11/27) whereNames 対応。whereNames が登録されていれば、AND で繋げる。 808 if( where != null && where.length() > 0 ) { 809 sql.append( whereAnd ).append( where ); 810 } 811 return sql.toString(); 812 } 813 814 /** 815 * names,constKeys,omitNames から、必要なキー情報と、属性情報を持った NamesData を作成します。 816 * 817 * @og.rev 4.1.2.1 (2008/03/17) 固定値の constVals の前後に、"'" を入れる。 818 * @og.rev 5.5.1.9 (2012/04/19) asNames、orgNames、funcKeys、funcVals属性追加 819 * 820 * @param nms カラム名配列(可変長引数) 821 * 822 * @return 属性情報を持ったNamesData 823 */ 824 private NamesData makeNamesData( final String... nms ) { 825 final NamesData namesData = new NamesData(); 826 827 // 5.5.1.9 (2012/04/19) omitNames に、asNames配列の値を設定しておきます。 828 if( asNames != null ) { 829 for( int i=0; i<asNames.length; i++ ) { 830 if( asNames[i] != null && asNames[i].length() > 0 ) { 831 omitNames = omitNames + asNames[i] + ","; 832 } 833 } 834 } 835 836 // names で指定されたカラム名 837 for( int i=0; i<nms.length; i++ ) { 838 final String nm = nms[i]; 839 if( nm != null && nm.length() > 0 && omitNames.indexOf( "," + nm + "," ) < 0 ) { 840 namesData.add( nm,"[" + nm + "]" ) ; 841 } 842 } 843 844 // 固定値の constKeys カラム配列を設定します。 845 if( constKeys != null && constKeys.length > 0 ) { 846 for( int j=0; j<constKeys.length; j++ ) { 847 final String nm = constKeys[j]; 848 if( nm != null && nm.length() > 0 ) { 849 namesData.add( nm,"'" + constVals[j] + "'" ) ; // constVals は、シングルクオートで囲います。 850 } 851 } 852 } 853 854 // 関数値の funcKeys カラム配列を設定します。 855 if( funcKeys != null && funcKeys.length > 0 ) { 856 for( int j=0; j<funcKeys.length; j++ ) { 857 final String nm = funcKeys[j]; 858 if( nm != null && nm.length() > 0 ) { 859 namesData.add( nm, funcVals[j] ) ; // funcVals は、シングルクオートで囲いません。 860 } 861 } 862 } 863 864 // 別名の asNames,orgNames カラム配列を設定します。 865 if( orgNames != null && orgNames.length > 0 ) { 866 for( int j=0; j<orgNames.length; j++ ) { 867 final String onm = orgNames[j]; 868 if( onm != null && onm.length() > 0 ) { 869 namesData.add( onm,"[" + asNames[j] + "]" ) ; 870 } 871 } 872 } 873 874 return namesData ; 875 } 876 877 /** 878 * 内部データを受け渡す為の、簡易クラスです。 879 * 更新するカラム名と値のセット配列を管理しています。 880 * 881 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 882 * ※ classのfinal化と変数のprivate化、メソッドの修飾子なし(パッケージプライベート)化を行います。 883 * @og.rev 6.4.1.2 (2016/01/22) nameの値を、大文字小文字の区別をなくすために、常に大文字で登録します。 884 */ 885 private static final class NamesData { 886 private final Map<String,String> nameMap = new LinkedHashMap<>() ; 887 888 /** 889 * 内部のMapをコピーした新しいインスタンスを返します。 890 * 891 * @og.rev 8.3.0.3 (2022/08/26) sqlType="MERGE" の場合、UPDATE文 に追加関連固定カラムキーが追加される不具合対応 892 * 893 * @return 新しいインスタンス 894 */ 895 /* default */ NamesData newInstance () { 896 final NamesData newNames = new NamesData(); 897 newNames.nameMap.putAll( nameMap ); 898 return newNames; 899 } 900 901 /** 902 * キーと値のセットを追加します。 903 * 904 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 905 * @og.rev 6.4.1.2 (2016/01/22) nameの値を、大文字小文字の区別をなくすために、常に大文字で登録します。 906 * 907 * @param nm キー(大文字のみ。内部で変換しておきます。) 908 * @param val 値 909 */ 910 /* default */ void add( final String nm,final String val ) { 911 nameMap.put( nm.toUpperCase(Locale.JAPAN),val ); 912 } 913 914 /** 915 * キー配列と対応する、値配列のセットを追加します。 916 * 917 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 918 * 919 * @param nms キー配列 920 * @param vals 値配列 921 */ 922 /* default */ void add( final String[] nms,final String[] vals ) { 923 if( nms != null ) { 924 for( int i=0; i<nms.length; i++ ) { 925 nameMap.put( nms[i].toUpperCase(Locale.JAPAN),vals[i] ); 926 } 927 } 928 } 929 930 /** 931 * キー配列を返します。 932 * 933 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 934 * 935 * @return キー配列 936 * @og.rtnNotNull 937 */ 938 /* default */ String[] getNames() { 939 return nameMap.keySet().toArray( new String[nameMap.size()] ); 940 } 941 942 /** 943 * 値配列を返します。 944 * 945 * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。 946 * 947 * @return 値配列 948 * @og.rtnNotNull 949 */ 950 /* default */ String[] getVals() { 951 return nameMap.values().toArray( new String[nameMap.size()] ); 952 } 953 } 954 955 /** 956 * このオブジェクトの文字列表現を返します。 957 * 基本的にデバッグ目的に使用します。 958 * 959 * @return このクラスの文字列表現 960 * @og.rtnNotNull 961 */ 962 @Override 963 public String toString() { 964 return ToString.title( this.getClass().getName() ) 965 .println( "VERSION" ,VERSION ) 966 .println( "sqlType" ,sqlType ) 967 .println( "table" ,table ) 968 .println( "names" ,names ) 969 .println( "omitNames" ,omitNames ) 970 .println( "where" ,where ) 971 .println( "whereNames" ,whereNames ) 972 .println( "constKeys" ,constKeys ) 973 .println( "constVals" ,constVals ) 974 .println( "logicalDelete" ,logicalDelete ) 975 .fixForm().toString() ; 976 } 977}