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