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