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.hayabusa.resource.GUIInfo;
022import org.opengion.fukurou.util.XHTMLTag;
023import org.opengion.fukurou.util.StringUtil;
024
025import static org.opengion.fukurou.util.StringUtil.nval ;
026
027import java.io.ObjectOutputStream;
028import java.io.ObjectInputStream;
029import java.io.IOException;
030
031/**
032 * フレームを作成するHTML拡張タグで、引数の受け渡しが可能です。
033 *
034 * @og.formSample
035 * ●形式:<og:frame src="…" name="…" />
036 * ●body:なし
037 *
038 * ●Tag定義:
039 *   <og:frame
040 *       src              ○【HTML】フレームに表示するソースファイルを指定します(必須)。
041 *       name             ○【HTML】フレーム名を指定します(例:QUERY,RESULT,CONTENTS など)(必須)。
042 *       changeGamen        【TAG】ソース指定の画面を変更します
043 *       keys               【TAG】引数を指定します
044 *       dbTable            【TAG】前ページで選択したデータ列の情報を次のページに渡すかどうか[true/false]を指定します(初期値:false)
045 *       longdesc           【HTML】フレームに関する詳しい説明のあるURL(lobgdesc)を指定します
046 *       marginwidth        【HTML】フレームの左右余白サイズ(marginwidth)を指定します
047 *       marginheight       【HTML】フレームの上下余白サイズ(marginheight)を指定します
048 *       noresize           【HTML】フレームサイズを変更できないよう(noresize)に指定します
049 *       scrolling          【HTML】スクロールバー(scrolling)の表示/非表示[auto/yes/no]を指定します(初期値:auto)
050 *       frameborder        【HTML】フレームの境界線(frameborder)の[0:非表示/1:表示]を指定します(初期値:1)
051 *       id                 【HTML】要素に対して固有の名前(id)をつける場合に設定します
052 *       clazz              【HTML】要素に対して class 属性を設定します
053 *       title              【HTML】要素に対する補足的情報(title)を設定します
054 *       style              【HTML】この要素に対して適用させるスタイルシート(style)を設定します
055 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 5.7.7.2 (2014/06/20)
056 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 5.7.7.2 (2014/06/20)
057 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
058 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
059 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
060 *   />
061 *
062 * ●使用例:
063 *    ・一般的な例:フレーム分割する構文は、HTML準拠。リクエスト変数は各フレームまで転送されます。
064 *    <frameset>
065 *        <og:frame marginheight="2" marginwidth="2" src="query.jsp"   name="QUERY"  />
066 *        <og:frame marginheight="2" marginwidth="2" src="forward.jsp" name="RESULT" />
067 *    </frameset>
068 *
069 *    ・DBTableModel の値(例ではPN)を、取り出して、リクエスト変数として利用します。
070 *      現状では、commonForward タグ の useTableData="true" dbkeys="{@dbkeys}" 属性を利用します。
071 *    <frameset>
072 *        <og:frame marginheight="2" marginwidth="2" src="query.jsp"   name="QUERY"  keys="PN" dbTable="true" />
073 *        <og:frame marginheight="2" marginwidth="2" src="forward.jsp" name="RESULT" keys="PN" dbTable="true" />
074 *    </frameset>
075 *
076 *    ・changeGamen 属性を利用して、ソース指定の画面を切り替えます。
077 *      たとえば、jsp/index.jsp では、GAMENID属性がURLに存在する場合、直接その画面を
078 *      表示させることができます。
079 *    <frameset cols="160,*,0" frameborder="1" framespacing="1">
080 *        <og:frame marginheight="2" marginwidth="2" src="menu/menu.jsp"    name="MENU" />
081 *        <og:frame marginheight="2" marginwidth="2" src="GE0000/index.jsp" name="CONTENTS"
082 *                                                    changeGamen="{@GAMENID}" />
083 *    </frameset>
084 *
085 * @og.group 画面部品
086 *
087 * @version  4.0
088 * @author       Kazuhiko Hasegawa
089 * @since    JDK5.0,
090 */
091public class FrameTag extends HTMLTagSupport {
092        //* このプログラムのVERSION文字列を設定します。   {@value} */
093        private static final String VERSION = "4.2.1.1 (2008/04/30)" ;
094
095        private static final long serialVersionUID = 421120080430L ;
096
097        private String                  tableId         = HybsSystem.TBL_MDL_KEY;
098//      private String                  changeGmn       = null;
099        protected       String          changeGmn       = null; // 5.9.1.2 (2015/10/23)
100        private String                  keys            = null;
101        private transient DBTableModel  table           = null;
102//      private boolean                 dbTable         = false;
103        protected       boolean         dbTable         = false; // 5.9.1.2 (2015/10/23)
104
105        // 3.5.2.0 (2003/10/20) システムパラメータ の FRAME_UNDER_BAR_REQUEST_KEY_USED を使用。
106        private final boolean UNDER_BAR_KEY_USED = HybsSystem.sysBool( "FRAME_UNDER_BAR_REQUEST_KEY_USED" );
107
108        /**
109         * タグリブオブジェクトをリリースします。
110         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
111         *
112         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
113         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
114         *
115         */
116        @Override
117        protected void release2() {
118                super.release2();
119                tableId         = HybsSystem.TBL_MDL_KEY;
120                changeGmn       = null;         // 4.0.0 (2005/02/28)
121                keys            = null;
122                table           = null;
123                dbTable         = false;
124        }
125
126        /**
127         * リンクを作成します。
128         *
129         * @og.rev 3.5.4.0 (2003/11/25) comand="RENEW" 時には、dbTable 属性は、強制的に false とします。
130         *
131         * @return      リンクタグ文字列
132         */
133        @Override
134        protected String makeTag() {
135                if( changeGmn != null ) { set( "src",changeGmn ); }
136
137                String cmd = getRequest().getParameter( "command" );
138                if( "RENEW".equals( cmd ) ) { dbTable = false; }
139
140                setIdName();
141                String urlEnc = getUrlEncode();
142                return XHTMLTag.frame( getAttributes(),urlEnc );
143        }
144
145        /**
146         * id 属性 / name 属性 セット
147         *
148         * フレーム名は id 属性で登録する(XHTML) 互換性のため、
149         * id 属性と name 属性には同じ値をセットしておく。
150         * 
151         * @og.rev 5.9.1.2 (2015/10/23) 継承先のiframeタグで利用するためprivateからprotectedに
152         *
153         */
154//      private void setIdName() {
155        protected void setIdName() {
156                String idno     = get( "id" );
157                String name = get( "name" );
158                if( idno == null || idno.length() == 0 ) {
159                        if( name != null && name.length() > 0 ) {
160                                set( "id", name );
161                        }
162                        else {
163                                String errMsg = "id 属性か name 属性のどちらかは登録してください。";
164                                throw new HybsSystemException( errMsg );
165                        }
166                }
167                else {
168                        set( "name", idno );
169                }
170        }
171
172        /**
173         * keys 属性 を元に、request情報より values の値を取り込む。
174         *
175         * keys属性は キー情報がカンマ区切りになっている為,ばらして
176         * values属性の配列に一つづつ設定していきます。
177         *
178         * @og.rev 2.0.0.2 (2002/09/24) 検索結果の値を取り込めていなかったバグを修正。
179         * @og.rev 2.1.1.1 (2002/11/15) 選択行情報を取り込めていなかったバグを修正。
180         * @og.rev 3.4.0.3 (2003/09/10) DBTableModelへのリクエスト情報をURLに連結しないように変更。
181         * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
182         * @og.rev 5.9.1.2 (2015/10/23) 継承先のiframeタグで利用するためprivateからprotectedに
183         *
184         * @return      URLエンコードされた文字列
185         */
186//      private String getUrlEncode() {
187        protected String getUrlEncode() {
188                int[] rowNo = getParameterRows();               // 4.0.0 (2005/01/31)
189                int selcount = rowNo.length;    // 4.0.0 (2005/01/31)
190
191                String[] key = (String[])StringUtil.enume2Array( getParameterNames(), new String[0] );
192                String[] dbkey = null;
193
194                int dbcount = 0;
195
196                int recount = 0;
197                for( int i=0; i<key.length; i++ ) {
198                        if( isNormalRequestKey( key[i] ) ) {    // 3.4.0.3 (2003/09/10)
199                                recount++;
200                        }
201                }
202
203                if( keys != null && dbTable && selcount > 0 ) {
204                        dbkey = StringUtil.csv2Array( keys );
205                        dbcount = dbkey.length;
206                }
207
208                String[] val  = new String[ recount + dbcount + selcount ];
209                String[] keyt = new String[ recount + dbcount + selcount ];
210
211                int j = 0;
212                for( int i=0; i<key.length; i++ ) {
213                        if( isNormalRequestKey( key[i] ) ) {    // 3.4.0.3 (2003/09/10)
214                                keyt[j] = key[i];
215                                val[j]  = getRequestValue( key[i] );
216                                j++;
217                        }
218                }
219
220                if( dbTable && dbcount > 0 ) {
221                        table = (DBTableModel)getSessionAttribute( tableId );
222                        if( table != null ) {
223                                for( int i=0; i<dbcount; i++ ) {
224                                        keyt[recount + i] = dbkey[i];
225                                        val[recount +i]  = table.getValue(rowNo[0],table.getColumnNo( dbkey[i] ));
226                                }
227                        }
228                }
229
230                // 4.0.0 (2005/01/31) selected文字配列をrowNo数字配列に変更
231                for( int i=0; i<selcount; i++ ) {
232                        keyt[recount + dbcount + i] = HybsSystem.ROW_SEL_KEY;
233                        val[recount + dbcount + i]      = String.valueOf( rowNo[i] );
234                }
235
236                return XHTMLTag.urlEncode( keyt,val );
237        }
238
239        /**
240         * 【HTML】フレームに表示するソースファイルを指定します。
241         *
242         * @og.tag フレームに表示するソースファイルを指定します。
243         *
244         * @param       src ソースファイル
245         */
246        public void setSrc( final String src ) {
247                set( "src",getRequestParameter( src ) );
248        }
249
250        /**
251         * 【HTML】フレーム名を指定します(例:QUERY,RESULT,CONTENTS など)。
252         *
253         * @og.tag フレーム名を指定します。
254         *
255         * @param       name フレーム名
256         */
257        public void setName( final String name ) {
258                set( "name",getRequestParameter( name ) );
259        }
260
261        /**
262         * 【HTML】フレームに関する詳しい説明のあるURL(lobgdesc)を指定します。
263         *
264         * @og.tag lobgdescを指定します。
265         *
266         * @param       longdesc 詳しい説明のあるURL
267         */
268        public void setLongdesc( final String longdesc ) {
269                set( "longdesc",getRequestParameter( longdesc ) );
270        }
271
272        /**
273         * 【HTML】フレームの左右余白サイズ(marginwidth)を指定します。
274         *
275         * @og.tag フレームの左右余白サイズを指定します。
276         *
277         * @param       marginwidth 左右余白サイズ
278         */
279        public void setMarginwidth( final String marginwidth ) {
280                set( "marginwidth",getRequestParameter( marginwidth ) );
281        }
282
283        /**
284         * 【HTML】フレームの上下余白サイズ(marginheight)を指定します。
285         *
286         * @og.tag フレームの上下余白サイズを指定します。
287         *
288         * @param       marginheight 上下余白サイズ
289         */
290        public void setMarginheight( final String marginheight ) {
291                set( "marginheight",getRequestParameter( marginheight ) );
292        }
293
294        /**
295         * 【HTML】フレームサイズを変更できないよう(noresize)に指定します。
296         *
297         * @og.tag フレームサイズを変更できないように指定します。
298         *
299         * @param       noresize フレームサイズを変更させない場合は、"noresize" を指定します。
300         */
301        public void setNoresize( final String noresize ) {
302                String ns = getRequestParameter( noresize );
303                if( ns != null ) { set( "noresize", "noresize" ); }
304        }
305
306        /**
307         * 【HTML】スクロールバー(scrolling)の表示/非表示[auto/yes/no]を指定します(初期値:auto)。
308         *
309         * @og.tag
310         * auto:必要に応じてスクロールバーを表示(初期値)
311         * yes:常にスクロールバーを表示
312         * no:常にスクロールバーを表示しない
313         *
314         * @param       scrolling  スクロールバーの表示/非表示[auto:自動/yes:常時表示/no:非表示]
315         */
316        public void setScrolling( final String scrolling ) {
317                set( "scrolling",getRequestParameter( scrolling ) );
318        }
319
320        /**
321         * 【HTML】フレームの境界線(frameborder)の[0:非表示/1:表示]を指定します(初期値:1)。
322         *
323         * @og.tag
324         * 0:枠を表示しない
325         * 1:枠を表示する。
326         * 初期値は、1:枠を表示する です。
327         *
328         * @param       frameborder     フレームの境界線[0:枠非表示/1:枠表示]
329         */
330        public void setFrameborder( final String frameborder ) {
331                set( "frameborder",getRequestParameter( frameborder ) );
332        }
333
334        /**
335         * 【TAG】ソース指定の画面を変更します。
336         *
337         * @og.tag
338         * src 指定がデフォルト設定で、changeGamen属性が設定されている
339         * 場合には、この値が優先されます。
340         * changeGamen は、画面IDのみ指定してください。src には、このID+"/index.jsp" が
341         * 追加されます。つまり、changeGamen="{&#064;GAMENID}" という指定をしておけば、
342         * FavoriteLinkTag 等で引数に GAMENID が指定された場合のみ、この属性が有効になり、
343         * src="実画面ID/index.jsp" が指定されたことと同じ結果になります。
344         *
345         * @og.rev 3.1.2.0 (2003/04/07) 画面IDと実画面ディレクトリとの関連見直し(DIRの代りにGAMENIDを推奨)
346         * @og.rev 4.2.1.1 (2008/04/30) 画面切り替えをするのは、アドレスが設定されいる場合に限る
347         * @param       src     置換えソース
348         */
349        public void setChangeGamen( final String src ) {
350                String sc = nval( getRequestParameter( src ),changeGmn );
351                if( sc != null ) {
352                        GUIInfo guiInfo = getGUIInfo( sc );
353                        if( guiInfo != null && guiInfo.getAddress() != null && guiInfo.getAddress().length() > 0 ) { // 見つからない場合は、アクセス不可
354                                changeGmn = guiInfo.getRealAddress( "index.jsp" );
355                        }
356                }
357        }
358
359        /**
360         * 【TAG】引数を指定します。
361         *
362         * @og.tag
363         * URL の引数にセットするキーを カンマ区切りでセットします。
364         *
365         * @param       key 引数
366         */
367        public void setKeys( final String key ) {
368                keys = getRequestParameter( key ) ;
369        }
370
371        /**
372         * 【TAG】前ページで選択したデータ列の情報を次のページに渡すかどうか[true/false]を指定します(初期値:false)。
373         *
374         * @og.tag
375         * ただし、1行分のデータのみです。(複数選択時は、最初の1件目)
376         * true:渡す
377         * false:渡さない。
378         * 初期値は、false:渡さない です。
379         *
380         * @param       db 選択データを次のページに渡すかどうか[true:渡す/false:渡さない]
381         */
382        public void setDbTable( final String db ) {
383                dbTable = nval( getRequestParameter( db ),dbTable );
384        }
385
386        /**
387         * 標準的な リクエスト情報かどうかを判断します。
388         *
389         * これは、引数のキーが、HybsSystem.ROW_SEL_KEY か、
390         * DBTableModel で送信されたキー( キー__番号)形式の場合は
391         * false を返します。
392         * 通常のリクエストキーとして扱いたくない場合の判定に使用します。
393         *
394         * @og.rev 3.4.0.3 (2003/09/10) 新規追加
395         * @og.rev 3.5.2.0 (2003/10/20) システムパラメータ の FRAME_UNDER_BAR_REQUEST_KEY_USED を使用。
396         * @og.rev 3.5.5.0 (2004/03/12) 名前と行番号の区切り記号("__")を、HybsSystem.JOINT_STRING  に変更。
397         * @og.rev 5.9.1.2 (2015/10/23) iframeタグで利用のためprotected化
398         *
399         * @param key 判定するキー
400         *
401         * @return 標準的な リクエスト情報かどうか [true:標準的/false:それ以外]
402         */
403//      private boolean isNormalRequestKey( final String key ) {
404        protected boolean isNormalRequestKey( final String key ) {
405                return  key != null &&
406                                ! key.equals( HybsSystem.ROW_SEL_KEY ) &&
407                                ( key.indexOf( HybsSystem.JOINT_STRING ) < 0 || UNDER_BAR_KEY_USED );
408        }
409
410        /**
411         * シリアライズ用のカスタムシリアライズ書き込みメソッド
412         *
413         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
414         * @og.rev 5.9.1.2 (2015/10/23) iframeタグで利用のためprotected化
415         * @serialData 一部のオブジェクトは、シリアライズされません。
416         *
417         * @param       strm    ObjectOutputStreamオブジェクト
418         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
419         */
420//      private void writeObject( final ObjectOutputStream strm ) throws IOException {
421        protected void writeObject( final ObjectOutputStream strm ) throws IOException {
422                strm.defaultWriteObject();
423        }
424
425        /**
426         * シリアライズ用のカスタムシリアライズ読み込みメソッド
427         *
428         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
429         *
430         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
431         * @og.rev 5.9.1.2 (2015/10/23) iframeタグで利用のためprotected化
432         * @serialData 一部のオブジェクトは、シリアライズされません。
433         *
434         * @param       strm    ObjectInputStreamオブジェクト
435         * @see #release2()
436         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
437         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
438         */
439//      private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
440        protected void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
441                strm.defaultReadObject();
442        }
443
444        /**
445         * このオブジェクトの文字列表現を返します。
446         * 基本的にデバッグ目的に使用します。
447         *
448         * @return このクラスの文字列表現
449         */
450        @Override
451        public String toString() {
452                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
453                                .println( "VERSION"             ,VERSION        )
454                                .println( "tableId"             ,tableId        )
455                                .println( "changeGmn"   ,changeGmn      )
456                                .println( "keys"                ,keys           )
457                                .println( "dbTable"     ,dbTable        )
458                                .println( "Other..."    ,getAttributes().getAttribute() )
459                                .fixForm().toString() ;
460        }
461}