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