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 static org.opengion.fukurou.util.StringUtil.nval;
019
020import java.util.Arrays;
021import java.util.Enumeration;
022import java.util.Locale;
023import java.util.Set;
024import java.util.TreeSet;
025
026import org.opengion.fukurou.util.ErrorMessage;
027import org.opengion.fukurou.util.StringUtil;
028import org.opengion.hayabusa.common.HybsSystem;
029import org.opengion.hayabusa.common.HybsSystemException;
030import org.opengion.hayabusa.db.DBColumn;
031import org.opengion.hayabusa.db.DBTableModel;
032
033/**
034 * 登録データの物理チェック(整合性チェック、nullチェック)を行うタグです。
035 *
036 * コマンドに対応したチェック方式で、指定のカラムをチェックします。
037 * command="NEW" の場合は、columns 引数にCSV形式で指定したカラム名より
038 * リクエスト情報を取得して、値をチェックします。
039 * 引数チェックでは、"%" や "_" などのあいまい検索時に指定する記号を
040 * 含むとエラーになるカラムはチェック対象からはずす必要がある為、
041 * チェックすべきカラムを指定する必要があります。
042 * command="ENTRY" の場合は、columns 引数に無関係に、全てのリクエストされたカラム
043 * の値をチェックします。これは、先の検索時の場合と異なり、ENTRYでは
044 * データベースに値を設定する為、無条件にチェックする必要があります。
045 * nullCheck は、command に無関係に指定のカラムが null (ゼロ文字列)かどうかを
046 * 判定します。
047 * maxRowCount は、一覧検索時のチェックされた件数が、指定の値を超えた場合に
048 * エラーになります。minRowCount は、同様に、最小選択件数(設定値を含む)の指定です。
049 * このタグは、エラー時には、それ以降のJSP画面を評価しません。BODY 部に記述された
050 * 値は、エラー時のみ表示され、正常時には、なにも表示されません。これは、エラー時の
051 * メッセージや、ユーザーにエラー時のアクションを行ってもらう場合の処理(例えば、
052 * 画面を戻る為のボタンなど)を表示させます。
053 * useColumnLabel を true にセットすると、エラー時のカラム名(ラベル)を、カラムオブジェクトから
054 * 取得するようになります。動的カラム実行時や、DBTableModelに対して、ColumnEditor等で
055 * ラベルを書き換えた場合に、有効です。false の場合は、基本的にはラベルリソースからの
056 * 取得になりますが、ケースによっては、カラムオブジェクトから取得している場合もあります。
057 * この属性は、互換性を重視し、初期値が、false になっています。
058 *
059 * command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。
060 *
061 * @og.formSample
062 * ●形式:<og:columnCheck command = "…" />
063 * ●形式:<og:columnCheck command = "…" >エラー時のみ処理 </og:columnCheck>
064 * ●body:なし/あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
065 *
066 * ●Tag定義:
067 *   <og:columnCheck
068 *       command            【TAG】コマンド[NEW/RENEW/ENTRY]をセットします(初期値:NEW)
069 *       columns            【TAG】チェックすべきカラム列をカンマ区切り(CSV形式)で指定します
070 *       nullCheck          【TAG】NULL チェックすべきカラム列をカンマ区切(CSV形式)りで指定します
071 *       mustAnyCheck       【TAG】選択必須カラム(指定のカラムの内最低ひとつがNULLでない)を"AA|BB|CC,XX|YY|ZZ" 形式で指定します
072 *       checkType          【TAG】 チェック対象のデータ[AUTO/NEW/ENTRY]を指定します(初期値:AUTO)
073 *       maxRowCount        【TAG】ENTRY時にチェックで選択された行数の最大値を設定します
074 *       minRowCount        【TAG】ENTRY時にチェックで選択された行数の最小値を設定します
075 *       tableId            【TAG】(通常は使いません) sessionに登録されている DBTableModel を取り出すキーを指定します
076 *       matchKeys          【TAG】正規表現でのマッチングを行うカラム列をカンマ区切り(CSV形式)で指定します
077 *       matchVals          【TAG】正規表現でのマッチングを行うカラム列に対する値(正規表現)をカンマ区切り(CSV形式)で指定します
078 *       realTime           【TAG】(通常使いません)リアルタイムチェックを行う場合に有効にします
079 *       useStrict          【TAG】NEWの場合に、厳密にチェックするかどうか[true/false]を指定します(初期値:false)
080 *       useColumnLabel     【TAG】カラムラベルを使用するかどうか[true/false]を指定します(初期値:false)
081 *       checkNames         【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します
082 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
083 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
084 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true)
085 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true)
086 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
087 *   >   ... Body ...
088 *   </og:columnCheck>
089 *
090 * ●使用例
091 * <og:columnCheck
092 *     command = "{@command}"
093 *     columns = "AAA,BBB,CCC"  DB定義(DBColumnリソース)で定義した項目(桁数,タイプ等)でチェックします。
094 *     maxRowCount = "1"        チェックで選ばれた 最大選択件数(設定値を含む)を指定。
095 *     minRowCount = "1"        チェックで選ばれた 最小選択件数(設定値を含む)を指定。
096 *     nullCheck = "AAA,CCC"    NULLチェックを実行します。
097 * />
098 *
099 * [エラー時に、BODY部に記述された内容を出力する。正常時には、このBODY部の記述は出力されません。]
100 * <og:columnCheck
101 *     command = "{@command}"
102 *     columns = "AAA,BBB,CCC"      DB定義(DBColumnリソース)で定義した項目(桁数,タイプ等)でチェックします。
103 *     nullCheck = "AAA,CCC"        NULLチェックを実行します。
104 * >
105 *     <form method="POST" action="forward.jsp" target="RESULT">
106 *         <og:input type="button" onClick="history.back()" msg="MSG0049" accesskey="R" td="false" />
107 *     </form>
108 * </og:columnCheck>
109 *
110 * mustAnyCheck 属性に、選択必須カラムを指定します。
111 *      例:mustAnyCheck="AA|BB|CC"
112 *          AA,BB,CC のカラムで選択必須(すべてがnullならエラー)
113 *      例:mustAnyCheck="AA|BB|CC,XX|YY|ZZ"
114 *          AA,BB,CC のセットと、XX,YY,ZZのセットでそれぞれ選択必須。
115 *      例:mustAnyCheck="AA|XX,AA|YY,AA|ZZ"
116 *          AA に値があればすべて成立。そうでない場合は、XX と YY と ZZ がすべて必須。
117 *      例:mustAnyCheck="AA|BB,BB|CC,AA|CC"
118 *          AA,BB,CC の内、どれか2つが必須。AAが成立すればBBかCCが必須。同様に、
119 *          BBが成立すれば、AAかCCが必須。
120 *
121 *  例:query.jsp
122 *        <og:column name="AA" mustAny="true" />
123 *        <og:column name="BB" mustAny="true" />
124 *        <og:column name="XX" mustAny="XYZ"  />
125 *        <og:column name="YY" mustAny="XYZ"  />
126 *      result.jsp
127 *        <og:columnCheck mustAnyCheck="AA|BB,XX|YY" />
128 *      custom/custom.css
129 *          .XYZ { background-color: Green; }
130 *
131 *  例:動的カラムで、entry.jsp でのチェックを行う場合。
132 *     entry.jsp
133 *        <og:columnCheck command="NEW" columns="*" useColumnLabel="true" />
134 *
135 *     useColumnLabel で、動的に作成されたカラム(SAVE=TRUEでキャッシュ済み)を使って
136 *     チェックします。command="NEW" なので、対象カラムを指定するのに、"*" ですべてを選択します。
137 *
138 * @og.group 画面登録
139 *
140 * @version  4.0
141 * @author   Kazuhiko Hasegawa
142 * @since    JDK5.0,
143 */
144public class ColumnCheckTag extends CommonTagSupport {
145        //* このプログラムのVERSION文字列を設定します。   {@value} */
146        private static final String VERSION = "5.7.8.0 (2014/07/04)" ;
147
148        private static final long serialVersionUID = 578020140704L ;
149
150        /** command 引数に渡す事の出来る コマンド  新規 {@value} */
151        public static final String CMD_NEW      = "NEW" ;
152        /** command 引数に渡す事の出来る コマンド  再検索 {@value}  */
153        public static final String CMD_RENEW = "RENEW" ;
154        /** command 引数に渡す事の出来る コマンド  エントリー {@value} */
155        public static final String CMD_ENTRY   = "ENTRY" ;
156        /** command 引数に渡す事の出来る コマンド リスト  */
157
158        // 4.3.1.1 (2008/08/23) transient 追加
159        private transient DBTableModel table            = null;         // 4.1.2.1 (2008/03/13)
160
161        private String          tableId         = HybsSystem.TBL_MDL_KEY;               // 3.5.4.3 (2004/01/05)
162        private String          command         = CMD_NEW;      // 無指定時は、チェックを行う。
163        private String[]        columns         = null;
164        private String[]        nullCheck       = null;
165        private String[]        mustAnyCheck= null;             // 3.8.0.9 (2005/10/17)
166        private int                     maxRowCount     = -1 ;          // 初期値として,無制限を指定
167        private int                     minRowCount     = -1 ;          // 初期値として,無制限を指定
168        private String          checkType       = "AUTO";
169        private String          bodyString      = null;         // 3.5.4.2 (2003/12/15)
170        private String[]        matchKeys       = null;         // 4.0.0 (2005/11/30)
171        private String[]        matchVals       = null;         // 4.0.0 (2005/11/30)
172        private boolean         isRealTime      = false;        // 4.3.7.0 (2009/06/01)
173        private boolean         isStrict        = false;        // 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加
174
175        private boolean         isColumnLabel= false;   // 5.4.3.4 (2012/01/12) true の場合に、カラムラベルを使用します。
176
177        private String                  checkNames      = null; // 5.4.3.8 (2012/01/24)
178
179        /**
180         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
181         *
182         * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。
183         * @og.rev 5.0.0.2 (2009/09/15) xss対応⇒チェックする
184         * @og.rev 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加
185         *
186         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
187         */
188        @Override
189        public int doStartTag() {
190                // 5.0.0.2 (2009/09/15) XSSチェックしない⇒する
191                // useXssCheck( false );
192//              return EVAL_BODY_BUFFERED ;             // Body を評価する
193
194                // 5.7.8.0 (2014/07/04) 追加
195                return useTag() ? EVAL_BODY_BUFFERED : SKIP_BODY ;
196        }
197
198        /**
199         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
200         *
201         * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。
202         *
203         * @return      後続処理の指示(SKIP_BODY)
204         */
205        @Override
206        public int doAfterBody() {
207                bodyString = getBodyString();
208
209                return SKIP_BODY ;
210        }
211
212        /**
213         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
214         *
215         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
216         * @og.rev 3.4.0.3 (2003/09/10) command="NEW" でエラー発生時には、DBTableModel をクリアする。
217         * @og.rev 3.5.4.2 (2003/12/15) HTMLTableViewForm クラス名変更(⇒ ViewForm_HTMLTable)
218         * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。
219         * @og.rev 3.5.4.3 (2004/01/05) tableId 属性を追加。
220         * @og.rev 3.5.4.4 (2004/01/16) エラー結果を表示するテーブル形式のフォーム修正
221         * @og.rev 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用
222         * @og.rev 4.1.2.1 (2008/03/13) table 属性を追加。
223         * @og.rev 4.3.3.0 (2008/10/01) viewSimple属性追加
224         * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime
225         * @og.rev 5.6.8.3 (2013/09/27) checkTypeがAutoの場合のセットをここで行い、tableModelチェックをcheckTypeで行う。
226         * @og.rev 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加
227         *
228         * @return      後続処理の指示
229         */
230        @Override
231        public int doEndTag() {
232                debugPrint();           // 4.0.0 (2005/02/28)
233
234                // 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加
235                if( !useTag() ) { return EVAL_PAGE ; }          // ページの残りを評価する。
236
237                int rtnCode = EVAL_PAGE;
238
239                // 4.1.2.1 (2008/03/13)
240                table = (DBTableModel)getObject( tableId );
241                
242                // 5.6.8.3 (2013/09/27) チェックタイプのautoを入れる位置変更
243                if( "AUTO".equals( checkType ) ) { checkType = command; }
244
245                // 3.4.0.3 (2003/09/10) コマンドが、NEW,RENEW 以外の場合は、DBTableModel は必須。
246                if( 
247                        !CMD_NEW.equals( checkType ) &&         // 5.6.8.3 (2013/09/27) commandから変更
248                        !CMD_RENEW.equals( checkType ) &&
249                        table == null ) {                                       // 4.1.2.1 (2008/03/13)
250                                String errMsg = "検索結果のオブジェクトが存在しません。"
251                                                                + " checkType=[" + checkType + "]" ;
252                                jspPrint( errMsg );
253                                rtnCode = SKIP_PAGE ;
254                }
255                else {
256                // 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用
257                        ErrorMessage errMsg = makeErrorDBTable();
258                        if( errMsg.getKekka() >= ErrorMessage.NG ) {
259                                if( bodyString != null ) { jspPrint( bodyString ); }    // 3.5.4.2 (2003/12/15)
260
261                                // 4.3.3.0 (2008/10/01)
262                                // 4.3.7.0 (2009/06/01)
263                                if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg,getResource() ) ); }
264                                else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource() ) ); }
265
266                                if( CMD_NEW.equals( command ) ) {
267                                        removeObject( tableId );
268                                }
269                                rtnCode = SKIP_PAGE ;
270                        }
271                        else if( errMsg.getKekka() == ErrorMessage.WARNING ) {
272                                // 4.3.3.0 (2008/10/01)
273                                // 4.3.7.0 (2009/06/01)
274                                if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg,getResource() ) ); }
275                                else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource() ) ); }                    }
276                }
277
278                return rtnCode ;
279        }
280
281        /**
282         * タグリブオブジェクトをリリースします。
283         *
284         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
285         *
286         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
287         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
288         * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。
289         * @og.rev 3.5.4.3 (2004/01/05) tableId 属性を追加。
290         * @og.rev 3.8.0.9 (2005/10/17) mustAnyCheck 属性を追加。
291         * @og.rev 4.1.2.1 (2008/03/13) table 属性を追加。
292         * @og.rev 4.3.3.0 (2008/10/01) viewSimple属性追加
293         * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime
294         * @og.rev 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加
295         * @og.rev 5.4.3.4 (2012/01/12) isColumnLabelを追加
296         *
297         */
298        @Override
299        protected void release2() {
300                super.release2();
301                command         = CMD_NEW;      // 無指定時は、チェックを行う。
302                columns         = null;
303                nullCheck       = null;
304                maxRowCount     = -1 ;          // 初期値として,無制限を指定
305                minRowCount     = -1 ;          // 初期値として,無制限を指定
306                checkType       = "AUTO";
307                bodyString      = null ;        // 3.5.4.2 (2003/12/15)
308                tableId         = HybsSystem.TBL_MDL_KEY;               // 3.5.4.3 (2004/01/05)
309                mustAnyCheck= null;             // 3.8.0.9 (2005/10/17)
310                matchKeys       = null;         // 4.0.0 (2005/11/30)
311                matchVals       = null;         // 4.0.0 (2005/11/30)
312                table           = null;         // 4.1.2.1 (2008/03/13)
313                isRealTime      = false;        // 4.3.7.0 (2009/06/01)
314                isStrict        = false;        // 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加
315                isColumnLabel= false;   // 5.4.3.4 (2012/01/12) true の場合に、カラムラベルを使用します。
316                checkNames      = null;         // 5.4.3.8 (2012/01/24)
317        }
318
319        /**
320         * DBColumn オブジェクトを作成して、DBColumn#valueCheck( String )で
321         * チェックを行う。その結果の、ErrorMessage オブジェクトを DBTableModel に
322         * 取り込んで、エラーの場合は、その表示を行う。
323         * 表示方法は、そのまま ViewForm オブジェクトを作成して、表示を行う。
324         *
325         * @og.rev 3.5.5.2 (2004/04/02) リターン値を、DBTableModel から ErrorMessage に変更
326         * @og.rev 4.0.0.0 (2005/01/31) リターン値の ErrorMessage は、必ず存在する。
327         * @og.rev 4.1.2.1 (2008/03/13) command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。
328         * @og.rev 5.6.8.3 (2013/09/27) checkTypeのAuto時設定位置をdoEndTagでするように変更
329         *
330         * @return      エラーメッセージのテーブルモデル
331         */
332        private ErrorMessage makeErrorDBTable() {
333                ErrorMessage errMsg = new ErrorMessage();
334
335                //if( "AUTO".equals( checkType ) ) { checkType = command; } // 5.6.8.3 (2013/09/27) move
336                if( CMD_ENTRY.equals( checkType ) ) {
337                        errMsg.setTitle( "Request Column Error!" );
338                        errMsg = makeEntryErrorMessage( errMsg );
339                        errMsg = makeMaxRowCountErrorMessage( errMsg );
340                        errMsg = makeMinRowCountErrorMessage( errMsg );
341                }
342                else if( CMD_NEW.equals( checkType ) ) {
343                        errMsg.setTitle( "Entry Column Error!" );
344                        errMsg = makeErrorMessage( errMsg );
345                        errMsg = makeMaxRowCountErrorMessage( errMsg );
346                        errMsg = makeMinRowCountErrorMessage( errMsg );
347                }
348                else if( minRowCount >= 0 || maxRowCount >= 0) {  // -1 は制限無し
349                        errMsg.setTitle( "Row Count Error Limited Error!" );
350                        errMsg = makeMaxRowCountErrorMessage( errMsg );
351                        errMsg = makeMinRowCountErrorMessage( errMsg );
352                }
353                // 4.1.2.1 (2008/03/13) command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。
354                else if( "MODIFY,DELETE".indexOf( checkType ) >= 0 && minRowCount < 0 ) {
355                        minRowCount = 1;
356                        errMsg = makeMinRowCountErrorMessage( errMsg );
357                }
358                return errMsg;
359        }
360
361        /**
362         * ErrorMessageをセットします。
363         * 引数のカラム名配列よりリクエスト情報を取得して、値をチェックします。
364         * DBColumn#valueCheck( String ) の結果のErrorMessageをすべて append
365         * していきます。
366         *
367         * @og.rev 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
368         * @og.rev 3.8.1.0 (2005/10/24) リクエスト情報の正規化変換(DBColumn#valueSet(String))中止
369         * @og.rev 3.8.5.3 (2006/06/30) リクエストに % , _ が含まれたときは、削除します。
370         * @og.rev 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加
371         * @og.rev 5.0.0.2 (2009/09/15) 個別にxssチェックをfalse
372         * @og.rev 5.1.9.0 (2010/08/01) 同じ名前の項目は、1つにまとめる(ラジオボタン等)
373         * @og.rev 5.2.0.0 (2010/09/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない
374         * @og.rev 5.2.2.0 (2010/11/01) DBColumn#valueCheck で、甘いチェックを行うように、引数に isStrict を追加
375         * @og.rev 5.4.3.4 (2012/01/12) getLabel( String )を、リソースからに統一するとともに、isColumnLabel 対応を行う。
376         * @og.rev 5.4.3.8 (2012/01/28) checkNames対応
377         *
378         * @param       errMsg  ErrorMessageオブジェクト
379         *
380         * @return      カラムキー + 値 のエラーメッセージオブジェクト
381         */
382        private ErrorMessage makeErrorMessage( final ErrorMessage errMsg ) {
383
384                // 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加
385                // request から取出す 注意:mustAny 以外の自由形式の値は所得していません。
386                // 5.2.0.0 (2010/09/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない
387                //  (基本的にパラメーターを送らない限り自動チェックは動かないが、RequestCacheにより動くことがある)
388                if( !isRealTime ) {
389                        if( nullCheck == null ) {
390                                nullCheck = getRequestValues( HybsSystem.MUST_KEY + "must" );
391                                // 5.1.9.0 (2010/08/01) 同じ名前の項目は、1つにまとめる(ラジオボタン等)
392                                if( nullCheck != null ) {
393                                        Set<String> ss = new TreeSet<String>();
394                                        ss.addAll( Arrays.asList( nullCheck ) );
395                                        nullCheck = ss.toArray( new String[ss.size()] );                // 5.1.9.0 (2010/08/01) K.H
396                                }
397                        }
398                        if( mustAnyCheck == null ) {
399                                String[] mustAnyReq = getRequestValues( HybsSystem.MUST_KEY + "mustAny" );
400                                if( mustAnyReq != null && mustAnyReq.length > 0 ) {
401                                        mustAnyCheck = new String[] { StringUtil.array2line( mustAnyReq,"|" ) };
402                                }
403                        }
404                }
405
406                if( nullCheck != null && nullCheck.length != 0 ) {
407                        for( int i=0; i<nullCheck.length; i++ ) {
408                                String clmKey = nullCheck[i];           // 5.4.3.4 (2012/01/12)
409                                // String val  = getRequestValue( nullCheck[i] );
410                                String val  = getRequestValue( clmKey, false ); // 5.0.0.2 (2009/09/15)
411                                if( val == null || val.length() == 0 ) {
412                                        // 5.4.3.4 (2012/01/12) isColumnLabel 追加
413                                        String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : getResource().getLabel( clmKey );
414                                        // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0}
415                                        errMsg.addMessage( 0,ErrorMessage.NG,"ERR0012",label );
416                                }
417                        }
418                }
419                // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
420                if( mustAnyCheck != null && mustAnyCheck.length != 0 ) {
421                        for( int i=0; i<mustAnyCheck.length; i++ ) {
422                                boolean flag = false;
423                                String[] mustSub = StringUtil.csv2Array( mustAnyCheck[i],'|' );
424                                for( int j=0; j<mustSub.length; j++ ) {
425                                        // String val  = getRequestValue( mustSub[j] );
426                                        String val  = getRequestValue( mustSub[j], false ); // 5.0.0.2 (2009/09/15)
427                                        if( val != null && val.length() > 0 ) {
428                                                flag = true; break;             // ひとつでもnullでなければ、OK
429                                        }
430                                }
431                                if( ! flag ) {
432                                        StringBuilder buf = new StringBuilder();
433                                        for( int j=0; j<mustSub.length; j++ ) {
434                                                String clmKey = mustSub[j];             // 5.4.3.4 (2012/01/12)
435                                                // 5.4.3.4 (2012/01/12) isColumnLabel 追加
436                                                String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : getResource().getLabel( clmKey );
437                                                buf.append( label ).append( "," );
438                                        }
439                                        // ERR0036 : 選択必須エラー。以下のデータの内どれかは入力してください。key={0}
440                                        errMsg.addMessage( 0,ErrorMessage.NG,"ERR0036",buf.toString() );
441                                }
442                        }
443                }
444                if( columns != null && columns.length != 0 ) {
445                        for( int i=0; i<columns.length; i++ ) {
446                                // 3.8.1.0 (2005/10/24) リクエスト情報の正規化変換(DBColumn#valueSet(String))中止
447                                // String clmVal = getRequestValue( columns[i] );
448                                String clmVal = getRequestValue( columns[i], false ); // 5.0.0.2 (2009/09/15)
449                                if( clmVal != null && clmVal.length() > 0 ) {
450                                        clmVal = StringUtil.replace( clmVal,"%","" );           // 3.8.5.3 (2006/06/30)
451                                        clmVal = StringUtil.replace( clmVal,"_","" );           // 3.8.5.3 (2006/06/30)
452                                        DBColumn dbColumn = getDBColumn( columns[i] );
453                                        // 5.4.3.8 (2012/01/24) checkNames対応
454                                        if( ( "," + checkNames + "," ).indexOf( "," + columns[i] + "," ) >= 0 ) {
455                                                String val = dbColumn.valueSet( clmVal );
456                                                if( val != null ) { clmVal = val; }
457                                        }
458                                        // 5.2.2.0 (2010/11/01) DBColumn#valueCheck で、甘いチェックを行うように、引数に isStrict を追加
459                                        errMsg.append( dbColumn.valueCheck( clmVal,isStrict ) );
460                                }
461                        }
462                }
463                // 4.0.0 (2005/11/30) 正規表現チェックの追加
464                if( matchKeys != null && matchKeys.length != 0 ) {
465                        for( int i=0; i<matchKeys.length; i++ ) {
466                                String clmKey = matchKeys[i];           // 5.4.3.4 (2012/01/12)
467                                // String val  = getRequestValue( matchKeys[i] );
468                                String val  = getRequestValue( clmKey, false ); // 5.0.0.2 (2009/09/15)
469                                if( val != null && ! val.matches( matchVals[i] ) ) {
470                                        // 5.4.3.4 (2012/01/12) isColumnLabel 追加
471                                        String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : getResource().getLabel( clmKey );
472                                        // ERR0037 : データ整合性エラー。指定のキーは整合性チェックの結果マッチしませんでした。key={0} val={1} regex={2}
473                                        errMsg.addMessage( 0,ErrorMessage.NG,"ERR0037",label,val,matchVals[i] );
474                                }
475                        }
476                }
477
478                return errMsg;
479        }
480
481        /**
482         * エントリーデータのErrorMessageをセットします。
483         * 引数のカラム名配列よりエントリーデータ形式のリクエスト情報を取得して、
484         * 値をチェックします。
485         * DBColumn#valueCheck( String ) の結果のErrorMessageをすべて append
486         * していきます。
487         *
488         * @og.rev 3.1.0.0 (2003/03/20) 名前と行番号の区切り記号を "^" から "__" に変更。
489         * @og.rev 3.5.5.0 (2004/03/12) 名前と行番号の区切り記号("__")を、HybsSystem.JOINT_STRING  に変更。
490         * @og.rev 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
491         * @og.rev 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加
492         * @og.rev 4.3.6.4 (2009/05/01) 削除時に必ずmustAnyチェックエラーになるバグを修正(書込み可能行のみを処理する
493         * @og.rev 4.3.7.0 (2009/06/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない
494         * @og.rev 5.0.0.2 (2009/09/15) xssチェック
495         * @og.rev 5.4.3.4 (2012/01/12) getLabel( String )を、リソースからに統一するとともに、isColumnLabel 対応を行う。
496         *
497         * @param       errMsg  ErrorMessageオブジェクト
498         *
499         * @return      カラムキー + 値 のエラーメッセージオブジェクト
500         */
501        private ErrorMessage makeEntryErrorMessage( final ErrorMessage errMsg ) {
502                int[] rowNo = getParameterRows();
503                if( rowNo.length == 0 ) { return errMsg; }
504
505                // 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加
506                // table から取出す (ソート済み)
507                // 4.3.7.0 (2009/06/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない
508                if( !isRealTime ) {
509                        if( nullCheck    == null ) { nullCheck    = table.getMustArray();        }
510                        if( mustAnyCheck == null ) { mustAnyCheck = table.getMustAnyArray(); }
511                }
512
513                // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
514                boolean[][] rowAnyOne = null;
515                // 4.3.6.4 (2009/05/01)
516                boolean[] rowForCheck = null;
517                if( mustAnyCheck != null && mustAnyCheck.length != 0 ) {
518                        rowAnyOne = new boolean[rowNo.length][mustAnyCheck.length];
519                        rowForCheck = new boolean[rowNo.length];
520        //              for( int i=0; i<rowNo.length; i++ ) {
521        //                      Arrays.fill( rowAnyOne[i],false );
522        //              }
523                }
524
525                DBColumn dbColumn = null;       // 5.4.3.4 (2012/01/12) isColumnLabel 対応
526                Enumeration<?> enume = getParameterNames();               // 4.3.3.6 (2008/11/15) Generics警告対応
527                while( enume.hasMoreElements() ) {
528                        String key  = (String)(enume.nextElement());
529                        int    idx  = key.lastIndexOf(HybsSystem.JOINT_STRING);
530
531                        if( idx > 0 ) {
532                                String column = key.substring(0,idx);
533                                int    row    = Integer.parseInt( key.substring(idx + 2) );
534                                // String val    = getRequestValue( key );
535                                String val    = getRequestValue( key, false ); // 5.0.0.2 (2009/09/15)
536
537                                int i = Arrays.binarySearch( rowNo,row );
538                                if( i >= 0 ) {
539                                        // 5.4.3.4 (2012/01/12) isColumnLabel 対応
540                                        dbColumn = null;
541                                        if( isColumnLabel && table != null ) {
542                                                int clmNo = table.getColumnNo( column,false );  // エラーを出さない。
543                                                if( clmNo >= 0 ) {
544                                                        dbColumn = table.getDBColumn( clmNo );
545                                                }
546                                        }
547                                        if( dbColumn == null ) {
548                                                dbColumn = getDBColumn( column );
549                                        }
550
551                                        String val2 = dbColumn.valueSet( val );
552                                        errMsg.append( row+1,dbColumn.valueCheck( val2 ) );
553                                        if( nullCheck != null && nullCheck.length != 0 ) {
554                                                int j = Arrays.binarySearch( nullCheck,column );
555                                                if( j>=0 && ( val2 == null || val2.length() == 0 )) {
556                                                        // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0}
557                                                        errMsg.addMessage( row+1,ErrorMessage.NG,"ERR0012",dbColumn.getLabel() );
558                                                }
559                                        }
560                                        // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
561                                        if( rowAnyOne != null ) {
562                                                for( int j=0; j<mustAnyCheck.length; j++ ) {
563                                                        if( !rowAnyOne[i][j] &&
564                                                                mustAnyCheck[j].indexOf( column ) >= 0 &&
565                                                                val2 != null && val2.length() > 0 ) {
566                                                                        rowAnyOne[i][j] = true; // どれかが存在
567                                                        }
568                                                }
569                                                // 4.3.6.4 (2009/05/01)
570                                                rowForCheck[i] = true;
571                                        }
572
573                                        // 4.0.0 (2005/11/30) 正規表現チェックの追加
574                                        if( matchKeys != null && matchKeys.length != 0 ) {
575                                                for( int j=0; j<matchKeys.length; j++ ) {
576                                                        if( column.equals( matchKeys[j] ) ) {
577                                                                if( val2 != null && ! val2.matches( matchVals[j] ) ) {
578                                                                        // 互換性はなくなっているが、正規表現チェックは余り使っていないので、統一しておく。
579                                                                        // 5.4.3.4 (2012/01/12) isColumnLabel 対応
580                                                                        dbColumn = null;
581                                                                        if( isColumnLabel && table != null ) {
582                                                                                int clmNo = table.getColumnNo( column,false );  // エラーを出さない。
583                                                                                if( clmNo >= 0 ) {
584                                                                                        dbColumn = table.getDBColumn( clmNo );
585                                                                                }
586                                                                        }
587                                                                        if( dbColumn == null ) {
588                                                                                dbColumn = getDBColumn( column );
589                                                                        }
590
591                                                                        // ERR0037 : データ整合性エラー。指定のキーは整合性チェックの結果マッチしませんでした。key={0} val={1} regex={2}
592                                                                        errMsg.addMessage( row+1,ErrorMessage.NG,"ERR0037",dbColumn.getLabel(),val2,matchVals[i] );
593                                                                }
594                                                                break;
595                                                        }
596                                                }
597                                        }
598                                }
599                        }
600                }
601
602                // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加
603                if( rowAnyOne != null ) {
604                        for( int row=0; row<rowAnyOne.length; row++ ) {
605                                // 4.3.6.4 (2009/05/01) 書込み可能行のみを処理する
606                                if ( rowForCheck[row] ) {
607                                        for ( int i = 0; i < mustAnyCheck.length; i++ ) {
608                                                if ( !rowAnyOne[row][i] ) {
609                                                        String[] mustSub = StringUtil.csv2Array( mustAnyCheck[i], '|' );
610
611                                                        StringBuilder buf = new StringBuilder();
612                                                        buf.append( "row=[" ).append( rowNo[row]+1 ).append( "] " );
613                                                        for ( int j = 0; j < mustSub.length; j++ ) {
614                                                                // ここの処理だけ、他と異なるのは、互換性重視のため。(選択必須は利用頻度が高いので。)
615                                                                // 5.4.3.4 (2012/01/12) isColumnLabel 対応
616                                                                String label = null ;
617                                                                if( isColumnLabel && table != null ) {
618                                                                        int clmNo = table.getColumnNo( mustSub[j],false );      // エラーを出さない。
619                                                                        if( clmNo >= 0 ) {
620                                                                                dbColumn = table.getDBColumn( clmNo );
621                                                                        }
622                                                                        if( dbColumn == null ) {
623                                                                                dbColumn = getDBColumn( mustSub[j] );
624                                                                        }
625                                                                        label = dbColumn.getLabel();
626                                                                }
627                                                                else {
628                                                                        label = getResource().getLabel( mustSub[j] );           // 互換性のための処置。
629                                                                }
630                                                                buf.append( label ).append( "|" );
631                                                        }
632                                                        // ERR0036 : 選択必須エラー。以下のデータの内どれかは入力してください。key={0}
633                                                        errMsg.addMessage( rowNo[row]+1, ErrorMessage.NG, "ERR0036", buf.toString() );
634                                                }
635                                        }
636                                }
637                        }
638                }
639
640                return errMsg;
641        }
642
643        /**
644         * ErrorMessageをセットします。
645         * リクエストされた件数の最大値に制限を加えます。
646         * 1件だけにしたい場合は,通常はViewでチェックボックスを使用せずに
647         * ラジオボタンを使用してください。
648         *
649         * @param       errMsg  ErrorMessageオブジェクト
650         *
651         * @return      カラムキー + 値 のエラーメッセージオブジェクト
652         */
653        private ErrorMessage makeMaxRowCountErrorMessage( final ErrorMessage errMsg ) {
654                if( maxRowCount < 0 ) { return errMsg; }     // 無制限
655
656                // 件数制限のチェック
657                int[] rowNo = getParameterRows();
658                int rowCount = rowNo.length ;
659                if( rowCount > maxRowCount ) {
660                        // ERR0017 : 選択エラー。選択行数({0} 件)が、最大制限値({1} 件)以上選ばれました。
661                        String arg0 = String.valueOf( rowCount );
662                        String arg1 = String.valueOf( maxRowCount );
663                        errMsg.addMessage( 0,ErrorMessage.NG,"ERR0017",arg0,arg1 );
664                }
665
666                return errMsg;
667        }
668
669        /**
670         * ErrorMessageをセットします。
671         * リクエストされた件数の最小値に制限を加えます。
672         * 1件だけにしたい場合は,通常はViewでチェックボックスを使用せずに
673         * ラジオボタンを使用してください。
674         *
675         * @param       errMsg  ErrorMessageオブジェクト
676         *
677         * @return      カラムキー + 値 のエラーメッセージオブジェクト
678         */
679        private ErrorMessage makeMinRowCountErrorMessage( final ErrorMessage errMsg ) {
680                if( minRowCount < 0 ) { return errMsg; }     // 無制限
681
682                // 件数制限のチェック
683                int[] rowNo = getParameterRows();
684                int rowCount = rowNo.length ;
685                if( rowCount < minRowCount ) {
686                        // ERR0018 : 選択エラー。選択行数({0} 件)が、最小制限値({1} 件)以下選ばれました。
687                        String arg0 = String.valueOf( rowCount );
688                        String arg1 = String.valueOf( minRowCount );
689                        errMsg.addMessage( 0,ErrorMessage.NG,"ERR0018",arg0,arg1 );
690                }
691
692                return errMsg;
693        }
694
695        /**
696         * 【TAG】チェックすべきカラム列をカンマ区切り(CSV形式)で指定します。
697         *
698         * @og.tag columns="AAA,BBB,CCC,DDD"
699         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
700         * "*" を指定すると、command="NEW" のときの判定にすべてのリクエスト文字列を
701         * チェック対象とします。通常は、必要分だけ指定しますが、動的カラムなどの
702         * 場合は、カラム名を予め指定できないため、"*" で指定できるようにします。
703         * その場合、"h_" , "hX_" , maxRowCount , command , pageSize , pagePlus ,
704         * GAMENID , BACK_JSPID , BACK_GAMENID の予約語は、対象から除きます。
705         *
706         * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
707         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
708         * @og.rev 5.4.3.4 (2012/01/12) command="NEW" のときの動的カラム対応( "*" ですべてのリクエスト)
709         *
710         * @param   clms カラム列(CSV形式)
711         */
712        public void setColumns( final String clms ) {
713                columns = StringUtil.csv2Array( getRequestParameter( clms ) );
714                if( columns.length == 0 ) { columns = null; }
715
716                // 5.4.3.4 (2012/01/12) command="NEW" のときの動的カラム対応( "*" ですべてのリクエスト)
717                if( columns != null && "*".equals( columns[0] ) ) {
718                        Set<String> clmSet = new TreeSet<String>();         // リクエストはバラバラなので、とりあえずソートしてきます。
719
720                        Enumeration<?> enume = getParameterNames();               // Generics警告対応
721                        while( enume.hasMoreElements() ) {
722                                String clm  = (String)(enume.nextElement());
723                                // 予約語以外を登録します。
724                                if( clm != null && !clm.isEmpty() && !clm.startsWith( "h_" ) && !clm.startsWith( "hX_" ) ) {
725                                        clmSet.add( clm );
726                                }
727                        }
728                        // 予約語を削除します。
729                        clmSet.remove( "maxRowCount" );
730                        clmSet.remove( "command" );
731                        clmSet.remove( "pageSize" );
732                        clmSet.remove( "pagePlus" );
733                        clmSet.remove( "GAMENID" );
734                        clmSet.remove( "BACK_JSPID" );
735                        clmSet.remove( "BACK_GAMENID" );
736
737                        columns = clmSet.toArray( new String[clmSet.size()] );
738                }
739        }
740
741        /**
742         * 【TAG】NULL チェックすべきカラム列をカンマ区切(CSV形式)りで指定します。
743         *
744         * @og.tag
745         * (must 属性のセットにより、自動処理されます)
746         * nullCheck="AAA,BBB,CCC,DDD"
747         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
748         *
749         * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
750         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
751         *
752         * @param   clms カラム列(CSV形式)
753         */
754        public void setNullCheck( final String clms ) {
755                nullCheck = StringUtil.csv2Array( getRequestParameter( clms ) );
756                if( nullCheck.length == 0 ) { nullCheck = null; }
757                else {
758                        Arrays.sort( nullCheck );
759                }
760        }
761
762        /**
763         * 【TAG】選択必須カラム(指定のカラムの内最低ひとつがNULLでない)を"AA|BB|CC,XX|YY|ZZ" 形式で指定します。
764         *
765         * @og.tag
766         * (mustAny 属性のセットにより、自動処理されます)
767         * 複数のカラム属性の値のうち、どれかが null でない場合は正常とし、
768         * すべてが null の場合を警告します。
769         *
770         *  例:mustAnyCheck="AA|BB|CC"
771         *      AA,BB,CC のカラムで選択必須(すべてがnullならエラー)
772         *  例:mustAnyCheck="AA|BB|CC,XX|YY|ZZ"
773         *      AA,BB,CC のセットと、XX,YY,ZZのセットでそれぞれ選択必須。
774         *  例:mustAnyCheck="AA|XX,AA|YY,AA|ZZ"
775         *      AA に値があればすべて成立。そうでない場合は、XX と YY と ZZ がすべて必須。
776         *  例:mustAnyCheck="AA|BB,BB|CC,AA|CC"
777         *      AA,BB,CC の内、どれか2つが必須。AAが成立すればBBかCCが必須。同様に、
778         *      BBが成立すれば、AAかCCが必須。
779         *
780         * 選択必須は、must と同様に、色づけを行う(query.jsp)画面では、mustAny 属性を
781         * セットします。チェックを行う(result.jsp)画面では、columnCheck タグの
782         * mustAnyCheck 属性に、選択必須カラムを指定します。(上記参照)
783         * column タグ等の mustAny 属性に、mustAny="true" とセットすると、生成される
784         * HTMLは、class="mustAny" が出力されます。エンジン標準では、default.css に
785         * .mustAny が定義されています。( background-color: #CCFFFF; )
786         * なお、mustAny 属性に、true 以外の値をセットした場合(mustAny="XYZ")は、
787         * 生成されるHTMLに、class="XYZ" が出力されます。これは、複数のグループ間で
788         * 色を変えて、選択必須を指定する場合に使用します。色は、custom/custom.css
789         * で指定します。
790         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
791         *
792         * @og.rev 3.8.0.9 (2005/10/17) 新規追加
793         * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
794         *
795         * @param   clms 選択必須カラム
796         */
797        public void setMustAnyCheck( final String clms ) {
798                mustAnyCheck = StringUtil.csv2Array( getRequestParameter( clms ) );
799                if( mustAnyCheck.length == 0 ) { mustAnyCheck = null; }
800                else {
801                        Arrays.sort( mustAnyCheck );
802                }
803        }
804
805        /**
806         * 【TAG】コマンド[NEW/RENEW/ENTRY]をセットします(初期値:NEW)。
807         *
808         * @og.tag
809         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
810         * フィールド定数値のいづれかを、指定できます。
811         * 何も設定されない、または、null の場合は、"NEW" が初期値にセットされます。
812         *
813         * @param       cmd コマンド(public static final 宣言されている文字列)
814         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ColumnCheckTag.CMD_NEW">コマンド定数</a>
815         */
816        public void setCommand( final String cmd ) {
817                String cmd2 = getRequestParameter( cmd );
818                if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
819        }
820
821        /**
822         * 【TAG】 チェック対象のデータ[AUTO/NEW/ENTRY]を指定します(初期値:AUTO)。
823         *
824         * @og.tag
825         * 通常のリクエストデータは、キーそのものですが,エントリデータは表形式の
826         * データを一括で登録する為、(キー+"__" + 行番号)形式を、バラす必要があります。
827         *
828         * ENTRY は、DBTableModelのリクエスト情報をチェックします。
829         * これは、全データが対象になります。(columns/nullCheck 属性は無効)
830         * AUTO は、command が、上記 NEW か ENTRY かを判断して処理を振り分けます。
831         * 初期値は、AUTO です。
832         *
833         * @param   flag チェック対象のデータ(AUTO,NEW,ENTRY)
834         */
835        public void setCheckType( final String flag ) {
836                String ct = getRequestParameter( flag );
837                if( ct != null && ct.length() > 0 ) { checkType = ct ; }
838        }
839
840        /**
841         * 【TAG】チェックで選択された行数の最大値を設定します。
842         *
843         * @og.tag
844         * 最大選択件数を超えた場合は,エラーメッセージを返します。
845         * 例えば、1件のみを正常とする場合は、maxRowCount="1" とします。
846         *
847         * @param   count 制限をかけたい行数(この件数と同じ場合は正常 )
848         */
849        public void setMaxRowCount( final String count ) {
850                maxRowCount = nval( getRequestParameter( count ),maxRowCount );
851        }
852
853        /**
854         * 【TAG】チェックで選択された行数の最小値を設定します。
855         *
856         * @og.tag
857         * 最小選択件数を超えない場合は、エラーメッセージを返します。
858         * 例えば、1件のみを正常とする場合は、minRowCount="1" とします。
859         *
860         * @param   count 制限をかけたい行数(この件数と同じ場合は正常 )
861         */
862         public void setMinRowCount( final String count ) {
863                minRowCount = nval( getRequestParameter( count ), minRowCount );
864         }
865
866        /**
867         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
868         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
869         *
870         * @og.tag
871         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
872         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
873         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
874         * この tableId 属性を利用して、メモリ空間を分けます。
875         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
876         *
877         * @param       id sessionに登録する時の ID
878         */
879        public void setTableId( final String id ) {
880                tableId = nval( getRequestParameter( id ),tableId );
881        }
882
883        /**
884         * 【TAG】正規表現でのマッチングを行うカラム列をカンマ区切り(CSV形式)で指定します。
885         *
886         * @og.tag matchKeys="AAA,BBB,CCC,DDD"
887         * matchKeys属性とmatchVals属性の個数は、同じでなければなりません。
888         * 先に配列に分解してからリクエスト変数の値を取得するようにします。
889         * こうする事で、リクエストにカンマ区切りの値を設定できるようになります。
890         *
891         * @og.rev 4.0.0.0 (2005/11/30) 新規作成
892         *
893         * @param   keys カラム列(CSV形式)
894         * @see     #setMatchVals( String )
895         */
896        public void setMatchKeys( final String keys ) {
897                matchKeys = getCSVParameter( keys );
898
899                if( matchVals != null && matchKeys.length != matchVals.length ) {
900                        String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。"
901                                                + HybsSystem.CR
902                                                + " matchKeys=[" + matchKeys.length + "]:KEYS="
903                                                + StringUtil.array2csv( matchKeys ) + HybsSystem.CR
904                                                + " matchVals=[" + matchVals.length + "]:VLAS="
905                                                + StringUtil.array2csv( matchVals ) + HybsSystem.CR ;
906                        throw new HybsSystemException( errMsg );
907                }
908        }
909
910        /**
911         * 【TAG】正規表現でのマッチングを行うカラム列に対する値(正規表現)をカンマ区切り(CSV形式)で指定します。
912         *
913         * @og.tag matchVals="AAA,BBB,CCC,DDD"
914         * matchKeys属性とmatchVals属性の個数は、同じでなければなりません。
915         * 先に配列に分解してからリクエスト変数の値を取得するようにします。
916         * こうする事で、リクエストにカンマ区切りの値を設定できるようになります。
917         *
918         * @og.rev 4.0.0.0 (2005/11/30) 新規作成
919         *
920         * @param   vals カラム列に対する値(正規表現)(CSV形式)
921         * @see     #setMatchKeys( String )
922         */
923        public void setMatchVals( final String vals ) {
924                matchVals = getCSVParameter( vals );
925
926                if( matchKeys != null && matchKeys.length != matchVals.length ) {
927                        String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。"
928                                                + HybsSystem.CR
929                                                + " matchKeys=[" + matchKeys.length + "]:KEYS="
930                                                + StringUtil.array2csv( matchKeys ) + HybsSystem.CR
931                                                + " matchVals=[" + matchVals.length + "]:VLAS="
932                                                + StringUtil.array2csv( matchVals ) + HybsSystem.CR ;
933                        throw new HybsSystemException( errMsg );
934                }
935        }
936
937        /**
938         * 【TAG】(通常使いません)リアルタイムチェックを行う場合に有効にします。
939         *
940         * @og.tag
941         * リアルタイムチェックを行う場合に有効にする属性です。
942         * trueが指定された場合、通常のチェックと比較し、以下の差異があります。
943         * @エラー結果を簡易フォーマットで出力します。
944         *   (ViewFormType="HTMLSimpleErrorList"で表示されます。)
945         *   この簡易フォーマットで出力した場合は、ラベル(短)の定義で出力され、
946         *   カラム名やデータ等は出力されません。
947         * Amust,mustAny属性のチェックを行いません。
948         *   必須及び選択必須は、視覚的に判別できるため、リアルタイムチェックの
949         *   対象外とします。
950         *
951         * @og.rev 4.3.3.0 (2008/10/01) 新規作成
952         * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime
953         *
954         * @param   flg 簡易表示を行うかどうか
955         */
956        public void setRealTime( final String flg ) {
957                isRealTime = nval( getRequestParameter( flg ),isRealTime );
958        }
959
960        /**
961         * 【TAG】NEWの場合に、厳密にチェックするかどうか[true/false]を指定します(初期値:false)。
962         *
963         * @og.tag
964         * データをチェックするに当たり、あいまい検索などで厳密にチェックすると
965         * エラーになるケースがあるため、command="NEW" のチェック時には、甘い目の
966         * チェックを行っています。DBColumn#valueCheck( String , false )
967         * command="ENTRY" のチェックは、厳密なチェックです。
968         * このフラグは、検索時でも、厳密なチェックを行いたい場合に、true をセットします。
969         *
970         * @og.rev 5.2.2.0 (2010/11/01) 新規作成
971         *
972         * @param   flg 厳密にチェックするかどうか [true:厳密/false:甘い]
973         */
974        public void setUseStrict( final String flg ) {
975                isStrict = nval( getRequestParameter( flg ),isStrict );
976        }
977
978        /**
979         * 【TAG】カラムラベルを使用するかどうか[true/false]を指定します(初期値:false)。
980         *
981         * @og.tag
982         * カラムラベルはラベルローダーを利用せずにアプリケーション側で
983         * 追加したラベルをResourceManagerにキャッシュしている所から取り出す
984         * かどうかを指定します。
985         * カラムラベルに存在しない場合は、通常のラベルから検索します。
986         *
987         * @og.rev 5.4.3.4 (2012/01/12) 新規作成
988         *
989         * @param   flg カラムラベルを使用するかどうか true:する/false:しない]
990         */
991        public void setUseColumnLabel( final String flg ) {
992                isColumnLabel = nval( getRequestParameter( flg ),isColumnLabel );
993        }
994
995        /**
996         * 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します。
997         *
998         * @og.tag
999         * カラムチェックで正規化が行われていないプラグインに対して強制的に正規化を行います。
1000         * この属性を利用したチェックを行った場合は、queryタグでPL/SQLを動作させる場合にも
1001         * 同名属性でカラムの指定を行う必要があります。
1002         * (queryタグでcheckNamesを利用しない場合はこの属性はnullにしてください)
1003         * この属性はチェックタイプがNEWの場合のみ有効です。
1004         * リアルタイムチェックでこの機能を利用したい場合は、columnTag等のoptionAttributes
1005         * 属性にrtOption='checkNames=VIEW_DATE'のように記述してください。
1006         *
1007         * @og.rev 5.4.3.8 (2012/01/24) 新規追加
1008         * @og.rev 5.4.4.0 (2012/02/01) コメント修正
1009         * @og.rev 5.6.9.4 (2013/10/31) 空白削除を行う
1010         *
1011         * @param       nm リクエスト変数の正規化を行うカラム
1012         */
1013        public void setCheckNames( final String nm ) {
1014                checkNames = StringUtil.deleteWhitespace( nval( getRequestParameter( nm ),checkNames ) ); // 5.6.9.4 (2013/10/31)
1015        }
1016
1017        /**
1018         * このオブジェクトの文字列表現を返します。
1019         * 基本的にデバッグ目的に使用します。
1020         *
1021         * @return このクラスの文字列表現
1022         */
1023        @Override
1024        public String toString() {
1025                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
1026                                .println( "VERSION"                     ,VERSION                )
1027                                .println( "tableId"                     ,tableId                )
1028                                .println( "command"                     ,command                )
1029                                .println( "columns"                     ,columns                )
1030                                .println( "nullCheck"           ,nullCheck              )
1031                                .println( "mustAnyCheck"        ,mustAnyCheck   )
1032                                .println( "maxRowCount"         ,maxRowCount    )
1033                                .println( "minRowCount"         ,minRowCount    )
1034                                .println( "checkType"           ,checkType              )
1035                                .println( "matchKeys"           ,matchKeys              )
1036                                .println( "matchVals"           ,matchVals              )
1037                                .println( "realTime"            ,isRealTime             )
1038                                .println( "bodyString"          ,StringUtil.htmlFilter( bodyString ) )
1039                                .println( "Other..."            ,getAttributes().getAttribute() )
1040                                .fixForm().toString() ;
1041        }
1042}