001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.taglib;
017
018import org.opengion.fukurou.security.HybsCryptography;
019import org.opengion.fukurou.util.HybsDateUtil;
020import static org.opengion.fukurou.util.StringUtil.nval;
021
022import java.io.IOException;
023import java.io.ObjectInputStream;
024import java.io.ObjectOutputStream;
025import java.util.Calendar;
026import java.util.Enumeration;
027import java.util.LinkedHashSet;
028import java.util.Locale;
029import java.util.ArrayList;
030import java.util.Set;
031import java.text.NumberFormat;
032
033import javax.servlet.jsp.PageContext;
034import javax.script.ScriptEngine;
035import javax.script.ScriptEngineManager;
036import javax.script.ScriptException;
037
038import org.opengion.hayabusa.common.HybsSystem;
039import org.opengion.hayabusa.common.HybsSystemException;
040import org.opengion.hayabusa.db.DBColumn;
041import org.opengion.hayabusa.db.DBTableModel;
042import org.opengion.hayabusa.db.Query;
043import org.opengion.hayabusa.db.QueryFactory;
044import org.opengion.fukurou.util.StringUtil;
045import org.opengion.fukurou.db.Transaction;
046import org.opengion.fukurou.db.TransactionReal;
047
048/**
049 * JSP上からキー、値を設定することにより、リクエスト情報として、値を
050 * 取出し可能にするタグです。
051 *
052 * 通常のリクエスト情報と同じ扱いができます(優先順位は、Valueタグが上位)。
053 *
054 * 設定した値は、{@XXXX} 形式で 取り出すことができます。
055 * また、command ="GET" で 直接画面に値を書き出すことも可能です。
056 *
057 * ※ このタグは、Transaction タグの対象です。
058 *
059 * @og.formSample
060 * ●形式:<og:value command="SET" key="ABC" value="123" />
061 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
062 *
063 * ●Tag定義:
064 *   <og:value
065 *       command            【TAG】コマンド(SET,GET,REMOVE,SQL,SETTBL,GETTBL,KEYTBL,CLEAR,SETMEM)をセットします(初期値:SET)
066 *       action             【TAG】アクション(UPPER,LOWER,MESSAGE,APPEND,ALL_APPEND,MAP,ALL_MAP,LIST,ALL_LIST,DAY_WEEK,
067 *                                  MERGE,FIRST,ROW_APPEND,REPLACE,SUBSTR,SPLIT,MAX_MIN,ALL_MAX_MIN,EXEC,CASE,MD5)をセットします
068 *       key                【TAG】リクエスト情報 に登録するキーをセットします
069 *       value              【TAG】リクエスト情報 に登録する値をセットします
070 *       defaultVal         【TAG】value値がNULLの場合に、この初期値を設定します
071 *       nullSet            【廃止】value が NULL の時に、設定するかどうか[true/false]を指定します(初期値:true)
072 *       separator          【TAG】各種アクションの文字列を連結/分解する項目区切り文字をセットします(初期値:",")
073 *       useMultiRows       【TAG】マルチデータ(複数件検索)を使用するかどうか[true/false]を指定します(初期値:false)
074 *       scope              【TAG】キャッシュする場合のスコープ(request,session)を指定します(初期値:request)
075 *       tableId            【TAG】sessionから取得する DBTableModelオブジェクトの ID
076 *       tblScope           【TAG】DBTableModel から取得する場合のスコープ(request,session)を指定します(初期値:session)
077 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
078 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
079 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
080 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
081 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true)
082 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true)
083 *       toVal              【TAG】部分文字列置換の 置換え後の部分文字列(to)を指定します
084 *       fromVal            【TAG】部分文字列置換の 置換え前の部分文字列(from)を指定します
085 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
086 *   >   ... Body ...
087 *   </og:value>
088 *
089 * ●使用例
090 *     ・ <og:value command="SET" key="ABC" value="123" />
091 *     ・ <og:value command="SQL">SELECT 1 TEST FROM DUAL</og:value>
092 *     ・ <og:value command="SET" key="DEF" value="{@NOCOMMAND}" defaultVal="0000" />
093 *     ・ <og:value command="GET" key="NOKEY" defaultVal="NODATA" />
094 *     ・ <og:value command="SET" key="{@ABC}4" value="TEST1234" />
095 *     ・ <og:value command="GET" key="ABC" />
096 *     ・ <og:value command="SET" action="LOWER" key="LOWERTEST" value="ABCDEF" />
097 *     ・ <og:value command="GET" key="LOWERTEST" />
098 *     ・ <og:value command="GET" action="UPPER" key="LOWERTEST" />
099 *     ・ <og:value command="REMOVE" key="ABC" />
100 *
101 * <style type="text/css">
102 *   #valueJavaDoc th { text-align:center; vertical-align: middle; writing-mode: tb-rl; }
103 *   #valueJavaDoc td { text-align:center; }
104 * </style>
105 *
106 * <table border="1" frame="box" rules="all" id="valueJavaDoc">
107 *   <caption>command 一覧と使用可能 action の対応表</caption>
108 *   <tr><th>command</th><th>UPPER</th><th>LOWER</th><th>MESSAGE</th><th>APPEND</th><th>ALL_APPEND</th><th>MAP</th><th>ALL_MAP</th><th>LIST</th><th>ALL_LIST</th>
109 *       <th>DAY_WEEK  </th><th>MERGE</th><th>FIRST</th><th>ROW_APPEND</th><th>REPLACE</th><th>SUBSTR</th><th>SPLIT</th><th>MAX_MIN</th><th>ALL_MAX_MIN</th></tr>
110 *   <tr><td>SET    </td><td>○</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
111 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td></tr>
112 *   <tr><td>GET    </td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
113 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
114 *   <tr><td>REMOVE </td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
115 *       <td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
116 *   <tr><td>CLEAR  </td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
117 *       <td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
118 *   <tr><td>SQL    </td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>○</td>
119 *       <td>×</td><td>×</td><td>×</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
120 *   <tr><td>SETTBL </td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td>
121 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td></tr>
122 *   <tr><td>GETTBL </td><td>○</td><td>○</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td>
123 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
124 *   <tr><td>KEYTBL </td><td>○</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
125 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
126 *   <tr><td>SETMEM </td><td>○</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
127 *       <td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td><td>○</td><td>×</td><td>×</td><td>○</td><td>○</td></tr>
128 *   <tr><td>SQLGET </td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td>
129 *       <td>×</td><td>×</td><td>×</td><td>○</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td><td>×</td></tr>
130 * </table>
131 *
132 * @og.group その他部品
133 *
134 * @version  4.0
135 * @author   M.Endou
136 * @since    JDK5.0,
137 */
138public class ValueTag extends CommonTagSupport {
139        //* このプログラムのVERSION文字列を設定します。   {@value} */
140        private static final String VERSION = "5.7.7.2 (2014/06/20)" ;
141
142        private static final long serialVersionUID = 577220140620L ;
143
144        /** command 引数に渡す事の出来る コマンド  セット {@value} */
145        public static final String CMD_SET              = "SET";
146        /** command 引数に渡す事の出来る コマンド  ゲット {@value} */
147        public static final String CMD_GET              = "GET";
148        /** command 引数に渡す事の出来る コマンド  リムーブ {@value} */
149        public static final String CMD_REMOVE   = "REMOVE";
150        /** command 引数に渡す事の出来る コマンド  クリア {@value} */
151        public static final String CMD_CLEAR    = "CLEAR";
152        /** command 引数に渡す事の出来る コマンド  SQL {@value} */
153        public static final String CMD_SQL              = "SQL";
154        /** command 引数に渡す事の出来る コマンド  セットテーブル {@value} */
155        public static final String CMD_SETTBL   = "SETTBL";
156        /** command 引数に渡す事の出来る コマンド  ゲットテーブル {@value} */
157        public static final String CMD_GETTBL   = "GETTBL";
158        /** command 引数に渡す事の出来る コマンド  キーテーブル {@value} */
159        public static final String CMD_KEYTBL   = "KEYTBL";
160        /** command 引数に渡す事の出来る コマンド  セットメモリ {@value} */
161        public static final String CMD_SETMEM   = "SETMEM";                     // 3.7.1.0 (2005/04/15)
162        /** command 引数に渡す事の出来る コマンド  SQLゲット {@value} */
163        public static final String CMD_SQLGET   = "SQLGET";                     // 5.1.7.0 (2010/06/01) SQLGET対応
164
165        /** command 引数に渡す事の出来る コマンド リスト  */
166        private static final String[] COMMAND_LIST = new String[] {
167                        CMD_SET , CMD_GET , CMD_REMOVE , CMD_SQL , CMD_SETTBL , CMD_GETTBL ,
168                        CMD_KEYTBL , CMD_CLEAR , CMD_SETMEM, CMD_SQLGET };
169
170        /** action 引数に渡す事の出来る アクション  アッパー(大文字化) {@value} */
171        public static final String ACT_UPPER            = "UPPER" ;
172        /** action 引数に渡す事の出来る アクション  ローワー(小文字化) {@value} */
173        public static final String ACT_LOWER            = "LOWER" ;
174        /** action 引数に渡す事の出来る アクション  メッセージ変換 {@value} */
175        public static final String ACT_MESSAGE          = "MESSAGE" ;
176        /** action 引数に渡す事の出来る アクション  データアペンド {@value} */
177        public static final String ACT_APPEND           = "APPEND" ;
178        /** action 引数に渡す事の出来る アクション  オールアペンド {@value} */
179        public static final String ACT_ALL_APPEND       = "ALL_APPEND" ;                                // 3.6.1.0 (2005/01/05)
180        /** action 引数に渡す事の出来る アクション  MAP {@value} */
181        public static final String ACT_MAP                      = "MAP" ;                                               // 5.5.0.3 (2012/03/12)
182        /** action 引数に渡す事の出来る アクション  ALL_MAP {@value} */
183        public static final String ACT_ALL_MAP          = "ALL_MAP" ;                                   // 5.5.0.3 (2012/03/12)
184        /** action 引数に渡す事の出来る アクション  LIST {@value} */
185        public static final String ACT_LIST                     = "LIST" ;                                              // 4.3.7.5 (2009/07/13)
186        /** action 引数に渡す事の出来る アクション  ALL_LIST {@value} */
187        public static final String ACT_ALL_LIST         = "ALL_LIST" ;                                  // 4.3.7.5 (2009/07/13)
188        /** action 引数に渡す事の出来る アクション  日付前方まるめ {@value} */
189        public static final String ACT_DAY_WEEK         = "DAY_WEEK" ;                                  // 3.7.1.0 (2005/04/15)
190        /** action 引数に渡す事の出来る アクション  マージ {@value} */
191        public static final String ACT_MERGE            = "MERGE" ;                                             // 3.7.1.1 (2005/05/23)
192        /** action 引数に渡す事の出来る アクション  ファースト {@value} */
193        public static final String ACT_FIRST            = "FIRST" ;                                             // 3.8.0.4 (2005/08/08)
194        /** action 引数に渡す事の出来る アクション  縦横回転 {@value} */
195        public static final String ACT_ROW_APPEND       = "ROW_APPEND" ;                                // 3.8.9.2 (2007/07/28)
196        /** action 引数に渡す事の出来る アクション  文字列置換 {@value} */
197        public static final String ACT_REPLACE          = "REPLACE" ;                                   // 5.2.2.0 (2010/11/01)
198        /** action 引数に渡す事の出来る アクション  部分文字列 {@value} */
199        public static final String ACT_SUBSTR           = "SUBSTR" ;                                    // 5.2.2.0 (2010/11/01)
200        /** action 引数に渡す事の出来る アクション  文字列分割 {@value} */
201        public static final String ACT_SPLIT            = "SPLIT" ;                                             // 5.2.2.0 (2010/11/01)
202        /** action 引数に渡す事の出来る アクション  最大_最小値 {@value} */
203        public static final String ACT_MAX_MIN          = "MAX_MIN" ;                                   // 5.6.4.3 (2013/05/24)
204        /** action 引数に渡す事の出来る アクション  ALL_最大_最小値 {@value} */
205        public static final String ACT_ALL_MAX_MIN      = "ALL_MAX_MIN" ;                               // 5.6.4.3 (2013/05/24)
206        /** action 引数に渡す事の出来る アクション  計算処理結果 {@value} */
207        public static final String ACT_EXEC                     = "EXEC" ;                                              // 5.7.7.2 (2014/06/20)
208        /** action 引数に渡す事の出来る アクション  条件分岐 {@value} */
209        public static final String ACT_CASE                     = "CASE" ;                                              // 5.7.7.2 (2014/06/20)
210        /** action 引数に渡す事の出来る アクション  MD5 {@value} */
211        public static final String ACT_MD5              = "MD5" ;                                                       // 5.9.6.3 (2016/03/18)
212
213        /** action 引数に渡す事の出来る アクション リスト  */
214        private static final String[] ACTION_LIST = new String[] {
215                ACT_UPPER , ACT_LOWER , ACT_MESSAGE , ACT_APPEND , ACT_ALL_APPEND , ACT_MAP , ACT_ALL_MAP , ACT_LIST, ACT_ALL_LIST ,
216                ACT_DAY_WEEK , ACT_MERGE , ACT_FIRST , ACT_ROW_APPEND , ACT_REPLACE , ACT_SUBSTR , ACT_SPLIT , ACT_MAX_MIN , ACT_ALL_MAX_MIN , 
217                ACT_EXEC , ACT_CASE, ACT_MD5
218        };
219
220        private String                  tableId         = HybsSystem.TBL_MDL_KEY;
221        private String                  command         = CMD_SET;
222        private String                  key                     = null;
223        private String                  inValue         = null;         // 3.5.4.0 (2003/11/25)
224        private String                  value           = null;
225        private String                  defaultVal      = null;
226        private String                  action          = null;
227        private transient DBTableModel  table           = null;
228        // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
229        private String                  dbid            = null;
230        private String                  scope           = "request";    // "request","session"
231        private String                  tblScope        = "session";    // 5.1.2.0 (2010/01/01) DBTableModel の取得先のscope
232        private String                  separator       = ",";   // 項目区切り文字
233        // 3.2.4.0 (2003/06/12) マルチデータ(複数件検索)を使用するかしないか。
234        private boolean                 useMultiRows    = false;        // 初期値:使用せず
235
236        private boolean                 xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.1.7.0 (2010/06/01) XSS対策
237
238        private String  fromVal         = null;         // 5.2.2.0 (2010/11/01)
239        private String  toVal           = null;         // 5.2.2.0 (2010/11/01)
240
241        private boolean tmpSelectedAll  = false;        // 5.6.4.3 (2013/05/24) action="ALL_xxx"を tmpSelectedAll="true" で内部処理します。
242
243        /**
244         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
245         *
246         * @og.rev 3.1.7.0 (2003/05/02) isNullSet 属性が true(初期値)のときは、リクエスト情報から値を取得。
247         * @og.rev 3.1.7.0 (2003/05/02) scope 属性を設定するタイミングを、早くする。
248         * @og.rev 3.5.4.0 (2003/11/25) getRequestParameter( value ) メソッドを setValue に移動。
249         * @og.rev 5.1.7.0 (2010/06/01) SQLGET対応
250         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
251         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
252         *
253         * @return      後続処理の指示
254         */
255        @Override
256        public int doStartTag() {
257                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
258                if( useTag() ) {
259                        super.setScope( scope );                // デフォルトscope が "request" なので、再設定している。
260
261        //              if( isNullSet ) {
262        //                      setUseValue( false );
263        //              }
264
265                        // 5.1.7.0 (2010/06/01) SQLGET対応
266                        if( CMD_SQL.equals( command ) || CMD_SET.equals( command ) || CMD_SQLGET.equals( command ) ) {
267                                return EVAL_BODY_BUFFERED ;             // Body を評価する
268                        }
269                }
270                return SKIP_BODY ;                              // Body を評価しない
271        }
272
273        /**
274         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
275         *
276         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
277         * @og.rev 3.6.0.8 (2004/11/19) エラー発生時に確実にリリースされるように try finally 追加
278         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
279         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
280         * @og.rev 5.1.7.0 (2010/06/01) SQLGET対応
281         * @og.rev 5.1.7.0 (2010/06/01) XSS解除対応
282         * @og.rev 5.1.9.0 (2010/08/01) TransactionTag 対応。上位に TransactionTag があれば、そこからConnection をもらう。
283         * @og.rev 5.2.1.0 (2010/10/01) command="SET" action="APPEND"でvalueをbody部に書いた場合に動作しないバグを修正
284         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
285         * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
286         *
287         * @return      後続処理の指示(SKIP_BODY)
288         */
289        @Override
290        public int doAfterBody() {
291                if( value == null || value.length() <= 0 ) {
292                        // 5.1.7.0 (2010/06/01) XSS対策
293                        useXssCheck( xssCheck );
294
295                        value = getBodyString();
296                        // 5.2.1.0 (2010/10/01)
297                        inValue = getBodyRawString();
298
299                        // 5.1.7.0 (2010/06/01) SQLGET対応
300                        if( CMD_SQL.equals( command ) || CMD_SQLGET.equals( command ) ) {
301                                Query query = QueryFactory.newInstance();               // 4.0.0 (2005/01/31)
302                                Transaction tran = null;
303                                try {
304                                        value = value.trim();
305
306                                        // 5.1.9.0 (2010/08/01) TransactionTag 対応
307                                        TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class );
308                                        if( tranTag == null ) {
309                                                tran = new TransactionReal( getApplicationInfo() );             // 5.3.7.0 (2011/07/01) 引数変更
310                                        }
311                                        else {
312                                                tran = tranTag.getTransaction();
313                                        }
314                                        query.setTransaction( dbid,tran );      // 5.1.9.0 (2010/08/01) TransactionTag 対応
315
316                                        query.setResourceManager( getResource() );      // 4.0.0 (2005/01/31)
317
318                                        query.setStatement( value );
319                                        query.execute();
320
321                                        table = query.getDBTableModel();
322                                }
323                                finally {
324                                        QueryFactory.close( query );
325                                        if( tran != null ) {
326                                                tran.close(); // 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
327                                        }               
328                                }
329                        }
330                }
331
332                return SKIP_BODY ;
333        }
334
335        /**
336         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
337         *
338         * @og.rev 3.1.0.1 (2003/03/26) DBTableModelの値をSET/GETできる command , action を追加。
339         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
340         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
341         * @og.rev 3.1.5.0 (2003/04/22) DBTableModel が存在するときのみ実行するロジックになっていたバグ対応。
342         * @og.rev 5.1.2.0 (2010/01/01) DBTableModel の取得先の tblScope を追加。
343         * @og.rev 5.1.7.0 (2010/06/01) SQLGET対応
344         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
345         *
346         * @return      後続処理の指示
347         */
348        @Override
349        public int doEndTag() {
350                debugPrint();           // 4.0.0 (2005/02/28)
351                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
352                if( useTag() ) {
353                        if( check( command, COMMAND_LIST ) ) {
354                                if( CMD_SETTBL.equals( command ) ||
355                                        CMD_GETTBL.equals( command ) ||
356                                        CMD_KEYTBL.equals( command ) ) {
357        //                                      table = (DBTableModel)getSessionAttribute( tableId );
358                                                // 5.1.2.0 (2010/01/01) DBTableModel の取得先の tblScope を追加。
359                                                if( "session".equals( tblScope ) ) { table = (DBTableModel) getSessionAttribute( tableId ); }
360                                                else if( "request".equals( tblScope ) ) { table = (DBTableModel) getRequestAttribute( tableId ); }
361                                                else {
362                                                        String errMsg = "このスコープはサポートされていません。[" + tblScope + "]";
363                                                        throw new IllegalArgumentException( errMsg );
364                                                }
365                                }
366                        }
367
368                        commandExec( command );
369
370                        // 5.1.7.0 (2010/06/01) SQLGET対応
371                        if( CMD_GET.equals( command ) || CMD_GETTBL.equals( command ) || CMD_SQLGET.equals( command ) ) {
372                                if( value != null ) { jspPrint( value ); }
373                        }
374                }
375                return EVAL_PAGE ;
376        }
377
378        /**
379         * タグリブオブジェクトをリリースします。
380         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
381         *
382         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
383         * @og.rev 3.1.0.1 (2003/03/26) DBTableModelの値をSET/GETできる command , action を追加。
384         * @og.rev 3.1.0.1 (2003/03/26) query 属性を削除します。
385         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
386         * @og.rev 3.2.4.0 (2003/06/12) マルチデータ(複数件検索)を使用するかしないか。
387         * @og.rev 3.5.4.0 (2003/11/25) inValue 変数の追加
388         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
389         * @og.rev 5.1.2.0 (2010/01/01) DBTableModel の取得先の tblScope を追加。
390         * @og.rev 5.1.7.0 (2010/06/01) XSS解除対応
391         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
392         * @og.rev 5.2.2.0 (2010/11/01) fromVal , toVal 属性 追加
393         * @og.rev 5.6.4.3 (2013/05/24) parameter 属性は、未使用なので削除
394         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加。action="ALL_xxx"を tmpSelectedAll="true" に置き換えます。
395         *
396         */
397        @Override
398        protected void release2() {
399                super.release2();
400                tableId         = HybsSystem.TBL_MDL_KEY;
401                command         = CMD_SET;
402                key                     = null;
403                value           = null;
404                defaultVal      = null;
405                action          = null;
406                table           = null;
407                dbid            = null;
408                scope           = "request";    // "request","session"
409                tblScope        = "session";    // 5.1.2.0 (2010/01/01) DBTableModel の取得先のscope
410                separator       = ",";
411                useMultiRows = false;
412                tmpSelectedAll  = false;        // 5.6.4.3 (2013/05/24)
413                inValue         = null;                 // 3.5.4.0 (2003/11/25)
414                xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );        // 5.1.7.0 (2010/06/01) XSS解除対応
415                fromVal         = null;                 // 5.2.2.0 (2010/11/01)
416                toVal           = null;                 // 5.2.2.0 (2010/11/01)
417        }
418
419        /**
420         * コマンドを実行します。
421         *
422         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
423         * フィールド定数値のいづれかを、指定できます。
424         * コマンドを登録すると同時に,実行も行ないます。
425         *
426         * @og.rev 3.1.0.1 (2003/03/26) command に、SETTBL / GETTBL / KEYTBL / CLEAR を追加。
427         * @og.rev 3.1.0.1 (2003/03/26) query 属性を削除します。
428         * @og.rev 3.1.7.0 (2003/05/02) scope 属性を設定するタイミングを、早くする。
429         * @og.rev 3.7.1.0 (2005/04/15) command に、SETMEM を追加。
430         * @og.rev 5.1.7.0 (2010/06/01) SQLGET対応
431         *
432         * @param       command コマンド(public static final 宣言されている文字列)
433         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ValueTag.CMD_GET">コマンド定数</a>
434         */
435        private void commandExec( final String command ) {
436
437                if( CMD_SQL.equals( command ) ) {
438                        setSQLAttribute( table );
439                }
440                else if( CMD_SQLGET.equals( command ) ) {
441                        value = getSQLAttribute( table );
442                }
443                else if( CMD_SET.equals( command ) ) {
444                        value = nval( value, defaultVal );
445                        setAttribute( key,value,action );
446                }
447                else if( CMD_GET.equals( command ) ) {
448                        value = getAttribute( key,action );
449                }
450                else if( CMD_REMOVE.equals( command ) ) {
451                        removeAttribute( key );
452                }
453                else if( CMD_CLEAR.equals( command ) ) {
454                        clearAttribute( key );
455                }
456                else if( CMD_SETTBL.equals( command ) ) {
457                        setTableAttribute( table,key,action );
458                }
459                else if( CMD_GETTBL.equals( command ) ) {
460                        value = getTableAttribute( table,key,action );
461                }
462                else if( CMD_KEYTBL.equals( command ) ) {
463                        setKeyTableAttribute( table,key,value,action );
464                }
465                else if( CMD_SETMEM.equals( command ) ) {               // 3.7.1.0 (2005/04/15)
466                        value = nval( value, defaultVal );
467                        setAttribute( key,value,action );
468                        setRequestCacheData( key,(String)getObject( key ) );
469                }
470        }
471
472        /**
473         * アクションを実行します。
474         *
475         * コマンドは action 属性で指定します。
476         * action コマンド が、 null の場合は、なにも実行しません。
477         *
478         * @og.rev 3.0.1.3 (2003/03/11) MESSAGE action を追加
479         * @og.rev 3.1.0.1 (2003/03/26) 引数を与えて処理する様に変更する。
480         * @og.rev 3.7.1.0 (2005/04/15) action に、DAY_WEEK を追加。
481         * @og.rev 3.7.1.1 (2005/05/23) action に、MERGE を追加。
482         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
483         * @og.rev 5.2.2.0 (2010/11/01) ACT_MERGE 時には、カンマで分解、separator で合成を行います。
484         * @og.rev 5.2.2.0 (2010/11/01) ACT_REPLACE 処理を新規追加します。
485         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
486         * @og.rev 5.6.6.1 (2013/07/12) value が null の場合は、無視します。
487         * @og.rev 5.7.7.2 (2014/06/20) EXEC と CASE アクションを追加
488         * @og.rev 5.9.6.3 (2016/02/18) MD5追加
489         *
490         * @param action        コマンド(public static final 宣言されている文字列)
491         * @param value         旧の値
492         *
493         * @return      処理後の値
494         */
495        private String actionExec( final String action,final String value ) {
496                String rtn = value;
497
498                // 5.6.6.1 (2013/07/12) value が null の場合は、無視します。
499                if( action == null || value == null ) { return rtn; }
500
501                if( ACT_UPPER.equals( action ) ) {
502                        // Localeを共通管理するようになった場合、String.toUpperCase( Locale locale )使用の事
503                        rtn = value.toUpperCase(Locale.JAPAN);
504                }
505                else if( ACT_LOWER.equals( action ) ) {
506                        // Localeを共通管理するようになった場合、String.toLowerCase( Locale locale )使用の事
507                        rtn = value.toLowerCase(Locale.JAPAN);
508                }
509                else if( ACT_MESSAGE.equals( action ) ) {
510                        // 引数をメッセージリソースのキーとして、メッセージ変換する。
511                        rtn = getResource().getLabel( value );
512                }
513                else if( ACT_DAY_WEEK.equals( action ) ) {
514                        // 日付型文字列(YYYYMMDD) の入力データを、開始日を月曜日にセットします。
515                        // SUNDAY=1 , MONDAY=2 になります。月曜日との差だけ、前に戻します。
516                        // 指定日が日曜日の場合は、次の日(月曜日)に進めます。
517                        Calendar ymd = HybsSystem.getCalendar( value );
518                        int shu = ymd.get( Calendar.DAY_OF_WEEK ) - Calendar.MONDAY ;
519
520                        if( shu != 0 ) { ymd.add( Calendar.DATE, -shu ); }
521
522                        rtn = HybsDateUtil.getDate( ymd.getTimeInMillis() , "yyyyMMdd" );               // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
523                }
524                // 3.7.1.1 (2005/05/23)
525                else if( ACT_MERGE.equals( action ) ) {
526                        // 引数をカンマで文字列配列に分解します。
527                        String[] str = StringUtil.csv2Array( value );
528                        Set<String> set = new LinkedHashSet<String>();
529                        for( int i=0; i<str.length; i++ ) {
530                                if( str[i] != null && str[i].length() > 0 ) {
531                                        set.add( str[i] );
532                                }
533                        }
534
535                        // 分解後、マージ(Setで)されます。 登録順は、キープします。
536                        rtn = StringUtil.iterator2line( set.iterator(),separator );     // 5.2.2.0 (2010/11/01) separator 使用
537                }
538                // 5.2.2.0 (2010/11/01) ACT_REPLACE 処理を新規追加
539                else if( ACT_REPLACE.equals( action ) ) {
540                        // value.replaceAll( from, to ) という文法で処理します。
541                        if( value != null && fromVal != null && toVal != null ) {
542                                rtn = value.replaceAll( fromVal, toVal );
543                        }
544                }
545                // 5.2.2.0 (2010/11/01) SUBSTR 処理を新規追加
546                else if( ACT_SUBSTR.equals( action ) ) {
547                        // value.substring( from, to ) という文法で処理します。
548                        if( value != null) {
549                                int from = (fromVal==null||fromVal.length()==0) ? 0              : Integer.parseInt( fromVal );
550                                int to   = (  toVal==null||  toVal.length()==0) ? value.length() : Integer.parseInt( toVal );
551
552                                rtn = value.substring( from, to );
553                        }
554                }
555                // 5.7.7.2 (2014/06/20) CASE 処理を新規追加
556                else if( ACT_CASE.equals( action ) ) {
557                        // fromVal="A:1 B:2 C:3 D:4" 形式
558                        if( fromVal != null && fromVal.length()>0 ) {
559                                String[] keys = StringUtil.csv2Array( fromVal , ' ' );
560                                for( int i=0; i<keys.length; i++ ) {
561                                        int idx = keys[i].indexOf( ':' );
562                                        if( idx >= 0 ) {                                                             // 分解した値にコロン(:)がなければ、パス
563                                                String key = keys[i].substring( 0,idx );        // 左辺(キー)
564                                                if( value.equalsIgnoreCase( key ) ) {
565                                                        rtn = keys[i].substring( idx+1 );               // 右辺(値)
566                                                        break;
567                                                }
568                                        }
569                                }
570                        }
571                }
572                // 5.7.7.2 (2014/06/20) EXEC 処理を新規追加
573                else if( ACT_EXEC.equals( action ) ) {
574                        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName( "JavaScript" );
575                        try {
576                                Object obj = jsEngine.eval( value );
577                                rtn = String.valueOf( obj );
578                        }
579                        catch( ScriptException ex ) {
580                                String errMsg = "JavaScript式のパースに失敗しました。[" + value + "]";
581                                throw new HybsSystemException( errMsg , ex );
582                        }
583                }
584                // 5.9.6.3 (2016/02/18)
585                else if( ACT_MD5.equals(  action ) ){
586                        rtn = HybsCryptography.getMD5( value );
587                }
588
589                return rtn;
590        }
591
592        /**
593         * 指定のスコープの内部キャッシュ情報を、キーで登録します。
594         *
595         * @og.rev 3.1.0.1 (2003/03/26) 引数を与えて処理する様に変更する。
596         * @og.rev 3.5.4.0 (2003/11/25) APPENDアクションを有効にします。
597         * @og.rev 3.5.6.5 (2004/08/09) APPEND時のセパレータを外部指定の変数を使用
598         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
599         * @og.rev 5.2.2.0 (2010/11/01) ACT_SPLIT 追加
600         * @og.rev 5.6.4.3 (2013/05/24) ACT_MAX_MIN アクションの追加
601         * @og.rev 5.6.6.1 (2013/07/12) value が null の場合は、無視します。
602         *
603         * @param key           キー
604         * @param value         値
605         * @param action        アクション
606         */
607        private void setAttribute( final String key,final String value,final String action ) {
608                if( key == null || key.length() == 0 ) {
609                        String errMsg = "key がセットされていません。"
610                                                + " command=" + command + " , action=" + action
611                                                + " , value=" + value ;                 // 5.1.8.0 (2010/07/01) errMsg 修正
612                        throw new HybsSystemException( errMsg );
613                }
614
615                // 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
616                // 5.6.6.1 (2013/07/12) value が null の場合は、無視します。
617                if( value != null ) {
618                        if( ACT_APPEND.equals( action ) ) {
619                                String[] array = getRequestParameterValues( inValue );
620                                setObject( key, StringUtil.array2line( array,separator ) );
621                        }
622                        // 5.2.2.0 (2010/11/01) ACT_SPLIT 追加
623                        else if( ACT_SPLIT.equals( action ) )  {
624                                String[] array = value.split( separator );
625                                setObject( key , array[0] );            // キー自体には、分割時の先頭の文字列を設定しておく。
626                                for( int i=0; i<array.length; i++ ) {
627                                        setObject( key + i , array[i] );
628                                }
629                        }
630                        // 5.6.4.3 (2013/05/24) ACT_MAX_MIN アクションの追加
631                        else if( ACT_MAX_MIN.equals( action ) )  {
632                                String[] array = value.split( separator );
633
634                                // command="SET" では、数字型としてのみ処理します。
635                                double minNum = Double.MAX_VALUE ;
636                                double maxNum = Double.MIN_VALUE ;
637                                double sumNum = 0d ;
638                                int    cntSum = 0;              // 平均計算に有効な件数
639
640                                for( int i=0; i<array.length; i++ ) {
641                                        String val = array[i].trim().replaceAll( ",","" );              // 数字型フォーマットのカンマを取り除く
642                                        if( val.isEmpty() ) { continue; }               // ゼロ文字列の場合は、取り直し
643
644                                        double tmp = Double.parseDouble( val );
645                                        if( minNum > tmp ) { minNum = tmp; }
646                                        if( maxNum < tmp ) { maxNum = tmp; }
647                                        sumNum += tmp ;  cntSum++ ;
648                                }
649
650                                // command="SET" の場合は、数字型の場合のみ使用します。
651                                if( cntSum > 0 ) {
652                                        NumberFormat nf = NumberFormat.getInstance();
653                                        nf.setGroupingUsed( false );                                    // カンマ編集なし
654                                        nf.setMaximumFractionDigits(2);                                 // 最大小数部は2桁
655                                        nf.setMinimumFractionDigits(0);                                 // できれば、整数表示
656
657                                        setObject( "MIN." + key,nf.format( minNum ) );          // Double.toString( minNum ) の代わり。
658                                        setObject( "MAX." + key,nf.format( maxNum ) );
659                                        setObject( "SUM." + key,nf.format( sumNum ) );
660                                        setObject( "AVG." + key,nf.format( sumNum/cntSum ) );
661                                }
662                                else {
663                                        setObject( "MIN." + key,nval( defaultVal , "" ) );
664                                        setObject( "MAX." + key,nval( defaultVal , "" ) );
665                                        setObject( "SUM." + key,nval( defaultVal , "" ) );
666                                        setObject( "AVG." + key,nval( defaultVal , "" ) );
667                                }
668                        }
669                        else {
670                                setObject( key, actionExec( action,value ) );
671                        }
672                }
673                else {
674                        setObject( key, null );                 // 5.6.6.1 (2013/07/12) value が null の場合
675                }
676        }
677
678        /**
679         * 指定のスコープの内部キャッシュ情報を、キーで取得します。
680         *
681         * @og.rev 3.1.0.1 (2003/03/26) 引数を与えて処理する様に変更する。
682         *
683         * @param key           キー
684         * @param action        アクション
685         *
686         * @return      キーに対する内部キャッシュ情報
687         */
688        private String getAttribute( final String key,final String action ) {
689                if( key == null || key.length() == 0 ) {
690                        String errMsg = "key がセットされていません。"
691                                                + " command=" + command + " , action=" + action;        // 5.1.8.0 (2010/07/01) errMsg 修正
692                        throw new HybsSystemException( errMsg );
693                }
694
695                String rtn = defaultVal;
696                Object obj = pageContext.findAttribute( key );
697                if( obj != null ) { rtn = obj.toString(); }
698
699                return actionExec( action,rtn );
700        }
701
702        /**
703         * 指定のスコープの内部キャッシュ情報を削除します。
704         *
705         * @og.rev 3.1.0.1 (2003/03/26) 引数を与えて処理する様に変更する。
706         *
707         * @param key           キー
708         */
709        private void removeAttribute( final String key ) {
710                if( key == null || key.length() == 0 ) {
711                        String errMsg = "key がセットされていません。"
712                                                + " command=" + command ;                       // 5.1.8.0 (2010/07/01) errMsg 修正
713                        throw new HybsSystemException( errMsg );
714                }
715                removeObject( key );
716        }
717
718        /**
719         * セッション/アプリケーションスコープのキャッシュ情報をクリアします。
720         *
721         * このクリアは、キーの前方一致で、大文字小文字の区別をせずにクリアします。
722         * また、キーが null の場合は、"X_" で始めるもの以外のすべての値をクリアします。
723         * また、Webエンジン内部で使用しているキーは、ここではクリアできません。
724         *
725         * @og.rev 3.1.0.1 (2003/03/26) クリアコマンドの追加。
726         * @og.rev 4.3.4.0 (2008/12/01) PageContextのスコープをクラス変数としてアクセス
727         *
728         * @param key           キー
729         */
730        private void clearAttribute( final String key ) {
731
732                String lowKey = null;
733                if( key != null ) { lowKey = key.toLowerCase(Locale.JAPAN); }
734
735                Enumeration<String> ekeys = pageContext.getAttributeNamesInScope( PageContext.APPLICATION_SCOPE );                // 4.3.3.6 (2008/11/15) Generics警告対応
736                while ( ekeys.hasMoreElements() ) {
737                        String ekey = ekeys.nextElement().toLowerCase(Locale.JAPAN);            // 4.3.3.6 (2008/11/15) Generics警告対応
738                        if( ( ! ekey.startsWith( "h_") && ! ekey.startsWith( "x_") ) &&
739                                (  lowKey == null || ekey.startsWith( key ) ) ) {
740                                        pageContext.removeAttribute( ekey, PageContext.APPLICATION_SCOPE ) ;
741                        }
742                }
743
744                ekeys = pageContext.getAttributeNamesInScope( PageContext.SESSION_SCOPE );
745                while ( ekeys.hasMoreElements() ) {
746                        String ekey = String.valueOf( ekeys.nextElement() ).toLowerCase(Locale.JAPAN);
747                        if( ( ! ekey.startsWith( "h_") && ! ekey.startsWith( "x_") ) &&
748                                (  lowKey == null || ekey.startsWith( key ) ) ) {
749                                        pageContext.removeAttribute( ekey, PageContext.SESSION_SCOPE ) ;
750                        }
751                }
752        }
753
754        /**
755         * 指定のスコープの内部キャッシュ情報を、指定のSQL文より作成します。
756         *
757         * @og.rev 3.1.0.1 (2003/03/26) 引数を与えて処理する様に変更する。
758         * @og.rev 3.2.4.0 (2003/06/12) マルチデータ(複数件検索)を使用するかしないか。
759         * @og.rev 3.8.6.0 (2006/08/07) nullSet="true"(初期値)の時は、検索結果がゼロ件時に "" をセットする。
760         * @og.rev 3.8.9.2 (2007/07/28) action="ROW_APPEND" 追加
761         * @og.rev 4.3.7.5 (2009/07/13) ACT_LIST、ACT_ALL_LIST アクションの追加
762         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
763         * @og.rev 5.5.0.3 (2012/03/12) ACT_MAP アクションの追加
764         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加。action="ALL_xxx"を tmpSelectedAll="true" に置き換えます。
765         *
766         * @param table DBTableModelオブジェクト
767         */
768        private void setSQLAttribute( final DBTableModel table ) {
769                if( table == null ) {           // 3.8.6.0 (2006/08/07)
770                        return;
771                }
772
773                int clmCnt = table.getColumnCount();
774                int rowCnt = table.getRowCount();
775                String sqlkey ;
776                String sqlval ;
777                String sufix = "";
778
779                if( ACT_ROW_APPEND.equals( action ) ) {
780                        for( int clm = 0; clm < clmCnt; clm++ ) {
781                                StringBuilder buf = new StringBuilder();
782                                for( int row=0; row<rowCnt; row++ ) {
783                                        sqlval = table.getValue( row, clm );
784                                        if( row > 0 ) { buf.append( separator ); }
785                                        buf.append( sqlval );
786                                }
787                                sqlkey = table.getColumnName( clm );
788                                setObject( sqlkey , buf.toString() );
789                        }
790                }
791                // 4.3.7.5 (2009/07/13) ACT_LIST、ACT_ALL_LIST アクションの追加
792                else if( ACT_LIST.equals( action ) ) {
793                        for( int clm = 0; clm < clmCnt; clm++ ) {
794                                ArrayList<String> list = new ArrayList<String>();
795                                for( int row=0; row<rowCnt; row++ ) {
796                                        sqlval = table.getValue( row, clm );
797                                        list.add( sqlval );
798                                }
799                                sqlkey = table.getColumnName( clm );
800                                setObject( sqlkey , list );
801                        }
802                }
803                // 5.5.0.3 (2012/03/12) ACT_MAP アクションの追加
804                else if( ACT_MAP.equals( action )  ) {
805                        if( clmCnt < 2 ) {
806                                String errMsg = "action=MAP 時には、カラムは、2つ以上必要です。カラム数=[" + clmCnt + "]";
807                                throw new IllegalArgumentException( errMsg );
808                        }
809                        for( int row=0; row<rowCnt; row++ ) {
810                                sqlkey = table.getValue( row, 0 );                      // 0番目カラムがキー
811                                sqlval = table.getValue( row, 1 );                      // 1番目カラムが値
812                                setObject( sqlkey , sqlval );
813                        }
814                }
815                else {
816                        // 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
817                        if( rowCnt == 0 ) {
818                                if( useMultiRows ) { sufix = "0" ; }
819                                for( int clm = 0; clm < clmCnt; clm++ ) {
820                                        sqlkey = table.getColumnName( clm );
821                                        sqlval = "";
822                                        setObject( sqlkey + sufix, sqlval );
823                                }
824                        }
825                        else {
826                                for( int row=0; row<rowCnt; row++ ) {
827                                        if( useMultiRows ) { sufix = String.valueOf( row ) ; }
828                                        for( int clm = 0; clm < clmCnt; clm++ ) {
829                                                sqlkey = table.getColumnName( clm );
830                                                sqlval = table.getValue( row, clm );
831                                                setObject( sqlkey + sufix, sqlval );
832                                        }
833                                        if( ! useMultiRows ) { break; }
834                                }
835                        }
836                }
837        }
838
839        /**
840         * 指定のSQL文の結果を文字列として画面に出力します。
841         * 画面に出力される項目は、1項目だけで2項目以降は無視されます。
842         *
843         * @og.rev 5.1.7.0 (2010/06/01) SQLGET対応
844         *
845         * @param table DBTableModelオブジェクト
846         *
847         * @return SQL文の結果文字列
848         */
849        private String getSQLAttribute( final DBTableModel table ) {
850                if( table == null ) {           // 3.8.6.0 (2006/08/07)
851                        return "";
852                }
853
854                int rowCnt = table.getRowCount();
855                final String rtn;
856                if( ACT_ROW_APPEND.equals( action ) ) {
857                        StringBuilder buf = new StringBuilder();
858                        for( int row=0; row<rowCnt; row++ ) {
859                                if( row > 0 ) { buf.append( separator ); }
860                                buf.append( table.getValue( row, 0 ) );
861                        }
862                        rtn = buf.toString();
863                }
864                else if ( rowCnt == 0 ) {
865                        rtn = "";
866                }
867                else {
868                        rtn = table.getValue( 0, 0 );
869                }
870
871                return rtn;
872        }
873
874        /**
875         * 指定のスコープの内部キャッシュ情報に、DBTableModel の選択された値を登録します。
876         *
877         * 複数選択行が存在する場合は、先頭行を処理します。ただし、action="APPEND"の
878         * 場合は、separator属性で指定された文字を使用して、連結します。
879         *
880         * @og.rev 3.1.0.1 (2003/03/26) 新規作成
881         * @og.rev 3.5.6.5 (2004/08/09) ACT_APPEND 時の処理変更
882         * @og.rev 3.6.1.0 (2005/01/05) ACT_ALL_APPEND アクションの追加
883         * @og.rev 4.3.7.5 (2009/07/13) ACT_LIST、ACT_ALL_LIST アクションの追加
884         * @og.rev 5.1.6.0 (2010/05/01) ALL_APPENDで選択行がない場合に処理されないバグを修正
885         * @og.rev 5.5.0.3 (2012/03/12) ACT_MAP アクションの追加
886         * @og.rev 5.6.4.3 (2013/05/24) ACT_MAX_MIN,ACT_ALL_MAX_MIN アクションの追加
887         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加。action="ALL_xxx"を tmpSelectedAll="true" に置き換えます。
888         *
889         * @param table         DBTableModelオブジェクト
890         * @param key           キー
891         * @param action        アクション
892         */
893        private void setTableAttribute( final DBTableModel table,final String key,final String action ) {
894                if( table == null || table.getRowCount() == 0 || table.getColumnCount() == 0 ) { return ; }
895
896                int[] rowNo = getParameterRows();
897                // 5.1.6.0 (2010/05/01)
898                if( rowNo.length == 0 ) { return; }                             // 5.6.4.3 (2013/05/24) tmpSelectedAll 属性を追加したので、0件判定が使える。
899
900                final String[] keys ;
901                if( key == null || key.length() == 0 ) {
902                        keys = table.getNames();
903                }
904                else {
905                        keys = new String[] { key } ;
906                }
907
908                // 5.6.4.3 (2013/05/24) tmpSelectedAll で、ロジックの共通化
909                if( ACT_APPEND.equals( action ) ) {
910                        for( int i=0; i<keys.length; i++ ) {
911                                int clm = table.getColumnNo( keys[i] );
912                                StringBuilder val = new StringBuilder();
913                                val.append( table.getValue( rowNo[0],clm ) );
914                                for( int j=1; j<rowNo.length; j++ ) {
915                                        val.append( separator );
916                                        val.append( table.getValue( rowNo[j],clm ) );
917                                }
918                                setObject( keys[i],val.toString() );
919                        }
920                }
921
922                // 5.5.0.3 (2012/03/12) ACT_MAP アクションの追加
923                else if( ACT_MAP.equals( action ) ) {
924                        int keyClm = table.getColumnNo( key   ,false );
925                        int valClm = table.getColumnNo( value ,false );
926
927                        if( keyClm < 0 ) { keyClm = 0; }     // キーとなるカラムが指定されていない場合は、最初のカラム
928                        if( valClm < 0 ) { valClm = 1; }     // 値となるカラムが指定されていない場合は、2番目のカラム
929
930                        for( int j=0; j<rowNo.length; j++ ) {
931                                String mapkey = table.getValue( rowNo[j], keyClm );
932                                String mapval = table.getValue( rowNo[j], valClm );
933                                setObject( mapkey , mapval );
934                        }
935                }
936
937                // 4.3.7.5 (2009/07/13) ACT_LIST アクションの追加
938                else if( ACT_LIST.equals( action ) ) {
939                        for( int i=0; i<keys.length; i++ ) {
940                                int clm = table.getColumnNo( keys[i] );
941                                ArrayList<String> list = new ArrayList<String>();
942                                for( int j=0; j<rowNo.length; j++ ) {
943                                        list.add( table.getValue( rowNo[j],clm ) );
944                                }
945                                setObject( keys[i],list );
946                        }
947                }
948
949                // 5.6.4.3 (2013/05/24) ACT_MAX_MIN アクションの追加
950                else if( ACT_MAX_MIN.equals( action ) ) {
951                        NumberFormat nf = null;
952                        for( int i=0; i<keys.length; i++ ) {
953                                int clm = table.getColumnNo( keys[i] );
954                                DBColumn clmObj = table.getDBColumn( clm );
955                                String clsNm = clmObj.getClassName();                   // NUMBER,INTEGER,DECIMAL が数字型。
956
957                                boolean numFlag = "NUMBER,INTEGER,DECIMAL".indexOf( clsNm ) >= 0 ;           // 数字型:true
958
959                                String minVal = null ;
960                                String maxVal = null ;
961                                double minNum = Double.MAX_VALUE ;
962                                double maxNum = Double.MIN_VALUE ;
963                                double sumNum = 0d ;
964                                int    cntSum = 0;              // 平均計算に有効な件数
965
966                                for( int j=0; j<rowNo.length; j++ ) {
967                                        String val = table.getValue( rowNo[j],clm );
968                                        if( val != null && val.length() > 0 ) {
969                                                // 数字として比較
970                                                if( numFlag ) {
971                                                        double tmp = Double.parseDouble( val );
972                                                        if( minNum > tmp ) { minNum = tmp; minVal = val; }
973                                                        if( maxNum < tmp ) { maxNum = tmp; maxVal = val; }
974                                                        sumNum += tmp ;  cntSum++ ;
975                                                }
976                                                else {
977                                                        // 文字列として比較
978                                                        if( minVal == null || minVal.compareTo( val ) > 0 ) { minVal = val; }        // 最初のデータは、必ずセットする。
979                                                        if( maxVal == null || maxVal.compareTo( val ) < 0 ) { maxVal = val; }        // 最初のデータは、必ずセットする。
980                                                }
981                                        }
982                                }
983                                if( minVal == null ) { minVal = nval( defaultVal , "" ); }              // 最後まで値が決まらなければ、""(空文字列) にする。
984                                if( maxVal == null ) { maxVal = nval( defaultVal , "" ); }              // 最後まで値が決まらなければ、""(空文字列) にする。
985                                setObject( "MIN." + keys[i],minVal );
986                                setObject( "MAX." + keys[i],maxVal );
987
988                                // SUM と AVG は、数字型の場合のみセットします。
989                                if( cntSum > 0 ) {
990                                        if( nf == null ) {
991                                                nf = NumberFormat.getInstance();
992                                                nf.setGroupingUsed( false );                                    // カンマ編集なし
993                                                nf.setMaximumFractionDigits(2);                                 // 最大小数部は2桁
994                                                nf.setMinimumFractionDigits(0);                                 // できれば、整数表示
995                                        }
996                                        setObject( "SUM." + keys[i],nf.format( sumNum ) );              // Double.toString( sumNum ) の代わり。
997                                        setObject( "AVG." + keys[i],nf.format( sumNum/cntSum ) );
998                                }
999                                else {
1000                                        setObject( "SUM." + keys[i],nval( defaultVal , "" ) );
1001                                        setObject( "AVG." + keys[i],nval( defaultVal , "" ) );
1002                                }
1003                        }
1004                }
1005                else {
1006                        for( int i=0; i<keys.length; i++ ) {
1007                                int clm = table.getColumnNo( keys[i] );
1008                                setAttribute( keys[i],table.getValue( rowNo[0],clm ),action );
1009                        }
1010                }
1011        }
1012
1013        /**
1014         * DBTableModel の選択された値を取得します。
1015         *
1016         * 複数選択行が存在する場合は、先頭行を処理します。ただし、action="APPEND"の
1017         * 場合は、separator属性で指定された文字を使用して、連結します。
1018         *
1019         * @og.rev 3.1.0.1 (2003/03/26) 新規作成
1020         * @og.rev 3.5.6.5 (2004/08/09) ACT_APPEND 時の処理変更
1021         * @og.rev 3.6.1.0 (2005/01/05) ACT_ALL_APPEND アクションの追加
1022         * @og.rev 5.1.6.0 (2010/05/01) ALL_APPENDで選択行がない場合に処理されないバグを修正
1023         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加。action="ALL_xxx"を tmpSelectedAll="true" に置き換えます。
1024         *
1025         * @param       table   DBTableModelオブジェクト
1026         * @param       key             キー
1027         * @param       action  アクション
1028         *
1029         * @return      DBTableModelの選択された値
1030         */
1031        private String getTableAttribute( final DBTableModel table,final String key,final String action ) {
1032                if( table == null ) {
1033                        String errMsg = "table がセットされていません。"
1034                                                + " command=" + command + " , action=" + action
1035                                                + " , key=" + key ;                     // 5.1.8.0 (2010/07/01) errMsg 修正
1036                        throw new HybsSystemException( errMsg );
1037                }
1038
1039                if( key == null || key.length() == 0 ) {
1040                        String errMsg = "key がセットされていません。"
1041                                                + " command=" + command + " , action=" + action;                        // 5.1.8.0 (2010/07/01) errMsg 修正
1042                        throw new HybsSystemException( errMsg );
1043                }
1044
1045                int[] rowNo = getParameterRows();
1046                // 5.1.6.0 (2010/05/01)
1047                if( rowNo.length == 0 ) { return "" ; }                         // 5.6.4.3 (2013/05/24) tmpSelectedAll 属性を追加したので、0件判定が使える。
1048
1049                // 3.6.1.0 (2005/01/05) ACT_ALL_APPEND アクションの追加
1050                int clm = table.getColumnNo( key );
1051                if( ACT_APPEND.equals( action ) ) {
1052                        StringBuilder val = new StringBuilder();
1053                        val.append( table.getValue( rowNo[0],clm ) );
1054                        for( int j=1; j<rowNo.length; j++ ) {
1055                                val.append( separator );
1056                                val.append( table.getValue( rowNo[j],clm ) );
1057                        }
1058                        return val.toString() ;
1059                }
1060                else {
1061                        return actionExec( action,table.getValue( rowNo[0],clm ) );
1062                }
1063        }
1064
1065        /**
1066         * 指定のスコープの内部キャッシュ情報に、DBTableModel の選択された値を登録します。
1067         *
1068         * これは、key で指定したカラムの値をキーとして、value で指定したカラムの値を
1069         * value 値として設定します。
1070         * setTableAttribute が、カラム(横持ち)データを処理するのに対して、
1071         * ロウ(縦持ち)データを処理することが出来ます。
1072         *
1073         * @og.rev 3.1.0.1 (2003/03/26) 新規作成
1074         * @og.rev 3.3.3.3 (2003/08/06) key 情報がデータの値になっていた。バグ修正。
1075         * @og.rev 3.5.6.5 (2004/08/09) ACT_APPEND 時の処理変更
1076         *
1077         * @param table         DBTableModelオブジェクト
1078         * @param key           キー
1079         * @param value         値
1080         * @param action        アクション
1081         */
1082        private void setKeyTableAttribute( final DBTableModel table,final String key,final String value,final String action ) {
1083                if( table == null ) { return ; }
1084
1085                if( key == null || key.length() == 0 ) {
1086                        String errMsg = "key がセットされていません。"
1087                                                + " command=" + command + " , action=" + action
1088                                                + " , value=" + value ;                 // 5.1.8.0 (2010/07/01) errMsg 修正
1089                        throw new HybsSystemException( errMsg );
1090                }
1091
1092                int[] rowNo = getParameterRows();
1093                if( rowNo.length == 0 ) { return ; }
1094
1095                final int[] valClm ;
1096                if( value == null || value.length() == 0 ) {
1097                        String[] vals = table.getNames();
1098                        valClm = new int[vals.length];
1099                        for( int i=0; i<vals.length; i++ ) {
1100                                valClm[i] = table.getColumnNo( vals[i] );
1101                        }
1102                }
1103                else {
1104                        valClm = new int[] { table.getColumnNo( value ) } ;
1105                }
1106
1107        // 3.3.3.3 (2003/08/06) key 情報がデータの値になっていた。バグ修正。
1108        //      3.5.6.5 (2004/08/09) ロジック変更
1109                for( int j=0; j<rowNo.length; j++ ) {
1110                        String rowKey = key + j ;
1111                        if( ACT_APPEND.equals( action ) ) {
1112                                StringBuilder val = new StringBuilder();
1113                                val.append( table.getValue( rowNo[j],valClm[0] ) );
1114                                for( int i=1; i<valClm.length; i++ ) {
1115                                        val.append( separator );
1116                                        val.append( table.getValue( rowNo[j],valClm[i] ) );
1117                                }
1118                                setObject( rowKey,val.toString() );
1119                        }
1120                        else {
1121                                setAttribute( rowKey,table.getValue( rowNo[j],valClm[0] ),action );
1122                        }
1123                }
1124        }
1125
1126        /**
1127         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
1128         *
1129         * action="FIRST" 処理と、tmpSelectedAll 属性追加に伴う処理を、Override します。
1130         *
1131         * @og.rev 3.1.0.1 (2003/03/26) 新規作成
1132         * @og.rev 4.0.0.0 (2005/01/31) メイン処理を、super class で対応
1133         * @og.rev 3.8.0.4 (2005/08/08) action="FIRST" 機能の追加
1134         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性の追加に伴い、全件選択状態のデータを作成します。
1135         *
1136         * @return      選択行の配列
1137         */
1138        @Override
1139        protected int[] getParameterRows() {
1140                final int[] rowNo ;
1141                // 3.8.0.4 (2005/08/08) action="FIRST" 機能の追加
1142                if( ACT_FIRST.equals( action ) ) {
1143                        rowNo = new int[] { 0 };
1144                }
1145                // 5.6.4.3 (2013/05/24) tmpSelectedAll 属性の追加
1146                else if( tmpSelectedAll ) {
1147                        int rowCnt = table.getRowCount();
1148                        rowNo = new int[ rowCnt ];
1149                        for( int i=0; i<rowCnt; i++ ) {
1150                                rowNo[i] = i;
1151                        }
1152                }
1153                else {
1154                        rowNo = super.getParameterRows() ;
1155                }
1156                return rowNo ;
1157        }
1158
1159        /**
1160         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
1161         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
1162         *
1163         * @og.tag
1164         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
1165         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
1166         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
1167         * この tableId 属性を利用して、メモリ空間を分けます。
1168         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
1169         *
1170         * @param       id sessionに登録する時の ID
1171         */
1172        public void setTableId( final String id ) {
1173                tableId   = nval( getRequestParameter( id ),tableId );
1174        }
1175
1176        /**
1177         * 【TAG】コマンド(SET,GET,REMOVE,SQL,SETTBL,GETTBL,KEYTBL,CLEAR,SETMEM)をセットします(初期値:SET)。
1178         *
1179         * @og.tag
1180         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
1181         * フィールド定数値のいづれかを、指定できます。
1182         * 何も設定されない、または、null の場合は、"SET" が初期値にセットされます。
1183         *
1184         * CLEAR 以外のすべての処理は、指定のスコープの内部キャッシュ情報に対して行われます。
1185         * <table border="1" frame="box" rules="all" >
1186         *   <caption>コマンド 一覧</caption>
1187         *   <tr><th>command </th><th>名称          </th><th>機能</th></tr>
1188         *   <tr><td>SET    </td><td>セット         </td><td>指定のキーに、value値を登録します。</td></tr>
1189         *   <tr><td>GET    </td><td>ゲット         </td><td>指定のキーの値を画面に出力します。</td></tr>
1190         *   <tr><td>REMOVE </td><td>リムーブ       </td><td>指定のキーの値を削除します。</td></tr>
1191         *   <tr><td>CLEAR  </td><td>クリア         </td><td>セッション/アプリケーションスコープのキャッシュ情報をクリアします。</td></tr>
1192         *   <tr><td>SQL    </td><td>SQL         </td><td>指定のSQL文の実行結果を、カラム名をキーとして設定します。</td></tr>
1193         *   <tr><td>SQLGET </td><td>SQLゲット   </td><td>指定のSQL文の実行結果を、画面に出力します。(2項目以降は無視されます)。</td></tr>
1194         *   <tr><td>SETTBL </td><td>セットテーブル </td><td>指定のキーに、DBTableModel の選択されたカラム(横持ち)の値を登録します。</td></tr>
1195         *   <tr><td>GETTBL </td><td>ゲットテーブル </td><td>指定のキーに、DBTableModel の選択されたカラム(横持ち)の値を画面に出力します。</td></tr>
1196         *   <tr><td>KEYTBL </td><td>キーテーブル   </td><td>指定のキーに、DBTableModel の選択されたロウ(縦持ち)の値を登録します。</td></tr>
1197         *   <tr><td>SETMEM </td><td>セットメモリ   </td><td>指定のキーに、value値を内部キャッシュに登録します。</td></tr>
1198         * </table>
1199         *
1200         * @og.rev 3.1.0.1 (2003/03/26) 指定のコマンド以外は、エラーとするように変更。
1201         * @og.rev 3.5.6.2 (2004/07/05) 文字列の連結にStringBuilderを使用します。
1202         *
1203         * @param       cmd コマンド(public static final 宣言されている文字列)
1204         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ValueTag.CMD_GET">コマンド定数</a>
1205         */
1206        public void setCommand( final String cmd ) {
1207                command = nval( getRequestParameter( cmd ),command ).toUpperCase(Locale.JAPAN);
1208
1209                if( !check( command, COMMAND_LIST ) ) {
1210                        StringBuilder errMsg = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
1211                        errMsg.append( "指定のコマンドは実行できません。コマンドエラー" );
1212                        errMsg.append( HybsSystem.CR );
1213                        errMsg.append( "command=[" ).append( command ).append( "] " );
1214                        errMsg.append( HybsSystem.CR );
1215                        for( int i=0; i<COMMAND_LIST.length; i++ ) {
1216                                errMsg.append( " | " );
1217                                errMsg.append( COMMAND_LIST[i] );
1218                        }
1219                        errMsg.append( " | " );
1220                        throw new HybsSystemException( errMsg.toString() );
1221                }
1222        }
1223
1224        /**
1225         * 【TAG】アクション(UPPER,LOWER,MESSAGE,APPEND,ALL_APPEND,MAP,ALL_MAP,LIST,ALL_LIST,
1226         *        DAY_WEEK,MERGE,FIRST,ROW_APPEND,REPLACE,SUBSTR,SPLIT,MAX_MIN,ALL_MAX_MIN,EXEC,CASE)をセットします。
1227         *
1228         * @og.tag
1229         * アクションは,HTMLから(get/post)指定されますので,ACT_xxx で設定される
1230         * フィールド定数値のいづれかを、指定できます。
1231         * 無指定の場合は、なにもしません。
1232         *
1233         * <table border="1" frame="box" rules="all" >
1234         *   <caption>アクション 一覧</caption>
1235         *   <tr><th>action     </th><th>名称               </th><th>機能</th></tr>
1236         *   <tr><td>UPPER      </td><td>アッパー(大文字化) </td><td>value値を大文字に変換します。</td></tr>
1237         *   <tr><td>LOWER      </td><td>ローワー(小文字化) </td><td>value値を小文字に変換します。</td></tr>
1238         *   <tr><td>MESSAGE    </td><td>メッセージ変換     </td><td>引数をメッセージリソースのキーとして、メッセージ変換します。</td></tr>
1239         *   <tr><td>APPEND     </td><td>データアペンド     </td><td>複数リクエストや複数選択時に値を連結します。</td></tr>
1240         *   <tr><td>ALL_APPEND </td><td>オールアペンド     </td><td>SETTBL,GETTBL 時に、チェック行以外の全行を対象に値の連結を行います。</td></tr>
1241         *   <tr><td>MAP        </td><td>マップ             </td><td>検索結果やTableModelのkeyをキーに、valuewを値に一括設定します。</td></tr>
1242         *   <tr><td>ALL_MAP    </td><td>オールマップ       </td><td>全行を対象に検索結果やTableModelのkeyをキーに、valuewを値に一括設定します。</td></tr>
1243         *   <tr><td>LIST       </td><td>リスト             </td><td>複数リクエストや複数選択時に値をArrayListにセットします。</td></tr>
1244         *   <tr><td>ALL_LIST   </td><td>オールリスト       </td><td>全行を対象に値をArrayListにセットします。</td></tr>
1245         *   <tr><td>DAY_WEEK   </td><td>日付前方まるめ     </td><td>日付型文字列(YYYYMMDD) の値を、月曜日に変換します。</td></tr>
1246         *   <tr><td>           </td><td>                   </td><td>指定日が日曜日の場合は、次の日(月曜日)に進めます。その他は、週始めに戻します。</td></tr>
1247         *   <tr><td>MERGE      </td><td>データのマージ     </td><td>重複を除く、ユニークな値に、マージします。(カンマで分解、separatorで合成)</td></tr>
1248         *   <tr><td>FIRST      </td><td>1件目取得         </td><td>最初の1件目を強制的に選択状態にして、処理を行います。</td></tr>
1249         *   <tr><td>ROW_APPEND </td><td>検索結果の連結     </td><td>検索結果の行方向のデータを連結します。</td></tr>
1250         *   <tr><td>REPLACE    </td><td>文字列置換         </td><td>value の値から、指定された正規表現(from)の部分文字列を、部分文字列(to)で置換します。</td></tr>
1251         *   <tr><td>SUBSTR     </td><td>部分文字列         </td><td>value の値から、指定された(from)から(to)の部分文字列を作成します。</td></tr>
1252         *   <tr><td>SPLIT      </td><td>文字列分割         </td><td>value の値から、指定されたseparatorで分割した文字列を作成します。(key+0〜連番)</td></tr>
1253         *   <tr><td>MAX_MIN    </td><td>最大_最小値        </td><td>選択行のkeyのカラムの最小値,最大値を、MIN.キー、MAX.キー の値にセットします。※1</td></tr>
1254         *   <tr><td>ALL_MAX_MIN</td><td>最大_最小値        </td><td>全行を対象にkeyのカラムの最小値,最大値を、MIN.キー、MAX.キー の値にセットします。※1</td></tr>
1255         *   <tr><td>EXEC       </td><td>計算結果           </td><td>value またはBODY部の値を、JavaScriptで計算した結果をセットします。</td></tr>
1256         *   <tr><td>CASE       </td><td>条件分岐           </td><td>fromVal="A:1 B:2 C:3 D:4" 形式の値を元に、value値(左辺)に一致する右辺をセットします。※2</td></tr>
1257         * </table>
1258         *
1259         * ※1 MAX_MIN,ALL_MAX_MIN  については、DBTableModelのカラムのCLS_NAMEが、NUMBER,INTEGER,DECIMAL の場合は、数字型(double)に変換して比較します。
1260         *    数字型(double)の場合だけ、合計(SUM.キー) と 平均(AVG.キー)計算も同時に行います。
1261         *    それ以外の場合は、文字列比較を行います。(command="SETTBL" のみ)
1262         *    command="SET" の場合は、数字型(double)として、value の値を、separator で分解したうえで、最大、最小、合計、平均 を計算し、
1263         *    それぞれを、MIN.キー、MAX.キー、SUM.キー、AVG.キー 変数にセットします。
1264         *    数字に変換できなかった場合は、エラーになります。
1265         *    null は、無視され(平均を求める場合の母数としても無視)、すべてが nulll の場合は、ゼロ文字列("")になります。
1266         *    ゼロ文字列("") の場合に、defaultVal 属性が設定されていると、defaultVal が設定されます。
1267         * ※2 CASE は、fromVal="A:1 B:2 C:3 D:4" 形式の値に対して、コロン(:)で分解し、value値(左辺)が、一致する右辺を返します。
1268         *    fromVal の値は、スペースで分割され、コロン(:)が存在する左辺(キー)と右辺(値)に分解し、value値とキーを比較し、
1269         *    一致すれば、右辺の値を返します。
1270         *    valueがnullの場合、defaultVal が設定されており、その値で、fromVal の値と比較します。
1271         *    一致する値がなければ、元の value が返されます。
1272         *
1273         * @og.rev 3.1.0.1 (2003/03/26) 指定のアクション以外は、エラーとするように変更。
1274         * @og.rev 3.5.6.2 (2004/07/05) 文字列の連結にStringBuilderを使用します。
1275         * @og.rev 4.3.7.5 (2009/07/13) ACT_LIST、ACT_ALL_LIST アクションの追加(JavaDocのみ修正)
1276         * @og.rev 5.6.4.3 (2013/05/24) ACTMAX_MIN アクションの追加(JavaDocのみ修正)
1277         * @og.rev 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加にともなう修正。action="ALL_xxx"は、tmpSelectedAll=true にします。
1278         * @og.rev 5.7.7.2 (2014/06/20) EXEC と CASE アクションを追加
1279         *
1280         * @param       act アクション(public static final 宣言されている文字列)
1281         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ValueTag.ACT_APPEND">アクション定数</a>
1282         */
1283        public void setAction( final String act ) {
1284                action = nval( getRequestParameter( act ),action );
1285
1286                if( action != null && !check( action, ACTION_LIST ) ) {
1287                        StringBuilder errMsg = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
1288                        errMsg.append( "指定のアクションは実行できません。アクションエラー" );
1289                        errMsg.append( HybsSystem.CR );
1290                        errMsg.append( "action=[" ).append( action ).append( "] " );
1291                        errMsg.append( HybsSystem.CR );
1292                        for( int i=0; i<ACTION_LIST.length; i++ ) {
1293                                errMsg.append( " | " );
1294                                errMsg.append( ACTION_LIST[i] );
1295                        }
1296                        errMsg.append( " | " );
1297                        throw new HybsSystemException( errMsg.toString() );
1298                }
1299
1300                // 5.6.4.3 (2013/05/24) tmpSelectedAll 属性追加。action="ALL_xxx"を tmpSelectedAll="true" に置き換えます。
1301                if( action != null && action.startsWith( "ALL_" ) ) {
1302                        action      = action.substring( 4 );    // "ALL_" の4文字分削除
1303                        tmpSelectedAll = true;
1304                }
1305        }
1306
1307        /**
1308         * 【TAG】リクエスト情報 に登録するキーをセットします。
1309         *
1310         * @og.tag リクエスト情報 に登録するキーをセットします。
1311         *
1312         * @og.rev 3.0.1.3 (2003/03/11) キーを toUpperCase している箇所を削除
1313         *
1314         * @param       key1 リクエスト情報に登録するキー
1315         */
1316        public void setKey( final String key1 ) {
1317                key = nval( getRequestParameter( key1 ),key ) ;
1318                if( key == null ) {
1319                        String errMsg = "key がセットされていません。"
1320                                                + " command=" + command + " , action=" + action;                        // 5.1.8.0 (2010/07/01) errMsg 修正
1321                        throw new HybsSystemException( errMsg );
1322                }
1323        }
1324
1325        /**
1326         * 【TAG】リクエスト情報 に登録する値をセットします。
1327         *
1328         * @og.tag リクエスト情報 に登録する値をセットします。
1329         *
1330         * @og.rev 3.1.7.0 (2003/05/02) isNullSet 属性が true(初期値)のときは、リクエスト情報から値を取得。
1331         * @og.rev 3.5.4.0 (2003/11/25) getRequestParameter( value ) メソッドを setValue に移動。
1332         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
1333         *
1334         * @param       val     リクエスト情報に登録する値
1335         */
1336        public void setValue( final String val ) {
1337                inValue = val;          // 3.5.4.0 (2003/11/25) 入力変数も、キープしておく。
1338                value = getRequestParameter( inValue );
1339        }
1340
1341        /**
1342         * 【TAG】value値がNULLの場合に、この初期値を設定します。
1343         *
1344         * @og.tag
1345         * value値がNULLの場合に、この初期値をセットします。
1346         *
1347         * @param       val 初期値
1348         */
1349        public void setDefaultVal( final String val ) {
1350                defaultVal = getRequestParameter( val );
1351        }
1352
1353        /**
1354         * 【廃止】value が NULL の時に、設定するかどうか[true/false]を指定します(初期値:true)。
1355         *
1356         * @og.tag
1357         * true の場合は, null のときでもセットします。
1358         * false の場合は, null のときは、既存の値を置き換えません。
1359         * 初期値は、null のときでもセットするです。 ("true")
1360         *
1361         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
1362         *
1363         * @param   flag NULL の時に設定するかどうか [true:設定する/それ以外:設定しない]
1364         * @deprecated 5.1.8.0 (2010/07/01) 廃止。
1365         */
1366        @Deprecated public void setNullSet( final String flag ) {
1367//              isNullSet = nval( getRequestParameter( flag ),isNullSet );
1368        }
1369
1370        /**
1371         * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。
1372         *
1373         * @og.tag Queryオブジェクトを作成する時のDB接続IDを指定します。
1374         *
1375         * @param       id データベース接続ID
1376         */
1377        public void setDbid( final String id ) {
1378                dbid = nval( getRequestParameter( id ),dbid );
1379        }
1380
1381        /**
1382         * 【TAG】キャッシュする場合のスコープ(request,session)を指定します(初期値:request)。
1383         *
1384         * @og.tag
1385         * "request","session" が指定できます。
1386         * 初期値は、 "request" です。
1387         *
1388         * @param       scp     スコープ
1389         */
1390        @Override
1391        public void setScope( final String scp ) {
1392                scope = nval( getRequestParameter( scp ),scope );
1393        }
1394
1395        /**
1396         * 【TAG】DBTableModel から取得する場合のスコープ(request,session)を指定します(初期値:session)。
1397         *
1398         * @og.tag
1399         * "request","session" が指定できます。
1400         * 初期値は、 "session" です。
1401         *
1402         * @og.rev 5.1.2.0 (2010/01/01) DBTableModel の取得先のscope
1403         *
1404         * @param       scp     スコープ
1405         */
1406        public void setTblScope( final String scp ) {
1407                tblScope = nval( getRequestParameter( scp ),tblScope );
1408        }
1409
1410        /**
1411         * 【TAG】マルチデータ(複数件検索)を使用するかどうか[true/false]を指定します(初期値:false)。
1412         *
1413         * @og.tag
1414         * command="SQL" の場合に、複数行検索した結果を、キー+行番号 というキーを作成して
1415         * 値を設定するかどうかを指定します。
1416         * false の場合は、従来どおり、検索カラム名がキーになります。
1417         * 初期値は、false です。
1418         *
1419         * @og.rev 3.2.4.0 (2003/06/12) 新規追加
1420         *
1421         * @param   flag 複数件検索 [true:使用する/false:使用しない]
1422         */
1423        public void setUseMultiRows( final String flag ) {
1424                useMultiRows = nval( getRequestParameter( flag ),useMultiRows );
1425        }
1426
1427        /**
1428         * 【TAG】各種アクションの文字列を連結/分解する項目区切り文字をセットします(初期値:",")。
1429         *
1430         * @og.tag
1431         * 各種アクションに基づく処理において、文字列の区切りを指定するのに使用します。
1432         * APPEND、ROW_APPEND 時には、文字列の連結に使用します。
1433         * MERGE の場合は、カンマで分解後、このセパレータでMERGE処理を行い、再び、連結します。
1434         * 初期値は、"," に設定されています。
1435         *
1436         * @og.rev 3.5.6.5 (2004/08/09) 新規追加
1437         *
1438         * @param   sepa 項目区切り文字(初期値:",")
1439         */
1440        public void setSeparator( final String sepa ) {
1441                separator = nval( getRequestParameter( sepa ),separator );
1442        }
1443
1444        /**
1445         * 【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します
1446         *              (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。
1447         *
1448         * @og.tag
1449         * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
1450         * (&gt;&lt;) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
1451         * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。
1452         *
1453         * @og.rev 5.1.7.0 (2010/06/01) 新規追加
1454         *
1455         * @param       flag    XSSチェック [true:する/false:しない]
1456         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
1457         */
1458        public void setXssCheck( final String flag ) {
1459                xssCheck = nval( getRequestParameter( flag ),xssCheck );
1460        }
1461
1462        /**
1463         * 【TAG】部分文字列置換の 置換え前の部分文字列(from)を指定します。
1464         *
1465         * @og.tag
1466         * value の値から、指定された正規表現(from)に一致する、この文字列の各部分文字列に対し、
1467         * 指定された文字列(to)で置換します。
1468         * value.replaceAll( from, to ) という文法で処理します。
1469         *
1470         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
1471         *
1472         * @param       from    置換え前の部分文字列
1473         * @see         #setToVal(String)
1474         */
1475        public void setFromVal( final String from ) {
1476                fromVal = nval( getRequestParameter( from ),fromVal );
1477        }
1478
1479        /**
1480         * 【TAG】部分文字列置換の 置換え後の部分文字列(to)を指定します。
1481         *
1482         * @og.tag
1483         * value の値から、指定された正規表現(from)に一致する、この文字列の各部分文字列に対し、
1484         * 指定された文字列(to)で置換します。
1485         * value.replaceAll( from, to ) という文法で処理します。
1486         *
1487         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
1488         *
1489         * @param       to      置換え後の部分文字列
1490         * @see         #setFromVal(String)
1491         */
1492        public void setToVal( final String to ) {
1493                toVal = nval( getRequestParameter( to ),toVal );
1494        }
1495
1496        /**
1497         * シリアライズ用のカスタムシリアライズ書き込みメソッド
1498         *
1499         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1500         * @serialData 一部のオブジェクトは、シリアライズされません。
1501         *
1502         * @param       strm    ObjectOutputStreamオブジェクト
1503         * @throws IOException  入出力エラーが発生した場合
1504         */
1505        private void writeObject( final ObjectOutputStream strm ) throws IOException {
1506                strm.defaultWriteObject();
1507        }
1508
1509        /**
1510         * シリアライズ用のカスタムシリアライズ読み込みメソッド
1511         *
1512         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
1513         *
1514         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
1515         * @serialData 一部のオブジェクトは、シリアライズされません。
1516         *
1517         * @param       strm    ObjectInputStreamオブジェクト
1518         * @see #release2()
1519         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
1520         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
1521         */
1522        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
1523                strm.defaultReadObject();
1524        }
1525
1526        /**
1527         * このオブジェクトの文字列表現を返します。
1528         * 基本的にデバッグ目的に使用します。
1529         *
1530         * @og.rev 4.3.4.0 (2008/12/01) PageContextのスコープをクラス変数としてアクセス
1531         * @og.rev 5.1.8.0 (2010/07/01) isNullSet 属性 廃止
1532         *
1533         * @return このクラスの文字列表現
1534         */
1535        @Override
1536        public String toString() {
1537                String rtnStr = org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
1538                                .println( "VERSION"                     ,VERSION                )
1539                                .println( "tableId"                     ,tableId                )
1540                                .println( "command"                     ,command                )
1541                                .println( "key"                         ,key                    )
1542                                .println( "inValue"                     ,inValue                )
1543                                .println( "value"                       ,value                  )
1544                                .println( "defaultVal"          ,defaultVal             )
1545                                .println( "action"                      ,action                 )
1546                                .println( "dbid"                        ,dbid                   )
1547                                .println( "scope"                       ,scope                  )
1548                                .println( "separator"           ,separator              )
1549                                .println( "useMultiRows"        ,useMultiRows   )
1550                                .println( "COMMAND_LIST"        ,COMMAND_LIST   )
1551                                .println( "ACTION_LIST"         ,ACTION_LIST    )
1552                                .println( "Other..."    ,getAttributes().getAttribute() )
1553                                .fixForm().toString() ;
1554
1555                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
1556                rtn.append( HybsSystem.CR ).append( "====================================" ).append( HybsSystem.CR );
1557
1558                rtn.append( "APPLICATION_SCOPE:" ).append( HybsSystem.CR );
1559
1560                Enumeration<String> ekeys = pageContext.getAttributeNamesInScope( PageContext.APPLICATION_SCOPE );        // 4.3.3.6 (2008/11/15) Generics警告対応
1561                while ( ekeys.hasMoreElements() ) {
1562                        String ekey = ekeys.nextElement();              // 4.3.3.6 (2008/11/15) Generics警告対応
1563                        rtn.append( "  key=[" ).append( ekey ).append( "] " );
1564                        rtn.append( "value=[" ).append( pageContext.getAttribute( ekey,PageContext.APPLICATION_SCOPE ) ).append( "]" );
1565                        rtn.append( HybsSystem.CR );
1566                }
1567
1568                rtn.append( "SESSION_SCOPE:" ).append( HybsSystem.CR );
1569                ekeys = pageContext.getAttributeNamesInScope( PageContext.SESSION_SCOPE );
1570                while ( ekeys.hasMoreElements() ) {
1571                        String ekey = String.valueOf( ekeys.nextElement() );
1572                        rtn.append( "  key=[" ).append( ekey ).append( "] " );
1573                        rtn.append( "value=[" ).append( pageContext.getAttribute( ekey,PageContext.SESSION_SCOPE ) ).append( "]" );
1574                        rtn.append( HybsSystem.CR );
1575                }
1576
1577                rtn.append( "REQUEST_SCOPE:" ).append( HybsSystem.CR );
1578                ekeys = pageContext.getAttributeNamesInScope( PageContext.REQUEST_SCOPE );
1579                while ( ekeys.hasMoreElements() ) {
1580                        String ekey = String.valueOf( ekeys.nextElement() );
1581                        rtn.append( "  key=[" ).append( ekey ).append( "] " );
1582                        rtn.append( "value=[" ).append( pageContext.getAttribute( ekey,PageContext.REQUEST_SCOPE ) ).append( "]" );
1583                        rtn.append( HybsSystem.CR );
1584                }
1585
1586                rtn.append( "PAGE_SCOPE:" ).append( HybsSystem.CR );
1587                ekeys = pageContext.getAttributeNamesInScope( PageContext.PAGE_SCOPE );
1588                while ( ekeys.hasMoreElements() ) {
1589                        String ekey = String.valueOf( ekeys.nextElement() );
1590                        rtn.append( "  key=[" ).append( ekey ).append( "] " );
1591                        rtn.append( "value=[" ).append( pageContext.getAttribute( ekey,PageContext.PAGE_SCOPE ) ).append( "]" );
1592                        rtn.append( HybsSystem.CR );
1593                }
1594                rtn.append( "====================================" ).append( HybsSystem.CR );
1595
1596                return rtnStr + rtn.toString();
1597        }
1598}