OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / hayabusa / taglib / CommonForwardTag.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.hayabusa.taglib;
17
18 import org.opengion.hayabusa.common.HybsSystem;
19 import org.opengion.hayabusa.common.HybsSystemException;
20 import org.opengion.hayabusa.db.DBTableModel;
21 import org.opengion.fukurou.util.ErrorMessage;
22 import org.opengion.fukurou.util.XHTMLTag;
23 import org.opengion.fukurou.util.StringUtil;
24 import org.opengion.fukurou.util.ToString;                                                      // 6.1.1.0 (2015/01/17)
25
26 import static org.opengion.fukurou.util.StringUtil.nval ;
27
28 import jakarta.servlet.http.HttpServletRequest;
29 import jakarta.servlet.http.HttpServletResponse;
30 import jakarta.servlet.http.HttpSession;
31 import jakarta.servlet.ServletException;
32 import java.io.IOException;
33 import java.util.Enumeration;
34 import java.util.Map;
35 import java.util.HashMap;
36 import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
37 import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.1 (2016/02/12) refactoring
38
39 /**
40  * submitタグを用いてページ転送するタグです(forward.jsp で使用)。
41  *
42  * 通常、forward は、ページ内転送(サーバー内部での転送)のため、別画面への遷移には
43  * 使用できません。これは、別画面では、index.jsp 等でフレーム分割する際の基準フォルダは、
44  * forward の場合、クライアントは理解していないため、もう一度先のフォルダに対する
45  * フレーム分割を行おうとするためです。
46  * (よく、index.jsp の frame タグに、src="../XXXX/query.jsp" などと、自分自身のフォルダ名を
47  * 記述したページを見かけますが、これは、フォルダをまたがる転送に、forward を使用する
48  * 為の悪い対策です。)
49  * 実際は、forward ではなく、redirect を使うべきです。redirect は、指定のアドレス要求を、
50  * 一旦クライアントに投げてそこから再度要求しなおしてもらう方式のため、このようにフォルダを
51  * またがる転送も正常に処理できます。
52  * この、commonForward タグでは、画面遷移の条件に応じて、forward か redirect の自動
53  * 判定を行い、適切に処理しています。
54  * 判定条件は、拡張子や、選択件数などを加味して以下の判定を順次テストします。
55  *
56  *   FORWARD :
57  *       アドレスが、 null(自分自身) か、.jsp を含み、"/" が入っていない場合
58  *   REDIRECT:
59  *       アドレスが、.jsp を含まないか、
60  *       それ以外(.jsp を含み、"/" も含む)で、選択数が1件のみの場合
61  *       もしくはuseRedirectCheck="false"の場合
62  *   COUNT_0 :
63  *       それ以外で、選択数が0件の場合
64  *   COUNT_N :
65  *       それ以外で、選択数が1件以上の場合、または、その他。
66  *
67  * ここで、COUNT_0 の場合は、未選択エラー、COUNT_N は、複数選択エラーを自動的に返します。
68  *
69  * @og.formSample
70  * ●形式:<og:commonForward />
71  * ●body:なし
72  *
73  * ●Tag定義:
74  *   <og:commonForward
75  *       dbkeys             【TAG】DBキーをCSV形式でセットします
76  *       tableId            【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID
77  *       useRedirectCheck   【TAG】非選択状態の場合にforwardを許可するかどうか[true/false]を指定します(初期値:true)
78  *       useRedirectHidden  【TAG】redirectの処理時に、hiddenパラメータを転送するかどうか[true:する/false:しない]指定します(初期値:false)。
79  *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
80  *       useSLabel          【TAG】7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)
81  *   />
82  *
83  * ●使用例
84  *     フォワードキャッシュによりページ転送します。
85  *     <og:commonForward dbkeys="{@dbkeys}" />
86  *
87  * @og.group 画面制御
88  *
89  * @version  4.0
90  * @author       Masaharu Endo
91  * @since    JDK5.0,
92  */
93 public class CommonForwardTag extends CommonTagSupport {
94         /** このプログラムのVERSION文字列を設定します。       {@value} */
95         private static final String VERSION = "7.0.7.0 (2019/12/13)" ;
96         private static final long serialVersionUID = 707020191213L ;
97
98         // 3.5.5.3 (2004/04/09) 共通アドレスで指定することで、クライアントキャッシュを有効利用する。
99         private static final String DUMMY_HTML  = "/" + HybsSystem.getContextName() + "/jsp/common/dummy.html";
100
101         // 3.8.5.1 (2006/04/28) dbkeys が null の場合に全件取得するかどうかを COMMON_FORWARD_DBKEYS_NULL_ALL で指定します。
102
103         private static final int FORWARD  = 0;
104         private static final int REDIRECT = 1;
105         private static final int COUNT_0  = 2;
106         private static final int COUNT_N  = 3;
107
108         // 3.5.5.2 (2004/04/02) 選択行が、1行のみか、そうでないか
109         private int rowCount = -1;
110
111         private int     rowNo    = -1;
112
113         // 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
114         private String  dbkeys          ;
115
116         // 3.5.5.8 (2004/05/20) submitタグの keys,vals を扱う 仮想リクエストMap
117         private String  tableIdTemp     ;
118         private String  dbkeysTemp      ;
119         /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */
120         private final transient ConcurrentMap<String,String> submitRequestMap = new ConcurrentHashMap<>();
121         /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */
122         private final transient ConcurrentMap<String,String> submitTableMap       = new ConcurrentHashMap<>();
123
124         // 4.0.0.0 (2007/11/09) 非選択状態でのforwardのための属性追加
125         private boolean isRedirectCheck         = true;
126
127         // 6.2.4.0 (2015/05/15) redirectの処理時に、hiddenパラメータを転送するかどうか[true:する/false:しない]
128         // 互換性の関係で、初期値は、false にします。
129         private boolean isRedirectHidden        ;
130
131         // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)
132         private boolean         useSLabel       ;
133
134         /**
135          * デフォルトコンストラクター
136          *
137          * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
138          */
139         public CommonForwardTag() { super(); }          // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
140
141         /**
142          * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
143          *
144          * @og.rev 3.3.1.1 (2003/07/03) URLにリクエスト情報をURLエンコードして追加します。
145          * @og.rev 3.5.5.2 (2004/04/02) フォルダ外転送時は、1行以外選択は、エラーとします。
146          * @og.rev 3.5.5.3 (2004/04/09) デバッグ時は、転送しないようにします。
147          * @og.rev 3.8.0.4 (2005/08/08) requestUrlEncode 廃止
148          * @og.rev 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
149          * @og.rev 4.0.0.0 (2007/11/09) 非選択状態からの遷移を許可するフラグを追加(11/12に振り分け処理をselectResponseMethodに移動)
150          * @og.rev 5.0.0.2 (2009/09/15) XSS対応⇒チェックする
151          * @og.rev 5.3.6.0 (2011/06/01) エラーメッセージ変更(URLの振り分け処理時に...のメッセージは出力しない)
152          * @og.rev 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
153          * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。
154          *
155          * @return      後続処理の指示
156          */
157         @Override
158         public int doEndTag() {
159                 debugPrint();           // 4.0.0 (2005/02/28)
160
161                 // useXssCheck( false ); // 5.0.0.2 (2009/09/15)
162
163                 final HttpServletRequest request  = ((HttpServletRequest)getRequest());
164                 final HttpSession session = pageContext.getSession();
165                 String page = getForwardURI( request, session );
166
167                 // 3.5.5.8 (2004/05/20) 内部仮想リクエストMap より値を取得
168                 dbkeys = nval( getSubmitRequestParameter( dbkeysTemp ),dbkeys );
169
170                 final HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
171
172                 String errMsgKey = null;
173                 try {
174
175                         // 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
176                         // 6.2.4.0 (2015/05/15) dbkeys != null の場合しか、[]付のパラメータを処理できなかった。
177                         if( rowCount == 1 && ( dbkeys != null || !submitTableMap.isEmpty() ) ) {                // 6.3.9.0 (2015/11/06) size() == 0 判定は、isEmpty() に置き換え可能
178                                 page = XHTMLTag.addUrlEncode( page,getTableUrlData() );
179                         }
180
181                         final String url = response.encodeRedirectURL( page );
182                         // 3.8.0.8 (2005/10/03) GET時の URL の長さ制限チェック(最大文字数は 2,083 文字)
183                         if( url != null && url.length() >= HybsSystem.MAX_GET_LENGTH ) {
184                                 final String errMsg = "GET時の URL の長さは、最大2,083 文字です。"
185                                                         + " URL.length=" + url.length() + " , MAX_LENGTH=" + HybsSystem.MAX_GET_LENGTH ;
186                                 throw new HybsSystemException( errMsg );
187                         }
188
189                         // 6.4.9.1 (2016/08/05) Avoid declaring a variable if it is unreferenced before a possible exit point.
190                         final int flag = selectResponseMethod( page );
191                         switch( flag ) {
192                                 case FORWARD:   if( isDebug() ) { jspPrint( "FORWARD URL = [" + url + "]" ); }
193                                                                 else { pageContext.forward( url ); }
194                                                                 break;
195                                 case REDIRECT:  // url = requestUrlEncode( url );               // 3.8.0.4 (2005/08/08)
196                                                                 if( isDebug() ) { jspPrint( "REDIRECT URL = [" + url + "]" ); }
197                                                                 else { response.sendRedirect( url ); }
198                                                                 break;
199                                 case COUNT_0:
200                                                                 errMsgKey = "ERR0028" ;  // 選択されていません。もう一度、選択しなおして下さい。
201                                                                 break;
202                                 default: errMsgKey = "ERR0029" ;        // 複数選択されました。1件のみ選択しなおして下さい。
203                                                                 break;
204                         }
205                 }
206                 // 7.2.9.5 (2020/11/28) PMD:'catch' branch identical to 'IOException' branch
207                 catch( final IOException | ServletException ex ) {
208                         // 5.3.6.0 (2011/06/01) エラーメッセージ表示変更
209                         final String errMsg = ex.getMessage();                                  // 5.1.8.0 (2010/07/01) errMsg 修正
210                         throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
211                 }
212 //              } catch( final IOException ex ) {
213 //                      // 5.3.6.0 (2011/06/01) エラーメッセージ表示変更
214 //                      final String errMsg = ex.getMessage();                                  // 5.1.8.0 (2010/07/01) errMsg 修正
215 //                      throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
216 //              } catch( final ServletException ex ) {
217 //                      // 5.3.6.0 (2011/06/01) エラーメッセージ表示変更
218 //                      final String errMsg = ex.getMessage();                                  // 5.1.8.0 (2010/07/01) errMsg 修正
219 //                      throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
220 //              }
221
222                 // 3.5.5.2 (2004/04/02) フォルダ外転送時は、1行以外選択は、エラーとします。
223                 if( errMsgKey != null ) {
224                         final ErrorMessage errMsg = new ErrorMessage( "Row Count Error Maximal Error!" );
225                         errMsg.addMessage( 0,ErrorMessage.NG,errMsgKey );
226
227 //                      jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource() ) );
228                         jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource(),useSLabel ) );            // 7.0.7.0 (2019/12/13)
229                 }
230
231                 return SKIP_PAGE ;              // ページの残りの処理を行わない。
232         }
233
234         /**
235          * タグリブオブジェクトをリリースします。
236          * キャッシュされて再利用されるので、フィールドの初期設定を行います。
237          *
238          * @og.rev 3.5.5.2 (2004/04/02) 新規追加(rowCount,useTableData)
239          * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
240          * @og.rev 3.8.5.1 (2006/04/28) URLに連結するDBTableModelのカラムを[カラム]形式で指定します。
241          * @og.rev 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
242          * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
243          * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。
244          */
245         @Override
246         protected void release2() {
247                 super.release2();
248                 rowCount                        = -1;
249                 rowNo                           = -1;
250                 dbkeys                          = null;         // 3.5.5.5 (2004/04/23)
251                 submitRequestMap.clear();               // 6.4.3.3 (2016/03/04)
252                 submitTableMap.clear();                 // 6.4.3.3 (2016/03/04)
253                 tableIdTemp                     = null;         // 3.5.5.8 (2004/05/20)
254                 dbkeysTemp                      = null;         // 3.5.5.8 (2004/05/20)
255                 isRedirectCheck         = true;         // 4.0.0.0 (2007/11/12)
256                 isRedirectHidden        = false;        // 6.2.4.0 (2015/05/15)
257                 useSLabel                       = false;        // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)
258         }
259
260         /**
261          * フォワード先URIを取得します。
262          *
263          * @og.rev 3.1.2.0 (2003/04/07) ソースコード中の固定値を、定義ファイルを使用するように変更する。
264          * @og.rev 3.1.4.1 (2003/04/21) request.getQueryString() をaddUrlEncodeしている箇所を削除。
265          * @og.rev 3.1.7.0 (2003/05/02) コマンド RENEW で、forward した場合に、result.jsp に遷移するように修正。
266          * @og.rev 3.1.7.0 (2003/05/02) 画面IDのセットで、自画面を、BACK_GAMENID 、飛び先を、GAMENID にする。
267          * @og.rev 3.1.8.0 (2003/05/16) SubmitData クラスを利用するように変更。
268          * @og.rev 3.3.1.1 (2003/07/03) ForwardManager クラスの廃止。飛び先のキャッシュを廃止します。
269          * @og.rev 3.5.5.2 (2004/04/02) 選択行の件数を設定しておきます。
270          * @og.rev 3.5.5.3 (2004/04/09) dummy.html を static final で絶対パス指定します。
271          * @og.rev 3.5.5.4 (2004/04/15) メソッド内で使用していない、gamenId,jspID 変数を削除します。
272          * @og.rev 3.5.5.5 (2004/04/23) 余計なボタン関連情報を転送しない為に、キーを変更します。
273          * @og.rev 3.5.5.5 (2004/04/23) SubmitTag の keys,vals 属性で指定した値のみ、転送します。
274          * @og.rev 3.5.5.8 (2004/05/20) SubmitTag の keys,vals 属性で指定した値を、内部仮想リクエスト Mapにセットします。
275          * @og.rev 3.7.0.1 (2005/01/31) リクエスト変数に選択された件数を追加
276          * @og.rev 3.7.0.3 (2005/03/01) 指定の行番号まで画面をスクロールさせる機能を追加。
277          * @og.rev 3.8.0.8 (2005/10/03) BACK_GAMENID があれば BACK_ROW を追加する。
278          * @og.rev 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
279          * @og.rev 5.1.8.0 (2010/07/01) VIEWの場合も、直前のJSPに遷移する。
280          * @og.rev 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
281          * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
282          * @og.rev 6.4.5.2 (2016/05/06) UPLOADから呼ばれた場合は、RESET  は、command="RENEW" , displayMsg=" " にします。
283          *
284          * @param       request HttpServletRequestオブジェクト
285          * @param       session HttpSessionオブジェクト
286          *
287          * @return      フォワード先URI
288          * @og.rtnNotNull
289          */
290         private String getForwardURI( final HttpServletRequest request,
291                                                                   final HttpSession        session ) {
292
293                 final String[] rows   = request.getParameterValues( HybsSystem.ROW_SEL_KEY );
294
295                 // 4.0.0 (2007/05/16) query.jsp で複数command 時の処理修正
296                 String   cmd  = request.getParameter( "command" );
297                 final String[] cmds = request.getParameterValues( "command" );
298                 if( cmds != null && cmds.length > 1 ) {
299                         for( int i=0; i<cmds.length; i++ ) {
300                                 if( ! "NEW".equals( cmds[i] ) ) {
301                                         cmd = cmds[i]; break;   // NEW でない、最初の一つ
302                                 }
303                         }
304                         // すべてが NEW の場合は、単体(getParameter) が NEW なので素通りでよい。
305                 }
306
307                 // 3.5.5.2 (2004/04/02) 選択行の件数
308                 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
309                 if( rows == null ) {
310                         rowCount = 0;
311                  }
312                 else {
313                         rowCount = rows.length;
314                         rowNo = Integer.parseInt( rows[0] );
315                 }
316                 // 3.7.0.1 (2005/01/31) リクエスト変数に選択された件数を追加
317                 setRequestAttribute( "ROW_COUNT",String.valueOf( rowCount ) );
318
319                 if( cmd == null || cmd.isEmpty() ) { cmd = "INIT"; }
320                 final String forwardPage;
321
322                 final String backPage = (String)session.getAttribute( HybsSystem.FORWARD_PAGE_KEY );
323                 String command  = cmd;          // 3.5.5.5 (2004/04/23)
324                 int    pagePlus = 0;
325
326                 // コマンドパラメータにより振分け
327                 // 5.1.8.0 (2010/07/01) VIEWの場合も、直前のJSPに遷移する。
328                 if( "FIRST,PREV,NEXT,LAST,VIEW".indexOf( cmd ) >= 0 ) {
329                         forwardPage = backPage;
330                 } else if( "NEW,RENEW".indexOf( cmd ) >= 0 ) {
331                         // 初期値
332                         forwardPage = "result.jsp";
333                 } else if( "INIT".equals( cmd ) ) {
334                         forwardPage = DUMMY_HTML;                       // 3.5.5.3 (2004/04/09)
335                 } else {
336                         // 共有オブジェクト検索
337
338                         // リンク元コマンド名取得
339                         // 3.5.5.5 (2004/04/23) 余計なボタン関連情報を転送しない為に、キーを変更します。
340                         command = request.getParameter( HybsSystem.NO_XFER_KEY + cmd + "CMD" );
341
342                         // 3.7.0.3 (2005/03/01) 指定の行番号まで画面をスクロールさせる機能を追加。
343                         if( rows != null && "ENTRY".equals( command ) ) {
344                                 setRequestCacheData( "SEL_ROW",String.valueOf( rowNo ) );
345                         }
346
347                         if( "RESET".equals( command ) ) { // RESET 時
348                                 forwardPage = "result.jsp";
349
350                                 // 6.4.5.2 (2016/05/06) UPLOADから呼ばれた場合は、RESET  は、command="RENEW" , displayMsg=" " にします。
351                                 if( Boolean.parseBoolean( request.getParameter( HybsSystem.USE_UPLOAD_KEY ) ) ) {
352                                         command = "RENEW";
353                                         setRequestAttribute( "displayMsg"," " );              // RESETなので、メッセージは出さない。
354                                         setRequestCacheData( "SEL_ROW"   ,null );               // RENEWで戻るため、以前に行選択があったら、そこに戻ってしまうため、クリアしておく。
355                                 }
356                         }
357                         else {
358                                 // リンク先取得
359                                 forwardPage = request.getParameter( HybsSystem.NO_XFER_KEY + cmd );
360                                 // INSERTとCOPYの場合のみ
361                                 if( "INSERT".equals( command ) || "COPY".equals( command ) ) {
362                                         if( rows != null ) { pagePlus = rows.length; }
363                                 }
364                         }
365                 }
366
367                 if( ! forwardPage.equals( backPage ) ) {
368                         session.setAttribute( HybsSystem.REVIEW_PAGE_KEY , backPage );
369                 }
370                 session.setAttribute( HybsSystem.FORWARD_PAGE_KEY, forwardPage );
371
372                 // 3.5.5.5 (2004/04/23) SubmitTag の keys,vals 属性で指定した値のみ、転送します。
373                 // 6.0.2.5 (2014/10/31) char を append する。
374                 final StringBuilder strURL = new StringBuilder( BUFFER_MIDDLE )
375                         .append( '&' ).append( "command"  ).append( '=' ).append( command )
376                         .append( '&' ).append( "pagePlus" ).append( '=' ).append( String.valueOf( pagePlus ) );
377
378                 final String btnKey = HybsSystem.NO_XFER_KEY + cmd + "KEY_" ;
379                 final int    keylen = btnKey.length() ;
380
381                 final Enumeration<?> enm = getParameterNames();         // 4.3.3.6 (2008/11/15) Generics警告対応
382
383                 // 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
384                 final Map<String,String> hiddenMap = new HashMap<>();
385                 boolean isGamenIdFlag = false;
386
387                 while( enm.hasMoreElements() ) {
388                         final String key = (String)( enm.nextElement() );
389                         // 3.5.5.5 (2004/04/23) 余計な情報を転送しない様に、キーを選別します。
390                         if( key != null && key.startsWith( btnKey ) ) {
391                                 // 3.5.5.8 (2004/05/20) 内部の仮想リクエスト Map に設定します。
392                                 final String kk = key.substring( keylen ) ;
393                                 final String vv = nval( getRequestValue( key ) , "" );                  // 6.4.3.1 (2016/02/12) ConcurrentHashMap の条件は、key,val ともに、not null
394                                 // 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
395                                 if( vv.length() > 2 && vv.charAt(0) == '[' && vv.charAt(vv.length()-1) == ']' ) {
396                                         submitTableMap.put( kk,vv.substring( 1,vv.length()-1 ));
397                                 }
398         //                      else if( "dbkeys".equals( kk ) ) {
399         //                              submitRequestMap.put( kk,vv );
400         //                      }
401                                 else {
402                                         submitRequestMap.put( kk,vv );
403                                         strURL.append( '&' )                                    // 6.0.2.5 (2014/10/31) char を append する。
404                                                 .append( kk ).append( '=' )                     // 6.0.2.5 (2014/10/31) char を append する。
405                                                 .append( StringUtil.urlEncode( vv ) );
406                                 }
407
408                                 // 3.8.0.8 (2005/10/03) BACK_GAMENID があれば BACK_ROW を追加する。
409                                 if( "BACK_GAMENID".equalsIgnoreCase( kk ) && rowNo >= 0 ) {
410                                         strURL.append( "&BACK_ROW=" ).append( rowNo );
411                                 }
412
413                                 // 6.2.4.0 (2015/05/15) 個別に GAMENID があれば、submitTag で指定されたはず。
414                                 if( "GAMENID".equalsIgnoreCase( kk ) ) {
415                                         isGamenIdFlag = true;
416                                 }
417                         }
418                         // 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
419                         // 取りあえず対象のリクエストは、Mapにセットしておきます。
420                         if( isRedirectHidden && key != null && !key.startsWith( "h_" ) && !key.startsWith( "hX_" ) ) {
421                                 hiddenMap.put( key,getRequestValue( key,false ) );
422                         }
423                 }
424
425                 // 6.2.4.0 (2015/05/15) useRedirectHidden 属性追加
426                 // 個別に GAMENID がある場合(isGamenIdFlag == true)のみ、このフラグを有効にします。
427                 if( isRedirectHidden && isGamenIdFlag ) {
428                         for( final Map.Entry<String,String> entry : hiddenMap.entrySet() ) {
429                                 final String key = '&' + entry.getKey() + '=';          // strURL は、必ず & で始まっている。
430                                 if( strURL.indexOf( key ) < 0 ) {                               // すでに、個別定義済みのパラメータは転送しない。
431                                         strURL.append( key ).append( StringUtil.urlEncode( entry.getValue() ) );
432                                 }
433                         }
434                 }
435
436                 return XHTMLTag.addUrlEncode( forwardPage,strURL.toString() );
437         }
438
439         /**
440          * ページを リダイレクトかフォワードか選択します。
441          * 判定条件は、拡張子や、選択件数などを加味して以下の判定を順次テストします。
442          *
443          *   FORWARD :
444          *       アドレスが、 null か、.jsp を含み、"/" が入っていない場合
445          *   REDIRECT:
446          *       アドレスが、.jsp を含まないか、それ以外(.jsp を含み、"/" も含む)で、選択数が1件のみの場合
447          *   COUNT_0 :
448          *       それ以外で、選択数が0件の場合
449          *   COUNT_N :
450          *       それ以外で、選択数が1件以上の場合、または、その他。
451          *
452          * @og.rev 3.5.5.2 (2004/04/02) 新規作成:isJspPrefix( String page ) の代用です。
453          * @og.rev 4.0.0.0 (2007/05/23) useTableData の書き換えを中止します。
454          * @og.rev 4.0.0.0 (2007/11/12) 非選択状態でもリダイレクト可能なフラグ(isRedirectCheck)を追加
455          *
456          * @param   page        判定する転送先アドレス
457          *
458          * @return  FORWARD,REDIRECT,COUNT_0,COUNT_N のうち、どれか
459          */
460         private int selectResponseMethod( final String page ) {
461                 if( page == null ) { return FORWARD; }
462
463                 final int adrs = page.indexOf( ".jsp" );
464
465                 if( adrs >= 0 && page.lastIndexOf( '/',adrs ) < 0 ) {
466                         return FORWARD;
467                 }
468                 else if( adrs < 0 || !isRedirectCheck ) { // 4.0.0.0 (2007/11/12) 非選択リダイレクト許可フラグ追加
469                         return REDIRECT;
470                 }
471                 else if( rowCount == 1 ) {
472                         return REDIRECT;
473                 }
474                 else if( rowCount == 0 ) {
475                         return COUNT_0;
476                 }
477                 else {
478                         return COUNT_N;
479                 }
480         }
481
482         /**
483          * 【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID
484          *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
485          *
486          * @og.tag
487          * 表示処理後に、(内部ポインタを書き換えた)DBTableModelオブジェクトを
488          * 同じキーで、sessionに登録します。
489          *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
490          *
491          * @og.rev 3.5.5.2 (2004/04/02) 新規追加
492          * @og.rev 3.5.5.8 (2004/05/20) 内部仮想リクエスト Map を参照できるようにする。
493          *
494          * @param       id テーブルID (sessionから所得する時のID)
495          */
496         public void setTableId( final String id ) {
497                 // 注意:引数のリクエスト変数が無ければ、自分自身({@XXX}形式)を再セットする。
498                 tableIdTemp   = nval( getRequestParameter( id ),id );
499         }
500
501         /**
502          * 指定のスコープの内部キャッシュ情報に、DBTableModel の選択された値を登録します。
503          *
504          * 複数選択行が存在する場合は、先頭行を処理します。ただし、action="APPEND"の
505          * 場合は、separator属性で指定された文字を使用して、連結します。
506          *
507          * @og.rev 3.5.5.2 (2004/04/02) 新規作成
508          * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
509          * @og.rev 3.8.0.4 (2005/08/08) dbkeys が null の場合に全件取得していた処理を中止します。
510          * @og.rev 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
511          * @og.rev 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
512          * @og.rev 3.8.5.1 (2006/04/28) dbkeys が null の場合に全件取得するかどうかを COMMON_FORWARD_DBKEYS_NULL_ALL で指定します。
513          * @og.rev 4.0.0.0 (2007/05/23) tableId をこのメソッド内で求めます。
514          *
515          * @return      DBTableModelの選択された値の文字列
516          * @og.rtnNotNull
517          */
518         private String getTableUrlData() {
519                 final String tableId = nval( getSubmitRequestParameter( tableIdTemp ),HybsSystem.TBL_MDL_KEY );
520
521                 final DBTableModel table = (DBTableModel)getSessionAttribute( tableId );
522
523                 String dbkeysUrl  = "";
524                 String tblkeysUrl = "";
525
526                 if( table != null ) {
527                         String[] keys = null;
528                         String[] vals = null;
529                         if( dbkeys != null ) {
530                                 keys = StringUtil.csv2Array( dbkeys );
531                                 vals = new String[keys.length];
532                                 for( int i=0; i<keys.length; i++ ) {
533                                         final int clmNo = table.getColumnNo( keys[i] );
534                                         vals[i] = table.getValue(rowNo,clmNo);
535                                 }
536                         }
537
538                         dbkeysUrl = XHTMLTag.urlEncode( keys, vals );
539
540                         // 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
541                         final int size = submitTableMap.size();
542                         if( size > 0 ) {
543                                 @SuppressWarnings("rawtypes")
544                                 final Map.Entry[] entry = submitTableMap.entrySet().toArray( new Map.Entry[size] );
545
546                                 String[] tblkeys = new String[size];
547                                 String[] tblvals = new String[size];
548
549                                 for( int i=0; i<size; i++ ) {
550                                         tblkeys[i]  = (String)entry[i].getKey();
551                                         final String temp = (String)entry[i].getValue();
552                                         final int clmNo = table.getColumnNo( temp );
553                                         tblvals[i] = table.getValue( rowNo,clmNo );
554                                 }
555                                 tblkeysUrl = XHTMLTag.urlEncode( tblkeys, tblvals );
556                         }
557                 }
558
559                 String rtn = dbkeysUrl;
560
561                 if( tblkeysUrl.length() > 0 ) {
562                         if( rtn.length() > 0 ) {
563                                 rtn += "&" + tblkeysUrl;
564                         }
565                         else {
566                                 rtn = tblkeysUrl ;
567                         }
568                 }
569                 return rtn ;
570         }
571
572         /**
573          * 【TAG】DBキーをCSV形式でセットします。
574          *
575          * @og.tag
576          * URI の引数にセットするキーを CSV形式でセットします。
577          * ここの指定は、DBTableModel 上のデータを取り込みます。
578          *
579          * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
580          * @og.rev 3.5.5.8 (2004/05/20) 内部仮想リクエスト Map を参照できるようにする。
581          *
582          * @param       key DBキー(CSV形式)
583          */
584         public void setDbkeys( final String key ) {
585                 // 注意:引数のリクエスト変数が無ければ、自分自身({@XXX}形式)を再セットする。
586                 dbkeysTemp = nval( getRequestParameter( key ),key ) ;
587         }
588
589         /**
590          * 内部の仮想リクエスト Map より、リクエストパラメータより値を設定します。
591          *
592          * submitタグの keys,vals より送信されたリクエスト値は、このクラスで
593          * 処理され、内部の仮想リクエスト Map に保存されます。
594          * 通常のリクエスト設定時点では、この値は取り出すことが出来ない為、
595          * Map に保存(getForwardURI 処理で設定)された後に、引き出します。
596          *
597          * @og.rev 3.5.5.8 (2004/05/20) 新規作成
598          *
599          * @param       key     DBキー(CSV形式)
600          *
601          * @return      仮想リクエスト Map を反映させた、リクエスト値
602          */
603         private String getSubmitRequestParameter( final String key ) {
604                 String rtn = key;
605
606                 // 変数が "{@XXXX}" の場合のみ対応
607                 if( key != null && key.startsWith( "{@" ) && key.charAt(key.length()-1) == '}' ) {
608                         rtn = submitRequestMap.get( key.substring( 2,key.length()-1 ) );
609                 }
610
611                 return rtn;
612         }
613
614         /**
615          * 【TAG】非選択状態の場合にforwardを許可するかどうか[true/false]を指定します(初期値:true)。
616          *
617          * @og.tag
618          * 初期値はtrueが設定されています
619          * falseにすると許可されます
620          *
621          * @og.rev 4.0.0.0 (2007/11/09) 新規作成
622          *
623          * @param       flag    非選択状態のforward許可 [true:不許可/false:許可]
624          */
625         public void setUseRedirectCheck(final String flag) {
626                 isRedirectCheck = nval( getRequestParameter( flag ),isRedirectCheck );
627         }
628
629         /**
630          * 【TAG】redirectの処理時に、hiddenパラメータを転送するかどうか[true:する/false:しない]を指定します(初期値:false)。
631          *
632          * @og.tag
633          * submitTag で、gamenId を指定すると、redirect されます。
634          * その場合、従来の画面では、hidden 属性が転送されていなかったため、
635          * 個別に keys,vals で指定する必要がありました。
636          * hidden で記述した値は、redirect でも転送できるようにします。
637          * なお、個別定義済みのパラメータがあり、hiddenパラメータを同じキーの場合は、
638          * 個別パラメータを優先し、hiddenパラメータは転送しません。
639          *
640          * 本来は、gamenId指定の submit の場合でも、必要最小限の値のみ転送すべきで、
641          * この値を true にするのは、過去のJSPソースを、修正せずに使いたいケースに限定してください。
642          * 互換性の関係で、初期値は、false にします。
643          *
644          * @og.rev 6.2.4.0 (2015/05/15) 新規作成
645          *
646          * @param       flag    非選択状態のforward許可 [true:不許可/false:許可]
647          */
648         public void setUseRedirectHidden(final String flag) {
649                 isRedirectHidden = nval( getRequestParameter( flag ),isRedirectHidden );
650         }
651
652         /**
653          * 【TAG】エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)。
654          *
655          * @og.tag
656          * 通常のエラーメッセージは、ラベル(長)が使われますが、これをラベル(短)を使いたい場合に、true にセットします。
657          * ここでのラベル(短)は、タグ修飾なしの、ラベル(短)です。
658          * 標準はfalse:利用しない=ラベル(長)です。
659          * true/false以外を指定した場合はfalse扱いとします。
660          *
661          * ラベルリソースの概要説明があれば表示しますが、useSLabel="true" 時は、概要説明を表示しません。
662          *
663          * @og.rev 7.0.7.0 (2019/12/13) 新規追加
664          *
665          * @param prm SLABEL利用 [true:利用する/false:利用しない]
666          */
667         public void setUseSLabel( final String prm ) {
668                 useSLabel = nval( getRequestParameter( prm ),useSLabel );
669         }
670
671         /**
672          * このオブジェクトの文字列表現を返します。
673          * 基本的にデバッグ目的に使用します。
674          *
675          * @return このクラスの文字列表現
676          * @og.rtnNotNull
677          */
678         @Override
679         public String toString() {
680                 return ToString.title( this.getClass().getName() )
681                                 .println( "VERSION"                             ,VERSION                        )
682                                 .println( "rowCount"                    ,rowCount                       )
683                                 .println( "rowNo"                               ,rowNo                          )
684                                 .println( "dbkeys"                              ,dbkeys                         )
685                                 .println( "tableIdTemp"                 ,tableIdTemp            )
686                                 .println( "dbkeysTemp"                  ,dbkeysTemp                     )
687                                 .println( "useRedirectCheck"    ,isRedirectCheck        )       // 6.2.4.0 (2015/05/15)
688                                 .println( "useRedirectHidden"   ,isRedirectHidden       )       // 6.2.4.0 (2015/05/15)
689                                 .println( "Other..."                    ,getAttributes().getAttribute() )
690                                 .fixForm().toString() ;
691         }
692 }