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