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