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.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.common.HybsSystemException;
020import org.opengion.hayabusa.db.DBTableModel;
021import org.opengion.fukurou.util.ErrorMessage;
022import org.opengion.fukurou.util.XHTMLTag;
023import org.opengion.fukurou.util.StringUtil;
024
025import static org.opengion.fukurou.util.StringUtil.nval ;
026
027import javax.servlet.http.HttpServletRequest;
028import javax.servlet.http.HttpServletResponse;
029import javax.servlet.http.HttpSession;
030import javax.servlet.ServletException;
031import java.io.IOException;
032import java.io.ObjectInputStream;
033import java.io.ObjectOutputStream;
034import java.util.Enumeration;
035import java.util.Map;
036import java.util.HashMap;
037
038/**
039 * submitタグを用いてページ転送するタグです(forward.jsp で使用)。
040 *
041 * 通常、forward は、ページ内転送(サーバー内部での転送)のため、別画面への遷移には
042 * 使用できません。これは、別画面では、index.jsp 等でフレーム分割する際の基準フォルダは、
043 * forward の場合、クライアントは理解していないため、もう一度先のフォルダに対する
044 * フレーム分割を行おうとするためです。
045 * (よく、index.jsp の frame タグに、src="../XXXX/query.jsp" などと、自分自身のフォルダ名を
046 * 記述したページを見かけますが、これは、フォルダをまたがる転送に、forward を使用する
047 * 為の悪い対策です。)
048 * 実際は、forward ではなく、redirect を使うべきです。redirect は、指定のアドレス要求を、
049 * 一旦クライアントに投げてそこから再度要求しなおしてもらう方式のため、このようにフォルダを
050 * またがる転送も正常に処理できます。
051 * この、commonForward タグでは、画面遷移の条件に応じて、forward か redirect の自動
052 * 判定を行い、適切に処理しています。
053 * 判定条件は、拡張子や、選択件数などを加味して以下の判定を順次テストします。
054 *
055 *   FORWARD :
056 *       アドレスが、 null(自分自身) か、.jsp を含み、"/" が入っていない場合
057 *   REDIRECT:
058 *       アドレスが、.jsp を含まないか、
059 *       それ以外(.jsp を含み、"/" も含む)で、選択数が1件のみの場合
060 *       もしくはuseRedirectCheck="false"の場合
061 *   COUNT_0 :
062 *       それ以外で、選択数が0件の場合
063 *   COUNT_N :
064 *       それ以外で、選択数が1件以上の場合、または、その他。
065 *
066 * ここで、COUNT_0 の場合は、未選択エラー、COUNT_N は、複数選択エラーを自動的に返します。
067 *
068 * @og.formSample
069 * ●形式:<og:commonForward />
070 * ●body:なし
071 *
072 * ●Tag定義:
073 *   <og:commonForward
074 *       dbkeys             【TAG】DBキーをCSV 形式でセットします
075 *       tableId            【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
076 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
077 *       useRedirectCheck   【TAG】非選択状態の場合にforwardを許可するかどうか[true/false]を指定します(初期値:true)
078 *   />
079 *
080 * ●使用例
081 *     フォワードキャッシュによりページ転送します。
082 *     <og:commonForward dbkeys="{@dbkeys}" />
083 *
084 * @og.group 画面制御
085 *
086 * @version  4.0
087 * @author       Masaharu Endo
088 * @since    JDK5.0,
089 */
090public class CommonForwardTag extends CommonTagSupport {
091        //* このプログラムのVERSION文字列を設定します。   {@value} */
092        private static final String VERSION = "5.3.6.0 (2011/06/01)" ;
093
094        private static final long serialVersionUID = 536020110601L ;    // 5.3.6.0 (2011/06/01)
095
096        // 3.5.5.3 (2004/04/09) 共通アドレスで指定することで、クライアントキャッシュを有効利用する。
097        private static final String DUMMY_HTML  = "/" + HybsSystem.getContextName() + "/jsp/common/dummy.html";
098
099        // 3.8.5.1 (2006/04/28) dbkeys が null の場合に全件取得するかどうかを COMMON_FORWARD_DBKEYS_NULL_ALL で指定します。
100
101        private static final int FORWARD  = 0;
102        private static final int REDIRECT = 1;
103        private static final int COUNT_0  = 2;
104        private static final int COUNT_N  = 3;
105
106        // 3.5.5.2 (2004/04/02) 選択行が、1行のみか、そうでないか
107        private int rowCount = -1;
108
109        // 3.5.5.2 (2004/04/02) 選択行の DBTableModel データを引数に使用するかどうか。
110//      private boolean useTableData = HybsSystem.sysBool( "COMMON_FORWARD_USE_TABLE_DATA" );
111//      private String  tableId          = HybsSystem.TBL_MDL_KEY;
112        private int             rowNo            = -1;
113
114        // 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
115        private String  dbkeys          = null;
116
117        // 3.5.5.8 (2004/05/20) submitタグの keys,vals を扱う 仮想リクエストMap
118//      private String  useTableTemp    = null;
119        private String  tableIdTemp             = null;
120        private String  dbkeysTemp              = null;
121        private transient Map<String,String>      submitRequestMap        = new HashMap<String,String>();   // 3.5.6.2 (2004/07/05)
122        private transient Map<String,String>      submitTableMap          = new HashMap<String,String>();   // 3.8.5.1 (2006/04/28)
123
124        // 4.0.0.0 (2007/11/09) 非選択状態でのforwardのための属性追加
125        private boolean isRedirectCheck         = true;
126
127        /**
128         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
129         *
130         * @og.rev 3.3.1.1 (2003/07/03) URLにリクエスト情報をURLエンコードして追加します。
131         * @og.rev 3.5.5.2 (2004/04/02) フォルダ外転送時は、1行以外選択は、エラーとします。
132         * @og.rev 3.5.5.3 (2004/04/09) デバッグ時は、転送しないようにします。
133         * @og.rev 3.8.0.4 (2005/08/08) requestUrlEncode 廃止
134         * @og.rev 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
135         * @og.rev 4.0.0.0 (2007/11/09) 非選択状態からの遷移を許可するフラグを追加(11/12に振り分け処理をselectResponseMethodに移動)
136         * @og.rev 5.0.0.2 (2009/09/15) XSS対応⇒チェックする
137         * @og.rev 5.3.6.0 (2011/06/01) エラーメッセージ変更(URLの振り分け処理時に...のメッセージは出力しない)
138         *
139         * @return      後続処理の指示
140         */
141        @Override
142        public int doEndTag() {
143                debugPrint();           // 4.0.0 (2005/02/28)
144
145                // useXssCheck( false ); // 5.0.0.2 (2009/09/15)
146
147                HttpServletRequest request  = ((HttpServletRequest)getRequest());
148                HttpSession session = pageContext.getSession();
149                String page = getForwardURI( request, session );
150
151                // 3.5.5.8 (2004/05/20) 内部仮想リクエストMap より値を取得
152//              useTableData = nval( getSubmitRequestParameter( useTableTemp ),useTableData );
153//              tableId          = nval( getSubmitRequestParameter( tableIdTemp  ),tableId );
154                dbkeys           = nval( getSubmitRequestParameter( dbkeysTemp   ),dbkeys );
155
156                HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
157
158                String errMsgKey = null;
159                try {
160                        // 3.5.5.2 (2004/04/02) 振り分け条件を判定するメソッドを通します。
161                        // このメソッドにより、useTableData が再設定されます。処理順に注意
162                        int flag = selectResponseMethod( page );
163
164                        // 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
165//                      if( rowCount == 1 && useTableData ) {
166                        if( rowCount == 1 && dbkeys != null ) {
167                                page = XHTMLTag.addUrlEncode( page,getTableUrlData() );
168                        }
169
170                        String url = response.encodeRedirectURL( page );
171                        // 3.8.0.8 (2005/10/03) GET時の URL の長さ制限チェック(最大文字数は 2,083 文字)
172                        if( url != null && url.length() >= HybsSystem.MAX_GET_LENGTH ) {
173                                String errMsg = "GET時の URL の長さは,最大2,083 文字です。"
174                                                        + " URL.length=" + url.length() + " , MAX_LENGTH=" + HybsSystem.MAX_GET_LENGTH ;
175                                throw new HybsSystemException( errMsg );
176                        }
177
178                        switch( flag ) {
179                                case FORWARD:   if( isDebug() ) { jspPrint( "FORWARD URL = [" + url + "]" ); }
180                                                                else { pageContext.forward( url ); }
181                                                                break;
182                                case REDIRECT:  // url = requestUrlEncode( url );               // 3.8.0.4 (2005/08/08)
183                                                                if( isDebug() ) { jspPrint( "REDIRECT URL = [" + url + "]" ); }
184                                                                else { response.sendRedirect( url ); }
185                                                                break;
186                                case COUNT_0:
187//                                                              if( isDebug() ) {
188//                                                                      jspPrint( "RedirectCheck = [" + isRedirectCheck + "]" );
189//                                                                      jspPrint( "FORWARD URL = [" + url + "]" );
190//                                                                      }
191//                                                              if( isRedirectCheck ) { errMsgKey = "ERR0028" ; } // 選択されていません。もう一度、選択しなおして下さい。
192//                                                              else{ response.sendRedirect( url );}    // 4.0.0.0 (2007/11/09) 非選択状態遷移フラグ追加
193                                                                errMsgKey = "ERR0028" ;  // 選択されていません。もう一度、選択しなおして下さい。
194                                                                break;
195                                default: errMsgKey = "ERR0029" ;        // 複数選択されました。1件のみ選択しなおして下さい。
196                                                                break;
197                        }
198
199                } catch ( IOException ex ) {
200                        // 5.3.6.0 (2011/06/01) エラーメッセージ表示変更
201//                      String errMsg = "URLの振り分け処理時に IOException が発生しました。 " + HybsSystem.CR
202//                                              + ex.getMessage();                                      // 5.1.8.0 (2010/07/01) errMsg 修正
203                        String errMsg = ex.getMessage();                                        // 5.1.8.0 (2010/07/01) errMsg 修正
204                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
205                } catch ( ServletException ex ) {
206                        // 5.3.6.0 (2011/06/01) エラーメッセージ表示変更
207//                      String errMsg = "URLの振り分け処理時に ServletException が発生しました。 " + HybsSystem.CR
208//                                              + ex.getMessage();                                      // 5.1.8.0 (2010/07/01) errMsg 修正
209                        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
213                // 3.5.5.2 (2004/04/02) フォルダ外転送時は、1行以外選択は、エラーとします。
214                if( errMsgKey != null ) {
215                        ErrorMessage errMsg = new ErrorMessage( "Row Count Error Maximal Error!" );
216                        errMsg.addMessage( 0,ErrorMessage.NG,errMsgKey );
217
218                        jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource() ) );
219                }
220
221                return( SKIP_PAGE );            // ページの残りの処理を行わない。
222        }
223
224        /**
225         * タグリブオブジェクトをリリースします。
226         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
227         *
228         * @og.rev 3.5.5.2 (2004/04/02) 新規追加(rowCount,useTableData)
229         * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
230         * @og.rev 3.8.5.1 (2006/04/28) URLに連結するDBTableModelのカラムを[カラム]形式で指定します。
231         *
232         */
233        @Override
234        protected void release2() {
235                super.release2();
236                rowCount     = -1;
237//              useTableData = HybsSystem.sysBool( "COMMON_FORWARD_USE_TABLE_DATA" );
238//              tableId          = HybsSystem.TBL_MDL_KEY;
239                rowNo            = -1;
240                dbkeys           = null;                // 3.5.5.5 (2004/04/23)
241                submitRequestMap        = new HashMap<String,String>();           // 3.5.5.8 (2004/05/20)
242                submitTableMap          = new HashMap<String,String>();           // 3.8.5.1 (2006/04/28)
243//              useTableTemp            = null;         // 3.5.5.8 (2004/05/20)
244                tableIdTemp                     = null;         // 3.5.5.8 (2004/05/20)
245                dbkeysTemp                      = null;         // 3.5.5.8 (2004/05/20)
246                isRedirectCheck         = true;         // 4.0.0.0 (2007/11/12)
247        }
248
249        /**
250         * フォワード先URIを取得します。
251         *
252         * @og.rev 3.1.2.0 (2003/04/07) ソースコード中の固定値を、定義ファイルを使用するように変更する。
253         * @og.rev 3.1.4.1 (2003/04/21) request.getQueryString() をaddUrlEncodeしている箇所を削除。
254         * @og.rev 3.1.7.0 (2003/05/02) コマンド RENEW で、forward した場合に、result.jsp に遷移するように修正。
255         * @og.rev 3.1.7.0 (2003/05/02) 画面IDのセットで、自画面を、BACK_GAMENID 、飛び先を、GAMENID にする。
256         * @og.rev 3.1.8.0 (2003/05/16) SubmitData クラスを利用するように変更。
257         * @og.rev 3.3.1.1 (2003/07/03) ForwardManager クラスの廃止。飛び先のキャッシュを廃止します。
258         * @og.rev 3.5.5.2 (2004/04/02) 選択行の件数を設定しておきます。
259         * @og.rev 3.5.5.3 (2004/04/09) dummy.html を static final で絶対パス指定します。
260         * @og.rev 3.5.5.4 (2004/04/15) メソッド内で使用していない、gamenId,jspID 変数を削除します。
261         * @og.rev 3.5.5.5 (2004/04/23) 余計なボタン関連情報を転送しない為に、キーを変更します。
262         * @og.rev 3.5.5.5 (2004/04/23) SubmitTag の keys,vals 属性で指定した値のみ、転送します。
263         * @og.rev 3.5.5.8 (2004/05/20) SubmitTag の keys,vals 属性で指定した値を、内部仮想リクエスト Mapにセットします。
264         * @og.rev 3.7.0.1 (2005/01/31) リクエスト変数に選択された件数を追加
265         * @og.rev 3.7.0.3 (2005/03/01) 指定の行番号まで画面をスクロールさせる機能を追加。
266         * @og.rev 3.8.0.8 (2005/10/03) BACK_GAMENID があれば BACK_ROW を追加する。
267         * @og.rev 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
268         * @og.rev 5.1.8.0 (2010/07/01) VIEWの場合も、直前のJSPに遷移する。
269         *
270         * @param       request HttpServletRequestオブジェクト
271         * @param       session HttpSessionオブジェクト
272         *
273         * @return      フォワード先URI
274         */
275        private String getForwardURI( final HttpServletRequest request,
276                                                                  final HttpSession        session ) {
277
278//              String   cmd    = request.getParameter( "command" );
279                String[] rows   = request.getParameterValues( HybsSystem.ROW_SEL_KEY );
280
281                // 4.0.0 (2007/05/16) query.jsp で複数command 時の処理修正
282                String   cmd  = request.getParameter( "command" );
283                String[] cmds = request.getParameterValues( "command" );
284                if( cmds != null && cmds.length > 1 ) {
285                        for( int i=0; i<cmds.length; i++ ) {
286                                if( ! "NEW".equals( cmds[i] ) ) {
287                                        cmd = cmds[i]; break;   // NEW でない、最初の一つ
288                                }
289                        }
290                        // すべてが NEW の場合は、単体(getParameter) が NEW なので素通りでよい。
291                }
292
293                // 3.5.5.2 (2004/04/02) 選択行の件数
294                if( rows != null ) {
295                        rowCount = rows.length;
296                        rowNo = Integer.parseInt( rows[0] );
297                }
298                else {
299                        rowCount = 0;
300                 }
301                // 3.7.0.1 (2005/01/31) リクエスト変数に選択された件数を追加
302                setRequestAttribute( "ROW_COUNT",String.valueOf( rowCount ) );
303
304                if( cmd == null || cmd.length() == 0 ) { cmd = "INIT"; }
305//              String forwardPage = "result.jsp" ;
306                final String forwardPage;
307
308                String backPage = (String)session.getAttribute( HybsSystem.FORWARD_PAGE_KEY );
309                String command  = cmd;          // 3.5.5.5 (2004/04/23)
310                int    pagePlus = 0;
311
312                // コマンドパラメータにより振分け
313                // 5.1.8.0 (2010/07/01) VIEWの場合も、直前のJSPに遷移する。
314//              if( "FIRST,PREV,NEXT,LAST".indexOf( cmd ) >= 0 ) {
315                if( "FIRST,PREV,NEXT,LAST,VIEW".indexOf( cmd ) >= 0 ) {
316                        forwardPage = backPage;
317//              } else if( "NEW,VIEW,RENEW".indexOf( cmd ) >= 0 ) {
318                } else if( "NEW,RENEW".indexOf( cmd ) >= 0 ) {
319                        // 初期値
320                        forwardPage = "result.jsp";
321                } else if( "INIT".equals( cmd ) ) {
322                        forwardPage = DUMMY_HTML;                       // 3.5.5.3 (2004/04/09)
323                } else {
324                        // 共有オブジェクト検索
325
326                        // リンク元コマンド名取得
327                        // 3.5.5.5 (2004/04/23) 余計なボタン関連情報を転送しない為に、キーを変更します。
328                        command = request.getParameter( HybsSystem.NO_XFER_KEY + cmd + "CMD" );
329
330                        // 3.7.0.3 (2005/03/01) 指定の行番号まで画面をスクロールさせる機能を追加。
331                        if( rows != null && "ENTRY".equals( command ) ) {
332                                setRequestCacheData( "SEL_ROW",String.valueOf( rowNo ) );
333                        }
334
335                        if( "RESET".equals( command ) ) { // RESET 時
336                                forwardPage = "result.jsp";
337                        }
338                        else {
339                                // リンク先取得
340                                forwardPage = request.getParameter( HybsSystem.NO_XFER_KEY + cmd );
341                                // INSERTとCOPYの場合のみ
342                                if( "INSERT".equals( command ) || "COPY".equals( command ) ) {
343                                        if( rows != null ) { pagePlus = rows.length; }
344                                }
345                        }
346
347//                      // リンク先取得
348//                      forwardPage = request.getParameter( HybsSystem.NO_XFER_KEY + cmd );
349//
350//                      // INSERTとCOPYの場合のみ
351//                      if( "INSERT".equals( command ) || "COPY".equals( command ) ) {
352//                              if( rows != null ) { pagePlus = rows.length; }
353//                      }
354//                      else if( "RESET".equals( command ) ) { // RESET 時
355//                              forwardPage = "result.jsp";
356//                      }
357                }
358
359                if( ! forwardPage.equals( backPage ) ) {
360                        session.setAttribute( HybsSystem.REVIEW_PAGE_KEY , backPage );
361                }
362                session.setAttribute( HybsSystem.FORWARD_PAGE_KEY, forwardPage );
363
364                // 3.5.5.5 (2004/04/23) SubmitTag の keys,vals 属性で指定した値のみ、転送します。
365                StringBuilder strURL = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
366                strURL.append( "&" ).append( "command" ).append( "=" ).append( command );
367                strURL.append( "&" ).append( "pagePlus" ).append( "=" ).append( String.valueOf( pagePlus ) );
368
369                String btnKey = HybsSystem.NO_XFER_KEY + cmd + "KEY_" ;
370                int    keylen = btnKey.length() ;
371
372                Enumeration<?> enm = getParameterNames();         // 4.3.3.6 (2008/11/15) Generics警告対応
373
374                while( enm.hasMoreElements() ) {
375                        String key = (String)( enm.nextElement() );
376                        // 3.5.5.5 (2004/04/23) 余計な情報を転送しない様に、キーを選別します。
377                        if( key != null && key.startsWith( btnKey ) ) {
378                                // 3.5.5.8 (2004/05/20) 内部の仮想リクエスト Map に設定します。
379                                String kk = key.substring( keylen ) ;
380                                String vv = getRequestValue(key) ;
381                                // 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
382                                if( vv != null && vv.length() > 2 && vv.charAt(0) == '[' && vv.charAt(vv.length()-1) == ']' ) {
383                                        submitTableMap.put( kk,vv.substring( 1,vv.length()-1 ));
384                                }
385        //                      else if( "dbkeys".equals( kk ) ) {
386        //                              submitRequestMap.put( kk,vv );
387        //                      }
388                                else {
389                                        submitRequestMap.put( kk,vv );
390                                        strURL.append( "&" );
391                                        strURL.append( kk ).append( "=" );
392                                        strURL.append( StringUtil.urlEncode( vv ) );
393                                }
394
395                                // 3.8.0.8 (2005/10/03) BACK_GAMENID があれば BACK_ROW を追加する。
396                                if( "BACK_GAMENID".equalsIgnoreCase( kk ) && rowNo >= 0 ) {
397                                        strURL.append( "&BACK_ROW=" );
398                                        strURL.append( rowNo );
399                                }
400                        }
401                }
402
403                return XHTMLTag.addUrlEncode( forwardPage,strURL.toString() );
404        }
405
406        /**
407         * ページを リダイレクトかフォワードか選択します。
408         * 判定条件は、拡張子や、選択件数などを加味して以下の判定を順次テストします。
409         *
410         *   FORWARD :
411         *       アドレスが、 null か、.jsp を含み、"/" が入っていない場合
412         *   REDIRECT:
413         *       アドレスが、.jsp を含まないか、それ以外(.jsp を含み、"/" も含む)で、選択数が1件のみの場合
414         *   COUNT_0 :
415         *       それ以外で、選択数が0件の場合
416         *   COUNT_N :
417         *       それ以外で、選択数が1件以上の場合、または、その他。
418         *
419         * @og.rev 3.5.5.2 (2004/04/02) 新規作成:isJspPrefix( String page ) の代用です。
420         * @og.rev 4.0.0.0 (2007/05/23) useTableData の書き換えを中止します。
421         * @og.rev 4.0.0.0 (2007/11/12) 非選択状態でもリダイレクト可能なフラグ(isRedirectCheck)を追加
422         *
423         * @param   page        判定する転送先アドレス
424         *
425         * @return  FORWARD,REDIRECT,COUNT_0,COUNT_N のうち、どれか
426         */
427        private int selectResponseMethod( final String page ) {
428                if( page == null ) { return FORWARD; }
429
430                int adrs = page.indexOf( ".jsp" );
431
432                if( adrs >= 0 && page.lastIndexOf( '/',adrs ) < 0 ) {
433//                      useTableData = false;           // 現時点での forward では、使用できません。
434                        return FORWARD;
435                }
436//              else if( adrs < 0 || !useTableData ) {
437//              else if( adrs < 0 ) {
438                else if( adrs < 0 || !isRedirectCheck ) { // 4.0.0.0 (2007/11/12) 非選択リダイレクト許可フラグ追加
439//                      useTableData = false;           //      jsp 以外では、使用できません。
440                        return REDIRECT;
441                }
442                else if( rowCount == 1 ) {
443                        return REDIRECT;
444                }
445                else if( rowCount == 0 ) {
446                        return COUNT_0;
447                }
448                else {
449                        return COUNT_N;
450                }
451        }
452
453        /**
454         * 【TAG】選択行データを、URL 引数に追加する(true)かどうかを指定します(初期値:false)。
455         *
456         * @og.tag
457         * 選択された DBTableModel の 行データをそのまま、URL の 引数に追加して
458         *      転送するかどうかを指定できるフラグ、useTableData 属性を追加します。
459         *      初期値は、false (互換性の為)です。
460         *      なお、SubmitTag(サブミットボタンタグ)で、gamenIdが指定された場合、
461         *      つまり、他のフォルダにリクエストされた場合のみ、有効になります。
462         *      自分自身のフォルダ内では、forward が使用されるため、使えません。
463         *
464         * @og.rev 3.5.5.2 (2004/04/02) 新規追加
465         * @og.rev 3.5.5.8 (2004/05/20) 内部仮想リクエスト Map を参照できるようにする。
466         *
467         * @param       flag 選択行データを使用する(true)/しない(false)
468         */
469//      public void setUseTableData( final String flag ) {
470//              useTableTemp = nval( getRequestParameter( flag ),useTableTemp );
471//      }
472
473        /**
474         * 【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
475         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
476         *
477         * @og.tag
478         * 表示処理後に,(内部ポインタを書き換えた)DBTableModelオブジェクトを
479         * 同じキーで、sessionに登録します。
480         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
481         *
482         * @og.rev 3.5.5.2 (2004/04/02) 新規追加
483         * @og.rev 3.5.5.8 (2004/05/20) 内部仮想リクエスト Map を参照できるようにする。
484         *
485         * @param       id sessionから所得する時の ID
486         */
487        public void setTableId( final String id ) {
488                // 注意:引数のリクエスト変数が無ければ、自分自身({@XXX}形式)を再セットする。
489                tableIdTemp   = nval( getRequestParameter( id ),id );
490        }
491
492        /**
493         * 指定のスコープの内部キャッシュ情報に、DBTableModel の選択された値を登録します。
494         *
495         * 複数選択行が存在する場合は、先頭行を処理します。ただし、action="APPEND"の
496         * 場合は、separator属性で指定された文字を使用して、連結します。
497         *
498         * @og.rev 3.5.5.2 (2004/04/02) 新規作成
499         * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
500         * @og.rev 3.8.0.4 (2005/08/08) dbkeys が null の場合に全件取得していた処理を中止します。
501         * @og.rev 3.8.0.8 (2005/10/03) dbkeys が null の場合に全件取得していた処理を復活します。
502         * @og.rev 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
503         * @og.rev 3.8.5.1 (2006/04/28) dbkeys が null の場合に全件取得するかどうかを COMMON_FORWARD_DBKEYS_NULL_ALL で指定します。
504         * @og.rev 4.0.0.0 (2007/05/23) tableId をこのメソッド内で求めます。
505         *
506         * @return      DBTableModelの選択された値の文字列
507         */
508        private String getTableUrlData() {
509                String tableId = nval( getSubmitRequestParameter( tableIdTemp ),HybsSystem.TBL_MDL_KEY );
510
511                DBTableModel table = (DBTableModel)getSessionAttribute( tableId );
512
513                String dbkeysUrl  = "";
514                String tblkeysUrl = "";
515
516                if( table != null ) {
517                        String[] keys = null;
518                        String[] vals = null;
519                        if( dbkeys != null ) {
520                                keys = StringUtil.csv2Array( dbkeys );
521                                vals = new String[keys.length];
522                                for( int i=0; i<keys.length; i++ ) {
523                                        int clmNo = table.getColumnNo( keys[i] );
524                                        vals[i] = table.getValue(rowNo,clmNo);
525                                }
526                        }
527
528                        dbkeysUrl = XHTMLTag.urlEncode( keys, vals );
529
530                        // 3.8.5.1 (2006/04/28) vals="[カラム名]" という引数を処理できる機能を追加。
531                        int size = submitTableMap.size();
532                        if( size > 0 ) {
533                                @SuppressWarnings("rawtypes")
534                                Map.Entry[] entry = submitTableMap.entrySet().toArray( new Map.Entry[size] );
535
536                                String[] tblkeys = new String[size];
537                                String[] tblvals = new String[size];
538
539                                for( int i=0; i<size; i++ ) {
540                                        tblkeys[i]  = (String)entry[i].getKey();
541                                        String temp = (String)entry[i].getValue();
542                                        int clmNo = table.getColumnNo( temp );
543                                        tblvals[i] = table.getValue( rowNo,clmNo );
544                                }
545                                tblkeysUrl = XHTMLTag.urlEncode( tblkeys, tblvals );
546                        }
547                }
548
549                String rtn = dbkeysUrl;
550
551                if( tblkeysUrl.length() > 0 ) {
552                        if( rtn.length() > 0 ) {
553                                rtn += "&" + tblkeysUrl;
554                        }
555                        else {
556                                rtn = tblkeysUrl ;
557                        }
558                }
559                return rtn ;
560        }
561
562        /**
563         * 【TAG】DBキーをCSV 形式でセットします。
564         *
565         * @og.tag
566         * URI の引数にセットするキーを CSV 形式でセットします。
567         * ここの指定は,DBTableModel 上のデータを取り込みます。
568         *
569         * @og.rev 3.5.5.5 (2004/04/23) URLに連結するDBTableModelのカラムをCSV形式で指定します。
570         * @og.rev 3.5.5.8 (2004/05/20) 内部仮想リクエスト Map を参照できるようにする。
571         *
572         * @param       key DBキー(CSV 形式)
573         */
574        public void setDbkeys( final String key ) {
575                // 注意:引数のリクエスト変数が無ければ、自分自身({@XXX}形式)を再セットする。
576                dbkeysTemp = nval( getRequestParameter( key ),key ) ;
577        }
578
579        /**
580         * 内部の仮想リクエスト Map より、リクエストパラメータより値を設定します。
581         *
582         * submitタグの keys,vals より送信されたリクエスト値は、このクラスで
583         * 処理され、内部の仮想リクエスト Map に保存されます。
584         * 通常のリクエスト設定時点では、この値は取り出すことが出来ない為、
585         * Map に保存(getForwardURI 処理で設定)された後に、引き出します。
586         *
587         * @og.rev 3.5.5.8 (2004/05/20) 新規作成
588         *
589         * @param       key        DBキー(CSV 形式)
590         *
591         * @return      仮想リクエスト Map を反映させた、リクエスト値
592         */
593        private String getSubmitRequestParameter( final String key ) {
594                String rtn = key;
595
596                // 変数が "{@XXXX}" の場合のみ対応
597                if( key != null && key.startsWith( "{@" ) && key.charAt(key.length()-1) == '}' ) {
598                        rtn = submitRequestMap.get( key.substring( 2,key.length()-1 ) );
599                }
600
601                return rtn;
602        }
603
604        /**
605         * 【TAG】非選択状態の場合にforwardを許可するかどうか[true/false]を指定します(初期値:true)。
606         *
607         * @og.tag
608         * 初期値はtrueが設定されています
609         * falseにすると許可されます
610         *
611         * @og.rev 4.0.0.0 (2007/11/09) 新規作成
612         *
613         * @param       flag    非選択状態のforwardを許可 [true:不許可/false:許可]
614         */
615        public void setUseRedirectCheck(final String flag) {
616                isRedirectCheck = nval( getRequestParameter( flag ),isRedirectCheck );
617        }
618
619//      private boolean isUseRedirectCheck() {
620//              return isRedirectCheck;
621//      }
622
623        /**
624         * シリアライズ用のカスタムシリアライズ書き込みメソッド
625         *
626         * @og.rev 4.3.1.1 (2008/08/23) 新規追加
627         * @serialData 一部のオブジェクトは、シリアライズされません。
628         *
629         * @param       strm    ObjectOutputStreamオブジェクト
630         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
631         */
632        private void writeObject( final ObjectOutputStream strm ) throws IOException {
633                strm.defaultWriteObject();
634        }
635
636        /**
637         * シリアライズ用のカスタムシリアライズ読み込みメソッド
638         *
639         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
640         *
641         * @og.rev 4.3.1.1 (2008/08/23) 新規追加
642         * @serialData 一部のオブジェクトは、シリアライズされません。
643         *
644         * @param       strm    ObjectInputStreamオブジェクト
645         * @see #release2()
646         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
647         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
648         */
649        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
650                strm.defaultReadObject();
651                submitRequestMap        = new HashMap<String,String>();
652                submitTableMap          = new HashMap<String,String>();
653        }
654
655        /**
656         * このオブジェクトの文字列表現を返します。
657         * 基本的にデバッグ目的に使用します。
658         *
659         * @return このクラスの文字列表現
660         */
661        @Override
662        public String toString() {
663                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
664                                .println( "VERSION"                     ,VERSION                )
665                                .println( "rowCount"            ,rowCount               )
666//                              .println( "useTableData"        ,useTableData   )
667//                              .println( "tableId"                     ,tableId                )
668                                .println( "rowNo"                       ,rowNo                  )
669                                .println( "dbkeys"                      ,dbkeys                 )
670//                              .println( "useTableTemp"        ,useTableTemp   )
671                                .println( "tableIdTemp"         ,tableIdTemp    )
672                                .println( "dbkeysTemp"          ,dbkeysTemp             )
673                                .println( "Other..."            ,getAttributes().getAttribute() )
674                                .fixForm().toString() ;
675        }
676}