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.io.IOException;
021import java.io.ObjectInputStream;
022import java.io.ObjectOutputStream;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Locale;
027import java.util.Map;
028
029import javax.script.ScriptEngine;
030import javax.script.ScriptEngineManager;
031import javax.script.ScriptException;
032import javax.servlet.ServletException;
033
034import org.opengion.fukurou.db.DBUtil;
035import org.opengion.fukurou.db.Transaction;
036import org.opengion.fukurou.db.TransactionReal;
037import org.opengion.fukurou.model.Formatter;
038import org.opengion.fukurou.util.ErrorMessage;
039import org.opengion.fukurou.util.StringUtil;
040import org.opengion.hayabusa.common.HybsSystem;
041import org.opengion.hayabusa.common.HybsSystemException;
042import org.opengion.hayabusa.db.DBTableModel;
043import org.opengion.hayabusa.resource.ResourceManager;
044
045/**
046 * 画面で入力されたデータのチェックを行うためのタグです。
047 *
048 * commandがNEWの場合は検索条件等のリクエストパラメータに対してチェックを行います。
049 * commandがENTRYの場合は、登録時のDBテーブルモデルに対するチェックを行います。
050 * (値の取得は、先に選択された行のみについて、実行されます。)
051 *
052 * チェックを行うための定義は、SQL文 又は JavaScriptの式が記述可能です。
053 * これらの式はタグのボディー部分に記述します。
054 *
055 * SQL文によりチェックを行う場合は、必ず件数が返されるように記述して下さい(select count(*) ・・・ 等)
056 * このSQL文で取得された件数とexistの属性値とを照合しチェックを行います。
057 * いずれの場合も、成立時は、正常とみなします。
058 * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。)
059 *
060 * JavaScript式を記述する場合は、必ずtrue or falseを返す式を指定して下さい。
061 * この式を評価した結果falseが返される場合は、エラーとみなします。
062 * 式に不等号等を使用する場合は、CDATAセクションで囲うようにして下さい。
063 *
064 * また、いずれのチェック方法の場合でも、引数部に[カラム名]を用いたHybs拡張SQL文を
065 * 指定することが可能です。
066 * メッセージIDの{0},{1}にはそれぞれ[カラム名]指定されたカラム名及びデータがカンマ区切りで
067 * 自動的に設定されます。
068 *
069 * ※ このタグは、Transaction タグの対象です。
070 *
071 * @og.formSample
072 * <pre>
073 * ●形式:
074 *       ・&lt;og:dataCheck
075 *                    command       = "{&#064;command}"
076 *                    exist         = "[auto|true|false|one|notuse]"
077 *                    errRemove     = "[true|false]"
078 *                    lbl           = "{&#064;lbl}"
079 *                    lblParamKeys  = "ZY03"      : メッセージリソースのキーをカンマ区切りで指定。{2} 以降にセット
080 *                    sqlType       = "{&#064;sqlType}"
081 *                    execType      = "INSERT|COPY|UPDATE|MODIFY|DELETE"  : sqlType を含む場合、実行
082 *                    conditionKey  = "FGJ"        : 条件判定するカラムIDを指定(初期値は columnId )
083 *                    conditionList = "0|1|8|9"    : 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件)
084 *                    uniqCheckKeys = "CLM,LANG"   : DBTableModel内でのユニークキーチェックを行うためのカラム
085 *         &gt;
086 *
087 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
088 *         (SQL文 又は JavaScript式)
089 *       :なし( from属性、where属性を使用して、SQL文を内部で作成します)
090 *
091 * ●Tag定義:
092 *   &lt;og:dataCheck
093 *       command            【TAG】コマンド(NEW or ENTRY)をセットします
094 *       exist              【TAG】データベースのチェック方法[auto/true/false/one/notuse]を指定します(初期値:auto[自動])
095 *       tableId            【TAG】(通常は使いません)結果をDBTableModelに書き込んで、sessionに登録するときのキーを指定します
096 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
097 *       lbl                【TAG】ラベルリソースIDを指定します
098 *       lblParamKeys       【TAG】ラベルリソースの引数をカンマ区切りで指定します
099 *       errRemove          【TAG】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false)
100 *       sqlType            【TAG】このチェックを行う、SQLタイプ を指定します
101 *       execType           【TAG】このチェックを行う、実行タイプ を指定します
102 *       conditionKey       【TAG】条件判定するカラムIDを指定します
103 *       conditionList      【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件)
104 *       uniqCheckClms      【TAG】指定されたキーに従って、メモリ上のテーブルに対してユニークキーチェックを行います
105 *       beforeErrorJsp     【TAG】エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します
106 *       afterErrorJsp      【TAG】エラーが発生した際に、エラーメッセージの表示後にincludeするJSPを指定します
107 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)
108 *       msg                【廃止】メッセージIDを指定します(lbl 属性を使用してください)
109 *       msgParamKeys       【廃止】メッセージリソースの引数をカンマ区切りで指定します(lblParamKeys 属性を使用してください)
110 *       from               【TAG】tableExist タグ廃止に伴う、簡易機能追加。チェックするデータベース名(from 句)を指定します。
111 *       where              【TAG】tableExist タグ廃止に伴う、簡易機能追加。チェックする検索条件(where句)を指定します。
112 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
113 *   &gt;   ... Body ...
114 *   &lt;/og:dataCheck&gt;
115 *
116 * ●使用例
117 *       ・&lt;og:dataCheck
118 *                    command   = "ENTRY"
119 *                    exist     = "true"
120 *                    lbl       = "MSG0001"
121 *         &gt;
122 *             select count(*) from GEA03 where clm = [CLM]
123 *         &lt;/og:dataCheck&gt;
124 *
125 *          ・exist 属性の値に応じて、チェック方法が異なります。
126 *            [ auto , true , false , one , notuse が指定できます。]
127 *
128 *       ・&lt;og:dataCheck
129 *                    command   = "ENTRY"
130 *                    lbl       = "MSG0001"
131 *         &gt;
132 *           &lt;![CDATA[
133 *             [DYSTART] &lt; [DY] &amp;&amp; [DY] &lt; [DYEND]
134 *           ]]&gt;
135 *         &lt;/og:dataCheck&gt;
136 *
137 *         ・&lt;og:dataCheck
138 *                    command   = "ENTRY"
139 *                    lbl       = "MSG0001"
140 *         &gt;
141 *           &lt;![CDATA[
142 *             [GOKEI] &lt; [TANKA] * [RITU]
143 *           ]]&gt;
144 *         &lt;/og:dataCheck&gt;
145 *
146 *    ※ og:tableExist タグが廃止されました。og:dataCheckタグで置き換えてください。
147 *       ・&lt;og:tableExist
148 *                    command = "{&#064;command}"
149 *                    names   = "USERID,SYSTEM_ID"
150 *                    from    = "GE10"
151 *                    where   = "USERID=? AND SYSTEM_ID=?"
152 *                    exist   = "true"
153 *         /&gt;
154 * 
155 *        ⇒
156 *       ・&lt;og:dataCheck
157 *                    command = "{&#064;command}"
158 *                    exist   = "true"
159 *                    from    = "GE10"
160 *                    where   = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]"
161 *         /&gt;
162 * 
163 *       ・&lt;og:tableExist
164 *                    command = "{&#064;command}"
165 *                    from    = "GE10"
166 *                    where   = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]"  /&gt;
167 *        ⇒
168 *       ・&lt;og:dataCheck
169 *                    command = "{&#064;command}"
170 *                    from    = "GE10"
171 *                    where   = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]"  /&gt;
172 *         /&gt;
173 *
174 * </pre>
175 *
176 * @og.rev 4.1.1.1 (2008/02/22) 新規作成
177 * @og.group DB登録
178 *
179 * @version  4.0
180 * @author       Hiroki Nakamura
181 * @since    JDK5.0,
182 */
183public class DataCheckTag extends CommonTagSupport {
184        //* このプログラムのVERSION文字列を設定します。   {@value} */
185        private static final String VERSION = "5.7.6.2 (2014/05/16)";
186
187        private static final long       serialVersionUID        = 576220140516L ;
188
189        /** command 引数に渡す事の出来る コマンド {@value} */
190        public static final String              CMD_NEW                         = "NEW";
191
192        /** command 引数に渡す事の出来る コマンド {@value} */
193        public static final String              CMD_ENTRY                       = "ENTRY";
194
195        /** command 引数に渡す事の出来る コマンド リスト  */
196        private static final String[]   COMMAND_LIST            = { CMD_ENTRY, CMD_NEW };
197
198        /** 内部変数 */
199        private transient DBTableModel  table           = null;
200        private transient boolean               isSql           = false;
201        private transient boolean               isUniqCheck     = false; // 4.3.4.0 (2008/12/01) 追加
202        private transient ScriptEngine  jsEngine        = null;
203        private transient String                bodyStr         = null; // 4.3.4.0 (2008/12/01) 追加
204
205        /** タグで設定する属性 */
206        private String          command                 = CMD_ENTRY;
207        private String          exist                   = "auto";
208        private String          tableId                 = HybsSystem.TBL_MDL_KEY;
209        private String          dbid                    = null;
210        private String          lbl                             = null;
211        private String[]        lblParamKeys    = null;         // 4.2.0.1 (2008/03/27)
212        private boolean         errRemove               = false;
213        private String          sqlType                 = null;         // INSERT,COPY,UPDATE,MODIFY,DELETE
214        private String          execType                = null;         // INSERT,COPY,UPDATE,MODIFY,DELETE
215        private boolean         isExec                  = true;         // 4.1.2.0 (2008/03/12)
216
217        private String          conditionKey    = null;         // 4.2.0.1 (2008/03/27)
218        private String          conditionList   = null;         // 4.2.0.1 (2008/03/27)
219        private String          from                    = null;         // 4.2.0.1 (2008/03/27)
220        private String          where                   = null;         // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加
221        private String[]        uniqCheckClms   = null;         // 4.3.4.0 (2008/12/01)
222
223        private String          beforeErrorJsp  = null;         // 5.1.9.0 (2010/08/01)
224        private String          afterErrorJsp   = null;         // 5.1.9.0 (2010/08/01)
225        private boolean         selectedAll             = false;        // 5.1.9.0 (2010/08/01)
226
227        /**
228         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
229         *
230         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
231         * @og.rev 4.1.2.0 (2008/03/12) sqlType,execType 判定
232         *
233         * @return      後続処理の指示
234         */
235        @Override
236        public int doStartTag() {
237                isExec = sqlType == null || execType == null || execType.indexOf( sqlType ) >= 0 ;
238
239                if( isExec ) {
240                        return EVAL_BODY_BUFFERED ;             // Body を評価する
241                }
242                else {
243                        return SKIP_BODY ;                              // Body を評価しない
244                }
245        }
246
247        /**
248         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
249         *
250         * @og.rev 4.3.4.0 (2008/12/01) 新規追加
251         *
252         * @return      後続処理の指示(SKIP_BODY)
253         */
254        @Override
255        public int doAfterBody() {
256                bodyStr = getBodyString().trim();
257                return SKIP_BODY ;
258        }
259
260        /**
261         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
262         *
263         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
264         * @og.rev 4.1.2.0 (2008/03/12) sqlType,execType 判定
265         * @og.rev 4.2.0.1 (2008/03/27) from を取得
266         * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応
267         * @og.rev 4.3.4.0 (2008/12/01) ユニークキーチェック対応。bodyContentの取得を#doAfterBody()で行う。
268         * @og.rev 5.1.9.0 (2010/08/01) エラーメッセージの表示前後にincludeするJSPを指定できるようにする。
269         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
270         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 、Transaction対応で、close処理を入れる。
271         *
272         * @return      後続処理の指示
273         */
274        @Override
275        public int doEndTag() {
276                debugPrint();
277                int rtnCode = EVAL_PAGE;
278
279                // 4.1.2.0 (2008/03/12) 実行条件 isExec を評価
280                if( isExec && check( command, COMMAND_LIST ) ) {
281                        // exist="notuse"の場合はチェックしない
282                        if( "notuse".equalsIgnoreCase( exist ) ) { return rtnCode; }
283
284                        // パラメーターから処理のタイプを判別
285                        checkParam();
286
287                        // エラーメッセージを管理するクラスを作成します。
288                        ErrMessageManager manager = new ErrMessageManager();
289                        manager.setTitle( "Data Check Error!" );
290                        manager.setParamKeys( lblParamKeys );
291                        manager.setResourceManager( getResource() );
292                        manager.setFrom( from );
293
294                        // 5.1.9.0 (2010/08/01) TransactionTag 対応
295                        Transaction tran = null ;
296                        // 5.3.7.0 (2011/07/01) Transaction対応で、close処理を入れる。
297                        try {
298                                if( isSql ) {
299                                        TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class );
300                                        if( tranTag == null ) {
301                                                tran = new TransactionReal( getApplicationInfo() );             // 5.3.7.0 (2011/07/01) 引数変更
302                                        }
303                                        else {
304                                                tran = tranTag.getTransaction();
305                                        }
306                                }
307
308                                // command="NEW"の場合
309                                if( CMD_NEW.equals( command ) ) {
310                                        if( isSql ) {
311                                                checkSql( bodyStr, manager, null, 0, DBTableModel.UPDATE_TYPE, tran );          // 5.1.9.0 (2010/08/01)
312                                        }
313                                        else {
314                                                checkJs( bodyStr, manager, null, 0, jsEngine );
315                                        }
316                                }
317                                // command="ENTRY"の場合(テーブルモデルが存在しない場合は処理しない)
318                                else if( CMD_ENTRY.equals( command ) ) {
319                                        table = (DBTableModel) getObject( tableId );
320                                        if( table != null && table.getRowCount() > 0 ) {
321                                                manager.setDBTableModel( table );
322                                                if( isUniqCheck ) {
323                                                        checkUnique( manager );
324                                                }
325                                                else {
326                                                        checkRows( bodyStr, manager, tran );            // 5.1.9.0 (2010/08/01)
327                                                }
328                                        }
329                                        else {
330                                                System.out.println( "DBTableModel doesn't exist!! need this when command=\"ENTRY\"" );
331                                        }
332                                }
333                        }
334                        finally {
335                                if( tran != null ) { tran.close(); }
336                        }
337
338                        // エラーが発生した場合は、エラーメッセージを表示して以降の処理を行わない。
339                        ErrorMessage errMessage = manager.getErrMessage() ;
340                        if( errMessage != null && !errMessage.isOK() && !errRemove ) {
341                                rtnCode = SKIP_PAGE;
342
343                                // 5.1.9.0 (2010/08/01) エラーメッセージの表示前にincludeするJSPを指定
344                                if( beforeErrorJsp != null && beforeErrorJsp.length() > 0 ) {
345                                        includeJsp( beforeErrorJsp );
346                                }
347
348                                jspPrint( TaglibUtil.makeHTMLErrorTable( errMessage, getResource() ) );
349
350                                // 5.1.9.0 (2010/08/01) エラーメッセージの表示後にincludeするJSPを指定
351                                if( afterErrorJsp != null && afterErrorJsp.length() > 0 ) {
352                                        includeJsp( afterErrorJsp );
353                                }
354                        }
355                }
356
357                return rtnCode ;
358        }
359
360        /**
361         * タグリブオブジェクトをリリースします。
362         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
363         *
364         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
365         * @og.rev 4.1.2.0 (2008/03/12) sqlType , execType , isExec 追加
366         * @og.rev 4.2.0.1 (2008/03/27) conditionKey , conditionList , msgParamKeys 追加
367         * @og.rev 5.1.9.0 (2010/08/01) beforeErrorJsp , afterErrorJsp, selectedAll 追加
368         * @og.rev 5.7.6.2 (2014/05/16) where 追加。tableExist タグに伴う便利機能追加
369         */
370        @Override
371        protected void release2() {
372                super.release2();
373                tableId                 = HybsSystem.TBL_MDL_KEY;
374                dbid                    = null;
375                command                 = CMD_ENTRY;
376                table                   = null;
377                exist                   = "auto";
378                errRemove               = false;
379                lbl                     = null;
380                lblParamKeys    = null;         // 4.2.0.1 (2008/03/27)
381                isSql                   = false;
382                isUniqCheck             = false;        // 4.3.4.0 (2008/12/01)
383                jsEngine                = null;
384                sqlType                 = null;         // INSERT,COPY,UPDATE,MODIFY,DELETE
385                execType                = null;         // INSERT,COPY,UPDATE,MODIFY,DELETE
386                isExec                  = true;         // 4.1.2.0 (2008/03/12)
387                conditionKey    = null;         // 4.2.0.1 (2008/03/27)
388                conditionList   = null;         // 4.2.0.1 (2008/03/27)
389                from                    = null;         // 4.2.0.1 (2008/03/27)
390                where                   = null;         // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加
391                bodyStr                 = null;         // 4.3.4.0 (2008/12/01))
392                uniqCheckClms   = null;         // 4.3.4.0 (2008/12/01)
393                beforeErrorJsp  = null;         // 5.1.9.0 (2010/08/01)
394                afterErrorJsp   = null;         // 5.1.9.0 (2010/08/01)
395                selectedAll             = false;        // 5.1.9.0 (2010/08/01)
396        }
397
398        /**
399         * 引数及びボディー部分のチェックを行い、処理のタイプを判別します。
400         *
401         * @og.rev 5.5.8.0 (2012/11/01) タイプ判別変更
402         * @og.rev 5.6.1.1 (2013/02/08) FROM 部の切り出し位置修正
403         * @og.rev 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加。from属性とwhere属性追加
404         */
405        private void checkParam() {
406                isUniqCheck = uniqCheckClms != null && uniqCheckClms.length > 0 ;
407                if( isUniqCheck ) {
408                        if( !CMD_ENTRY.equals( command ) ) {
409                                String errMsg = "ユニークキーチェックは、command=\"ENTRY\"の場合のみ使用可能です。"
410                                                        + " command=" + command ;               // 5.1.8.0 (2010/07/01) errMsg 修正
411                                throw new HybsSystemException( errMsg );
412                        }
413                }
414                // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加。from属性とwhere属性追加
415                else if( from != null ) {
416                        StringBuilder buf = new StringBuilder();
417                        buf.append( "SELECT count(*) FROM " ).append( from );
418                        if( where != null ) { buf.append( " WHERE " ).append( where ); }
419                        bodyStr = buf.toString();
420                        isSql = true;
421                }
422                else {
423                        if( bodyStr == null || bodyStr.length() == 0 ) {
424                                String errMsg = "Body部分にチェック定義を記述して下さい。";
425                                throw new HybsSystemException( errMsg );
426                        }
427                        else {
428                                // SQLチェックかJavaScriptによるチェックかの判定
429                                String query = bodyStr.toUpperCase( Locale.JAPAN );             // 4.2.0.1 (2008/03/27)
430                                if( query.indexOf( "SELECT" ) == 0 ) { // 5.5.8.0 (2012/11/01) 先頭に限定する。(trim済のため)
431                                        isSql = true;
432                                        int st = query.indexOf( "FROM" ) ;
433                                        int ed = query.indexOf( "WHERE" ) ;
434                                        if( st > 0 && st < ed ) {
435                                                from = query.substring( st+"FROM".length(),ed ).trim();         // 5.6.1.1 (2013/02/08)
436                                        }
437                                }
438                                else {
439                                        jsEngine = new ScriptEngineManager().getEngineByName( "JavaScript" );
440                                }
441                        }
442                }
443        }
444
445        /**
446         * SQLによるデータチェックを行います。
447         * チェック方法は、exist属性の指定に依存します。
448         * autoの場合は、テーブルモデルの改廃Cから自動でチェック方法が決定されます。
449         *
450         * @param       str     実行するSQL文
451         * @param       manager ErrMessageManager オブジェクト
452         * @param       values  SQL文のパラメータ
453         * @param       row     行番号
454         * @param       modifyType      改廃C
455         * @param       tran    トランザクションオブジェクト
456         *
457         * @return      処理の成否
458         *
459         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
460         * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応
461         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
462         */
463        private boolean checkSql( final String str, final ErrMessageManager manager, final String[] values
464                                                        , final int row, final String modifyType, final Transaction tran ) {
465
466                int cnt = DBUtil.dbExist( str, values, tran, dbid );                    // 5.1.9.0 (2010/08/01)
467
468                boolean okFlag = true;
469                String id = null;
470                if( ( "true".equalsIgnoreCase( exist ) || ( "auto".equalsIgnoreCase( exist )
471                                && ( DBTableModel.UPDATE_TYPE.equals( modifyType ) || DBTableModel.DELETE_TYPE.equals( modifyType ) ) ) ) && cnt <= 0 ) {
472                        // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。
473                        id = ( lbl == null ? "ERR0025" : lbl );
474                        okFlag = false;
475                }
476                else if( ( "false".equalsIgnoreCase( exist ) || ( "auto".equalsIgnoreCase( exist )
477                                && DBTableModel.INSERT_TYPE.equals( modifyType ) ) ) && cnt > 0 ) {
478                        // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。
479                        id = ( lbl == null ? "ERR0026" : lbl );
480                        okFlag = false;
481                }
482                else if( "one".equalsIgnoreCase( exist ) && cnt > 1 ) {
483                        // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。
484                        id = ( lbl == null ? "ERR0027" : lbl );
485                        okFlag = false;
486                }
487
488                if( !okFlag ) {
489                        manager.addMessage( row, id, values );
490
491                }
492                return okFlag;
493        }
494
495        /**
496         * JavaScriptの式を実行します。
497         * 実行した結果がboolean型でない場合はエラーとなります。
498         *
499         * @param str  実行するSQL文
500         * @param       manager オブジェクト
501         * @param values 値配列
502         * @param row 行番号
503         * @param engine JavaScriptエンジン
504         *
505         * @return 処理の成否
506         *
507         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
508         * @og.rev 4.2.0.1 (2008/03/27) getClass().getName() から、instanceof に変更
509         * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応
510         */
511        private boolean checkJs(  final String str, final ErrMessageManager manager, final String[] values
512                                                        , final int row, final ScriptEngine engine ) {
513                // JavaScriptエンジンによる評価
514                Object obj = null;
515                try {
516                        obj = engine.eval( str );
517                }
518                catch( ScriptException ex ) {
519                        String errMsg = "JavaScript式のパースに失敗しました。[" + str + "]";
520                        throw new HybsSystemException( errMsg , ex );
521                }
522
523                // 返り値がBoolean型かチェック
524                boolean okFlag = false;
525                // 4.2.0.1 (2008/03/27) instanceof に変更
526                if( obj instanceof Boolean ) {  // 4.3.1.1 (2008/08/23) instanceof チェックは、nullチェック不要
527                        okFlag = ((Boolean)obj).booleanValue();
528                }
529                else {
530                        String errMsg = "JavaScript式には true 若しくは false が返るように設定して下さい"
531                                                + " Object=" + obj ;                    // 5.1.8.0 (2010/07/01) errMsg 修正
532                        throw new HybsSystemException( errMsg );
533                }
534
535                if( !okFlag ) {
536                        // ERR0030=入力したデータが不正です。key={0} value={1} 形式={2}
537                        String id = ( lbl == null ? "ERR0030" : lbl );
538
539                        manager.addMessage( row, id, values );
540                }
541
542                return okFlag;
543        }
544
545        /**
546         * DBテーブルモデルの各行に対してデータチェックを行います。
547         *
548         * @param str チェック対象の文字列
549         * @param manager ErrMessageManagerオブジェクト
550         * @param tran Transactionトランザクションオブジェクト
551         *
552         * @og.rev 4.1.1.0 (2008/02/22) 新規作成
553         * @og.rev 4.2.0.1 (2008/03/27) conditionKey,conditionList 対応
554         * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応
555         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
556         */
557        private void checkRows( final String str, final ErrMessageManager manager, final Transaction tran ) {
558
559                int[] rowNo = getParameterRows(); // 4.0.0 (2005/01/31)
560                if( rowNo.length == 0 ) { return; }
561
562                Formatter format = new Formatter( table );
563                format.setFormat( str );
564                int[] clmNo = format.getClmNos();
565                // 4.2.0.1 (2008/03/27) カラム名のメッセージリソース文字列を作成します。
566                manager.setClmNos( clmNo );
567
568                // SQL文の場合のみ[xxx]を?に変換したSQL文を取得(JavaScriptの場合はループ内で各行毎に取得
569                String query = null;
570                if( isSql ) {
571                        query = format.getQueryFormatString();
572                }
573
574                // 4.2.0.1 (2008/03/27) conditionKey,conditionList 対応
575                int cndKeyNo = -1;
576                if( conditionKey != null && conditionList != null ) {
577                        cndKeyNo = table.getColumnNo( conditionKey );           // 不正指定はエラー
578                }
579
580                List<Integer> list = new ArrayList<Integer>();
581                boolean okFlag = false;
582                for( int i = 0; i < rowNo.length; i++ ) {
583                        int row = rowNo[i] ;
584                        String[] values = getTableModelData( row, clmNo );
585                        // 4.2.0.1 (2008/03/27) 条件指定がされている場合に、
586                        // Listに含まれない場合は、実行されない。
587                        // 4.2.1.0 (2008/04/11) 厳密に処理します。
588                        if( cndKeyNo >= 0 && conditionList.indexOf( table.getValue( row,cndKeyNo ) ) < 0 ) {
589                                String conVal = "|" + table.getValue( row,cndKeyNo ) + "|" ;
590                                if( conditionList.indexOf( conVal ) < 0 ) { continue; }
591                        }
592
593                        if( isSql ) {
594                                okFlag = checkSql( query, manager, values, row, table.getModifyType( row ), tran );
595                        }
596                        else {
597                                String jsStr = format.getFormatString( row, "\"" );
598                                okFlag = checkJs( jsStr, manager, values, row, jsEngine );
599                        }
600
601                        if( errRemove && okFlag ) {
602                                list.add( row );
603                        }
604                }
605
606                if( errRemove ) {
607                        Integer[] in = list.toArray( new Integer[list.size()] );
608                        int[] newRowNo = new int[in.length];
609                        for( int i = 0; i < in.length; i++ ) {
610                                newRowNo[i] = in[i].intValue();
611                        }
612                        setParameterRows( newRowNo );
613                }
614        }
615
616        /**
617         * DBテーブルモデルの各行にユニークキーのチェックを行います。
618         *
619         * @og.rev 4.3.4.0 (2008/12/01) 新規作成
620         *
621         * @param manager ErrMessageManagerオブジェクト
622         */
623        private void checkUnique( final ErrMessageManager manager ) {
624                int[] rowNo = getParameterRows();
625                if( rowNo.length == 0 ) { return; }
626
627                int[] clmNo = new int[uniqCheckClms.length];
628                for( int i=0; i<clmNo.length; i++ ) {
629                        clmNo[i] = table.getColumnNo( uniqCheckClms[i] );
630                }
631
632                manager.setClmNos( clmNo );
633
634                List<Integer> list = new ArrayList<Integer>();
635                Map<String,Integer> map = new HashMap<String,Integer>();
636                for( int i = 0; i < rowNo.length; i++ ) {
637                        int row = rowNo[i] ;
638                        String[] values = getTableModelData( row, clmNo );
639                        String key = StringUtil.array2line( values, " + " );
640
641                        if( map.get( key ) == null ) {
642                                map.put( key, 1 );
643                                if( errRemove ) {
644                                        list.add( row );
645                                }
646                        }
647                        else {
648                                // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。
649                                id = ( lbl == null ? "ERR0027" : lbl );
650                                manager.addMessage( row, id, values );
651                        }
652                }
653
654                if( errRemove ) {
655                        Integer[] in = list.toArray( new Integer[list.size()] );
656                        int[] newRowNo = new int[in.length];
657                        for( int i = 0; i < in.length; i++ ) {
658                                newRowNo[i] = in[i].intValue();
659                        }
660                        setParameterRows( newRowNo );
661                }
662        }
663
664        /**
665         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
666         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
667         *
668         * @og.tag
669         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
670         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
671         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
672         * この tableId 属性を利用して、メモリ空間を分けます。
673         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
674         *
675         * @param       id sessionに登録する時の ID
676         */
677        public void setTableId( final String id ) {
678                tableId = nval( getRequestParameter( id ), tableId );
679        }
680
681        /**
682         * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。
683         *
684         * @og.tag Queryオブジェクトを作成する時のDB接続IDを指定します。
685         *
686         * @param       id データベース接続ID
687         */
688        public void setDbid( final String id ) {
689                dbid = nval( getRequestParameter( id ), dbid );
690        }
691
692        /**
693         * 【TAG】コマンド(NEW or ENTRY)をセットします。
694         *
695         * @og.tag
696         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
697         * フィールド定数値のいづれかを、指定できます。
698         *
699         * @param       cmd コマンド(public static final 宣言されている文字列)
700         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.DataCheckTag.CMD_NEW">コマンド定数</a>
701         */
702        public void setCommand( final String cmd ) {
703                String cmd2 = getRequestParameter( cmd );
704                if( cmd2 != null && cmd2.length() > 0 ) {
705                        command = cmd2.toUpperCase( Locale.JAPAN );
706                }
707        }
708
709        /**
710         * 【TAG】データベースのチェック方法[auto/true/false/one/notuse]を指定します(初期値:auto[自動])。
711         *
712         * @og.tag
713         * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、
714         * の値は、いずれの場合も、成立時は、正常とみなします。
715         * 「auto:自動」は、DBTableModeleのmodifyType(A,C,D)に応じて、チェックします。
716         * A,C,D は、entryタグにコマンドを渡してデータを作成したときに、内部で作成されます。
717         * (command="NEW"の場合は、trueと同じ動きになります。)
718         * notuse は、チェックを行いません。これは、このタグを共有使用する場合に、外部で
719         * チェックを行うかどうかを指定できるようにするために使用します。
720         * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。)
721         * 初期値は、「auto:自動」です。
722         *
723         * @param       ext チェック方法(「auto:自動」、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、「notuse:チェックしない」)
724         */
725        public void setExist( final String ext ) {
726                exist = nval( getRequestParameter( ext ), exist );
727                if( !"auto".equalsIgnoreCase( exist )
728                                && !"true".equalsIgnoreCase( exist )
729                                && !"false".equalsIgnoreCase( exist )
730                                && !"one".equalsIgnoreCase( exist )
731                                && !"notuse".equalsIgnoreCase( exist ) ) {
732                        String errMsg = "exist 属性は、(auto,true,false,one,notuse)を指定してください。 [" + exist + "]" + HybsSystem.CR;
733                        throw new HybsSystemException( errMsg );
734                }
735        }
736
737        /**
738         * 【TAG】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false)。
739         *
740         * @og.tag
741         * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、
742         * に対して、エラーが発生した選択行番号を、取り除いて以下の処理を継続するかどうかを
743         * 指定します。
744         * true に設定した場合は、エラーデータを削除し、継続処理を行うことができます。
745         * flase の場合は、エラーデータを表示して、継続処理を停止します。
746         * 初期値は、「false:エラー時停止」です。
747         *
748         * @param       flag エラー時の継続処理 [true:エラー行番号を取り除き継続処理/false:エラー時停止]
749         */
750        public void setErrRemove( final String flag ) {
751                errRemove = nval( getRequestParameter( flag ), errRemove );
752        }
753
754        /**
755         * 【廃止】メッセージIDを指定します(lbl 属性を使用してください)。
756         *
757         * @og.tag メッセージIDを指定します。
758         * 各処理に応じた初期設定のメッセージIDは、以下の通りです。
759         *   exist="true"   ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。
760         *   exist="false"  ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。
761         *   exist="one"    ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。
762         *   JavaScript     ERR0030=入力したデータが不正です。key={0} value={1} 形式={2}
763         * 引数のパラメータには、通常、チェックに使用した実データが、DBTableModel から取得されます。
764         * 引数を変更する場合は、lblParamKeys を使用してください。
765         *
766         * @og.rev 5.2.2.0 (2010/11/01) 廃止します。lbl 属性を使用してください。
767         *
768         * @param id メッセージID
769         * @see    #setMsgParamKeys( String )
770         * @deprecated  lbl 属性を使用してください。
771         */
772        @Deprecated public void setMsg( final String id ) {
773                setLbl( id );
774//              msg = nval( getRequestParameter( id ), msg );
775        }
776
777        /**
778         * 【TAG】ラベルリソースIDを指定します。
779         *
780         * @og.tag ラベルリソースIDを指定します。
781         * 各処理に応じた初期設定のラベルリソースIDは、以下の通りです。
782         *   exist="true"   ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。
783         *   exist="false"  ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。
784         *   exist="one"    ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。
785         *   JavaScript     ERR0030=入力したデータが不正です。key={0} value={1} 形式={2}
786         * 引数のパラメータには、通常、チェックに使用した実データが、DBTableModel から取得されます。
787         * 引数を変更する場合は、lblParamKeys を使用してください。
788         *
789         * @param id メッセージID
790         * @see    #setLblParamKeys( String )
791         */
792        @Override
793        public void setLbl( final String id ) {
794                // 継承親のメソッドを使わない。
795                lbl = nval( getRequestParameter( id ), lbl );
796        }
797
798        /**
799         * 【廃止】メッセージリソースの引数をカンマ区切りで指定します(lblParamKeys 属性を使用してください)。
800         *
801         * @og.tag
802         * メッセージリソースのキーをカンマ区切りで指定することで、設定します。
803         * メッセージに引数( {0},{1} など ) がある場合、ここで指定した値を
804         * 順番に、{0},{1},{2}・・・ に当てはめていきます。
805         * キーワードは、カンマ区切りで指定し、それを分解後、ラベルリソースで
806         * リソース変換を行います。(つまり、記述された値そのものでは在りません)
807         * PL/SQL では、"{#PN}" などと指定していた分は、同様に "PN" と指定しです。
808         * 内部的に、where 条件に指定されたキーと値は、@KEY と @VAL に、
809         * from と where の間の文字列は、&#064;TBL に対応付けられます。
810         * {&#064;XXXX} 変数も使用できます。実データの値を取出したい場合は、[PN]と
811         * すれば、DBTableModel の PN の値を取出します。
812         * なにも指定しない場合は、キー={0} 、値={1}、from={2} です。
813         *
814         * @og.rev 4.2.0.1 (2008/03/27) 新規追加
815         * @og.rev 5.2.2.0 (2010/11/01) 廃止します。lbl 属性を使用してください。
816         *
817         * @param keys メッセージリソースのキー(CSV)
818         * @see    #setLbl( String )
819         * @deprecated  lblParamKeys 属性を使用してください。
820         */
821        @Deprecated public void setMsgParamKeys( final String keys ) {
822                setLblParamKeys( keys );
823//              lblParamKeys = getCSVParameter( keys );
824        }
825
826        /**
827         * 【TAG】ラベルリソースの引数をカンマ区切りで指定します。
828         *
829         * @og.tag
830         * ラベルリソースのキーをカンマ区切りで指定することで、設定します。
831         * ラベルに引数( {0},{1} など ) がある場合、ここで指定した値を
832         * 順番に、{0},{1},{2}・・・ に当てはめていきます。
833         * キーワードは、カンマ区切りで指定し、それを分解後、ラベルリソースで
834         * リソース変換を行います。(つまり、記述された値そのものでは在りません)
835         * PL/SQL では、"{#PN}" などと指定していた分は、同様に "PN" と指定しです。
836         * 内部的に、where 条件に指定されたキーと値は、&#064;KEY と &#064;VAL に、
837         * from と where の間の文字列は、&#064;TBL に対応付けられます。
838         * {&#064;XXXX} 変数も使用できます。実データの値を取出したい場合は、[PN]と
839         * すれば、DBTableModel の PN の値を取出します。
840         * なにも指定しない場合は、キー={0} 、値={1}、from={2} です。
841         *
842         * @og.rev 4.2.0.1 (2008/03/27) 新規追加
843         *
844         * @param keys メッセージリソースのキー(CSV)
845         * @see    #setLbl( String )
846         */
847        public void setLblParamKeys( final String keys ) {
848                lblParamKeys = getCSVParameter( keys );
849        }
850
851        /**
852         * 【TAG】このチェックを行う、SQLタイプ を指定します。
853         *
854         * @og.tag
855         * SQLタイプは、INSERT,COPY,UPDATE,MODIFY,DELETE などの記号を指定します。
856         * 一般には、result 画面から update 画面へ遷移するときの、command と
857         * 同じにしておけばよいでしょう。
858         * これは、execType とマッチした場合のみ、このチェックが処理されます。
859         * 簡易 equals タグの代役に使用できます。
860         * なにも指定しない場合は、チェックは実行されます。
861         *
862         * @og.rev 4.1.2.0 (2008/03/12) 新規追加
863         *
864         * @param       type このチェックを行う、SQLタイプ
865         */
866        public void setSqlType( final String type ) {
867                sqlType = nval( getRequestParameter( type ),sqlType );
868        }
869
870        /**
871         * 【TAG】このチェックを行う、実行タイプ を指定します。
872         *
873         * @og.tag
874         * 実行タイプは、sqlType とマッチした場合のみ、このチェックが処理されます。
875         * 簡易 equals タグの代役に使用できます。
876         * execType は、複数指定が可能です。単純な文字列マッチで、sqlType を
877         * 含めば、実行されます。
878         * 例えば、sqlType={&#064;sqlType} execType="INSERT|COPY" とすれば、
879         * sqlType に、INSERT または、COPY が登録された場合にチェックが掛かります。
880         * なにも指定しない場合は、チェックは実行されます。
881         *
882         * @og.rev 4.1.2.0 (2008/03/12) 新規追加
883         *
884         * @param       type このチェックを行う、実行タイプ
885         */
886        public void setExecType( final String type ) {
887                execType = nval( getRequestParameter( type ),execType );
888        }
889
890        /**
891         * 【TAG】条件判定するカラムIDを指定します。
892         *
893         * @og.tag
894         * 指定のカラムIDの値と、conditionList の値を比較して、
895         * 存在する場合は、check処理を実行します。
896         * この処理が有効なのは、command="ENTRY" の場合のみです。
897         *
898         * @og.rev 4.2.0.1 (2008/03/27) 新規追加
899         *
900         * @param       key カラムID
901         * @see         #setConditionList( String )
902         */
903        public void setConditionKey( final String key ) {
904                conditionKey = nval( getRequestParameter( key ),null ) ;
905        }
906
907        /**
908         * 【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件)。
909         *
910         * @og.tag
911         * conditionKey とペアで指定します。ここには、カラムの設定値のリストを
912         * 指定することで、複数条件(OR結合)での比較を行い、リストにカラム値が
913         * 存在する場合のみ、check処理を実行します。
914         * この処理が有効なのは、command="ENTRY" の場合のみです。
915         * 設定しない場合は、無条件に実行します。
916         *
917         * @og.rev 4.2.0.1 (2008/03/27) 新規追加
918         *
919         * @param       list 条件判定する値("|"で区切)
920         * @see         #setConditionKey( String )
921         */
922        public void setConditionList( final String list ) {
923                conditionList = nval( getRequestParameter( list ),null ) ;
924                if( conditionList != null ) {
925                        conditionList = "|" + conditionList + "|" ;
926                }
927        }
928
929        /**
930         * 【TAG】指定されたキーに従って、メモリ上のテーブルに対してユニークキーチェックを行います。
931         *
932         * @og.tag
933         * ユニークキーチェックを行うキーを指定します。ここで、指定されたキーに対して、
934         * DBTableModelの値をチェックし、全てのキーに同じ値となっている行が存在すればエラーとなります。
935         * このチェックは、command="ENTRY"の場合のみ有効です。
936         * また、このチェックは他のチェック(DB存在チェックなど)と同時に処理することはできません。
937         * キーが指定され手いる場合は、ボディ部分に記述されている定義は無視されます。
938         * errRemoveの属性がtrueに指定されている場合、重複行は、DBTableModelの並び順から見て、
939         * 最初の行のみ処理され、2つめ以降の重複行は無視されます。
940         * なお、キーはカンマ区切り(CSV形式)で複数指定が可能です。
941         *
942         * @og.rev 4.3.4.0 (2008/12/01) 新規追加
943         *
944         * @param       clm チェックキー(CSV形式)
945         */
946        public void setUniqCheckClms( final String clm ) {
947                String tmp = nval( getRequestParameter( clm ),null );
948                uniqCheckClms = StringUtil.csv2Array( tmp );
949        }
950
951        /**
952         * 【TAG】エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。
953         *
954         * @og.tag
955         * エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。
956         * エラーが発生していない場合は、ここで指定されたJSPが処理されることはありません。
957         * 通常は、戻るリンクなどを指定します。
958         *
959         * 指定の方法は、相対パス、絶対パスの両方で指定することができます。
960         * 但し、絶対パスで指定した場合、その基点は、コンテキストのルートディレクトリになります。
961         * 例) beforeErrorJsp = "/jsp/common/history_back.jsp"
962         *
963         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
964         *
965         * @param jsp 表示前にincludeするJSPファイル名
966         */
967        public void setBeforeErrorJsp( final String jsp ) {
968                beforeErrorJsp = nval( getRequestParameter( jsp ),beforeErrorJsp );
969        }
970
971        /**
972         * 【TAG】エラーが発生した際に、エラーメッセージの表示後にincludeするJSPを指定します。
973         *
974         * @og.tag
975         * エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。
976         * エラーが発生していない場合は、ここで指定されたJSPが処理されることはありません。
977         *
978         * 指定の方法は、相対パス、絶対パスの両方で指定することができます。
979         * 但し、絶対パスで指定した場合、その基点は、コンテキストのルートディレクトリになります。
980         * 例) afterErrorJsp = "/jsp/common/history_back.jsp"
981         *
982         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
983         *
984         * @param jsp 表示後にincludeするJSPファイル名
985         */
986        public void setAfterErrorJsp( final String jsp ) {
987                afterErrorJsp = nval( getRequestParameter( jsp ),afterErrorJsp );
988        }
989
990        /**
991         * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。
992         *
993         * @og.tag
994         * 全てのデータを選択済みデータとして扱って処理します。
995         * 全件処理する場合に、(true/false)を指定します。
996         * 初期値は false です。
997         *
998         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
999         *
1000         * @param  all 選択済みとして処理するかどうか[true:全件選択済み/false:通常]
1001         */
1002        public void setSelectedAll( final String all ) {
1003                selectedAll = nval( getRequestParameter( all ),selectedAll );
1004        }
1005
1006        /**
1007         * 【TAG】チェックするデータベース名(from 句)を指定します。
1008         *
1009         * @og.tag
1010         * これは、tableExist タグ廃止に伴う便利機能で、通常、BODYに記述された
1011         * SELECT count(*) from XXXX where XXXXX で、チェックしますが、
1012         * from 属性 と、where 属性を指定する事で、内部で、チェック用のSQL文を
1013         * 作成します。
1014         * from が指定された場合は、BODY は無視されますので、ご注意ください。
1015         *
1016         * @og.rev 5.7.6.2 (2014/05/16) 新規追加
1017         *
1018         * @param  frm チェックするテーブルID
1019         */
1020        public void setFrom( final String frm ) {
1021                from = nval( getRequestParameter( frm ),from );
1022        }
1023
1024        /**
1025         * 【TAG】チェックする検索条件(where句)を指定します。
1026         *
1027         * @og.tag
1028         * これは、tableExist タグ廃止に伴う便利機能で、通常、BODYに記述された
1029         * SELECT count(*) from XXXX where XXXXX で、チェックしますが、
1030         * from 属性 と、where 属性を指定する事で、内部で、チェック用のSQL文を
1031         * 作成します。
1032         * where は、from が指定された場合のみ、有効ですし、where を指定しなければ、
1033         * 全件検索になります。
1034         * tableExist タグと異なるのは、where の指定の仕方で、tableExist タグでは、
1035         * names 属性と、対応する where には、? で記述していましたが、
1036         * dataCheck タグでは、通常の [] でDBTableModelの値を指定します。
1037         *
1038         * @og.rev 5.7.6.2 (2014/05/16) 新規追加
1039         *
1040         * @param  whr チェックするWHERE 条件
1041         */
1042        public void setWhere( final String whr ) {
1043                where = nval( getRequestParameter( whr ),where );
1044        }
1045
1046        /**
1047         * 指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。
1048         *
1049         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を
1050         * 処理の対象とします。
1051         *
1052         * @og.rev 4.2.0.1 (2008/03/27) row と clm を入れ替えます。(他とあわせます)
1053         *
1054         * @param       row   行番号
1055         * @param       clmNo カラムNo配列
1056         *
1057         * @return      行番号とカラムNo配列に対応した、値の配列
1058         */
1059        private String[] getTableModelData( final int row, final int[] clmNo ) {
1060                String[] values = new String[clmNo.length];
1061                for( int i = 0; i < values.length; i++ ) {
1062                        values[i] = table.getValue( row, clmNo[i] );
1063                }
1064                return values;
1065        }
1066
1067        /**
1068         * エラーメッセージの前後に処理するJSPをインクルードします。
1069         *
1070         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
1071         *
1072         * @param jsp JSP名
1073         */
1074        private void includeJsp( final String jsp ) {
1075                try {
1076                        pageContext.include( jsp, false );
1077                } catch ( IOException ex ) {
1078                        String errMsg = jsp + " の include に失敗しました。 ";
1079                        throw new HybsSystemException( errMsg,ex );
1080                } catch ( ServletException ex ) {
1081                        String errMsg = jsp + " の include に失敗しました。 ";
1082                        throw new HybsSystemException( errMsg,ex );
1083                }
1084        }
1085
1086        /**
1087         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
1088         *
1089         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
1090         *
1091         * @return      選択行の配列
1092         */
1093        @Override
1094        protected int[] getParameterRows() {
1095                final int[] rowNo ;
1096                if( selectedAll ) {
1097                        int rowCnt = table.getRowCount();
1098                        rowNo = new int[ rowCnt ];
1099                        for( int i=0; i<rowCnt; i++ ) {
1100                                rowNo[i] = i;
1101                        }
1102                } else {
1103                        rowNo = super.getParameterRows();
1104                }
1105                return rowNo ;
1106        }
1107
1108        /**
1109         * ErrMessage を管理している メソッド集約型内部クラス
1110         *
1111         * 繰返し処理部と、固定部が混在したエラーメッセージで、固定部を先に処理し、
1112         * 繰返し部は、必要時に処理するようにしました。
1113         * また、実際にエラーが発生して必要になるまで、実行遅延させます。
1114         *
1115         * @og.rev 4.2.1.0 (2008/04/11) 新規追加
1116         * @og.rev 4.3.0.0 (2008/07/24) クラス宣言をstatic化
1117         */
1118        private static final class ErrMessageManager {
1119                // 引数として初期設定される変数
1120                private String title     = null;
1121                private String from      = null;
1122                private String[] lblKeys = null;
1123                private ResourceManager resource = null;
1124                private DBTableModel    table    = null;
1125                private int[]  clmNo    = null;
1126
1127                // 内部引数として処理されたキャッシュ値
1128                private ErrorMessage errMessage  = null;
1129                private String names     = null;
1130                private String fromLbl   = null;
1131                private String[] lblVals = null;
1132
1133                private boolean isFirst  = true;                // 初期化されていない=true
1134
1135                /**
1136                 * ErrMessage のタイトルを設定します。
1137                 *
1138                 * @param       title   タイトル
1139                 */
1140                public void setTitle( final String title ) { this.title = title; }
1141
1142                /**
1143                 * 処理対象のテーブル名を設定します。
1144                 *
1145                 * @param       from    テーブル名
1146                 */
1147                public void setFrom( final String from ) { this.from = from; }
1148
1149                /**
1150                 * 処理対象のテーブルオブジェクトを設定します。
1151                 *
1152                 * @param table DBTableModelオブジェクト
1153                 */
1154                public void setDBTableModel( final DBTableModel table ) { this.table = table; }
1155
1156                /**
1157                 * ResourceManagerオブジェクトを設定します。
1158                 *
1159                 * @param resource ResourceManagerオブジェクト
1160                 */
1161                public void setResourceManager( final ResourceManager resource ) { this.resource = resource; }
1162
1163                /**
1164                 * lblParamKeys 属性の配列を設定します。
1165                 *
1166                 * @param       lblKeys 属性の配列
1167                 */
1168                public void setParamKeys( final String[] lblKeys ) { this.lblKeys = lblKeys; }
1169
1170                /**
1171                 * カラム名列を設定します。
1172                 *
1173                 * @param       clmNo   カラム名
1174                 */
1175                public void setClmNos( final int[] clmNo ) { this.clmNo = clmNo ; }
1176
1177                /**
1178                 * 初期処理を行います。
1179                 * エラー処理は、エラー時のみ実行する為、必要のない場合は、処理が不要です。
1180                 * 最初のエラー出力までは、内部オブジェクトの構築処理を行いません。
1181                 * 2回目以降は、内部変数にキャッシュされた変換値を利用して、高速化します。
1182                 *
1183                 * @og.rev 4.2.3.2 (2008/06/20) from が、null なら、なにもしない。
1184                 */
1185                private void firstExecute() {
1186                        errMessage = new ErrorMessage( title );
1187
1188                        // テーブル(from) をキーにラベルリソースから値を取得します。
1189                        // 4.2.3.2 (2008/06/20) from が、null なら、なにもしない。
1190                        if( from != null ) {
1191                                fromLbl  = resource.getLabel( from );
1192                        }
1193
1194                        // カラム番号配列から、カラム名のラベルリソース情報のCSV文字列を作成します。
1195                        names = getKeysLabel( clmNo );
1196
1197                        if( lblKeys != null && lblKeys.length > 0 ) {
1198                                int size = lblKeys.length;
1199                                lblVals = new String[size] ;
1200
1201                                for( int i=0; i<size; i++ ) {
1202                                        String key = lblKeys[i] ;
1203                                        if( key != null ) {
1204                                                if(              "@KEY".equals( key ) ) { lblVals[i] = names;   }
1205                                                else if( "@TBL".equals( key ) ) { lblVals[i] = fromLbl;}
1206                                                else if( key.startsWith( "{#" ) && key.endsWith( "}" )  ) {
1207                                                        lblVals[i] = resource.getLabel( key.substring( 2,key.length()-1 ));
1208                                                }
1209                                                else {
1210                                                        lblVals[i] = key;
1211                                                }
1212                                        }
1213                                }
1214                        }
1215                }
1216
1217                /**
1218                 * カラムNo配列(int[])に対応したカラム名のメッセージリソース文字列を返します。
1219                 *
1220                 * @param       clmNo カラムNo配列
1221                 * @return      カラムNo配列に対応した、カラム名のメッセージリソース
1222                 */
1223                private String getKeysLabel( final int[] clmNo ) {
1224                        StringBuilder buf = new StringBuilder();
1225                        if( table != null && clmNo.length > 0 ) {
1226                                String key = table.getColumnName( clmNo[0] );
1227                                buf.append( resource.getLabel( key ) );
1228                                for( int i=1; i<clmNo.length; i++ ) {
1229                                        key = table.getColumnName( clmNo[i] );
1230                                        buf.append( "," ).append( resource.getLabel( key ) );
1231                                }
1232                        }
1233
1234                        return buf.toString();
1235                }
1236
1237                /**
1238                 * カラム名列を設定します。
1239                 *
1240                 * @og.rev 4.3.5.7 (2008/03/22) エラーメッセージの行番号を実際の行番号と一致させる。
1241                 *
1242                 * @param       row     カラム名
1243                 * @param       id      カラム名
1244                 * @param       values  指定の行に対する値
1245                 */
1246                public void addMessage( final int row, final String id, final String[] values ) {
1247                        if( isFirst ) { firstExecute(); isFirst = false; }
1248
1249                        String vals = StringUtil.array2csv( values );
1250                        if( lblVals == null ) {
1251                                errMessage.addMessage( row + 1, ErrorMessage.NG, id, names, vals, fromLbl );
1252                        }
1253                        else {
1254                                int size = lblKeys.length;
1255                                String[] args = new String[size] ;
1256
1257                                for( int i=0; i<size; i++ ) {
1258                                        String key = lblVals[i] ;
1259                                        if( key != null ) {
1260                                                if(              "@VAL".equals( key ) ) { args[i] = vals; }
1261                                                else if( key.startsWith( "[" ) && key.endsWith( "]" )  ) {
1262                                                        if( table != null ) {
1263                                                                args[i] = table.getValue( row,key.substring( 1,key.length()-1 ) );
1264                                                        }
1265                                                }
1266                                                else {
1267                                                        args[i] = key;
1268                                                }
1269                                        }
1270                                }
1271                                errMessage.addMessage( row + 1, ErrorMessage.NG, id, args );
1272                        }
1273                }
1274
1275                /**
1276                 * ErrorMessageオブジェクトを返します。
1277                 *
1278                 * @return ErrorMessage オブジェクト
1279                 */
1280                public ErrorMessage getErrMessage() { return errMessage; }
1281        }
1282
1283        /**
1284         * シリアライズ用のカスタムシリアライズ書き込みメソッド
1285         *
1286         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1287         * @serialData 一部のオブジェクトは、シリアライズされません。
1288         *
1289         * @param       strm    ObjectOutputStreamオブジェクト
1290         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
1291         */
1292        private void writeObject( final ObjectOutputStream strm ) throws IOException {
1293                strm.defaultWriteObject();
1294        }
1295
1296        /**
1297         * シリアライズ用のカスタムシリアライズ読み込みメソッド
1298         *
1299         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
1300         *
1301         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1302         * @serialData 一部のオブジェクトは、シリアライズされません。
1303         *
1304         * @param       strm    ObjectInputStreamオブジェクト
1305         * @see #release2()
1306         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
1307         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
1308         */
1309        private void readObject( final ObjectInputStream strm ) throws IOException, ClassNotFoundException {
1310                strm.defaultReadObject();
1311        }
1312
1313        /**
1314         * このオブジェクトの文字列表現を返します。
1315         * 基本的にデバッグ目的に使用します。
1316         *
1317         * @return このクラスの文字列表現
1318         */
1319        @Override
1320        public String toString() {
1321                return org.opengion.fukurou.util.ToString.title(this.getClass().getName() )
1322                .println( "VERSION", VERSION )
1323                .println( "tableId", tableId )
1324                .println( "dbid", dbid )
1325                .println( "command", command )
1326                .println( "exist", exist )
1327                .println( "lbl", lbl )
1328                .println( "Other...", getAttributes().getAttribute() ).fixForm().toString();
1329        }
1330}