    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.taglib;
    017
    018import org.opengion.fukurou.util.TagBuffer;
    019import org.opengion.fukurou.util.XHTMLTag;
    020import org.opengion.hayabusa.common.HybsSystem;
    021import org.opengion.hayabusa.common.HybsSystemException;
    022import org.opengion.hayabusa.db.DBTableModel;
    023import org.opengion.hayabusa.db.DBTableModelUtil;
    024
    025import static org.opengion.fukurou.util.StringUtil.nval;
    026
    027import java.io.IOException;
    028import java.io.ObjectInputStream;
    029import java.io.ObjectOutputStream;
    030import java.util.ArrayList;
    031import java.util.List;
    032import java.util.Locale;
    033
    034/** タブ形式のリンクを表示するタグです。
    035 *
    036 * このタグ形式の実態は、リンクのリストであるため、実の画面の表示はターゲットを指定して
    037 * 別フレームで行う必要があります。
    038 *
    039 * タブの指定方法については、listType属性の指定により、クエリ発行(DB)により動的に生成する
    040 * パターンと、タグ指定(TAG)により、静的に生成するパターンがあります。
    041 * listType属性に何も指定されていない場合は、Body部分に記述された内容により、自動判定されます。
    042 * ("SELECT"で始まっている場合はDB、それ以外はTAGとして処理)
    043 *
    044 * ①listType属性が"DB"の場合
    045 *  検索された各カラムは、その順番により次の意味を持ちます。
    046 *  [第1カラム] タブの名前        : リンク時のキー情報、後述のopenTabName属性のキーとしても使用 ※必須
    047 *  [第2カラム] タブの表示名称    : タブの表示名称 指定がない場合は、第1カラムが表示名称となります。
    048 *  [第3カラム] タブのリンク先URL : タブのリンク先URL 指定がない場合は、href属性の値が適用されます。
    049 *  [第4カラム] タブのクラス属性  : 個別のタブに付加されるクラス属性 指定がない場合は、unselClass属性の値が適用されます。
    050 *  [第5カラム] タブのロールズ    : タブのロールズを指定します。ユーザーロールズと一致しない指定した場合は、タブが表示されなくなります。
    051 *  [第6カラム] タブの選択可否    : タブの選択可否を'true'or'false'で指定します。falseを指定した場合は、タブが表示されなくなります。
    052 *                                  (ロールズで選択不可になっている場合は、この値は無視されます)
    053 *  各カラムの値は[カラム名]=[値]の形で、リンク先のJSPに引数として渡されます。
    054 *  また、リンク先のJSPについては、href属性で指定します。
    055 *
    056 * ②listType属性が"TAG"の場合
    057 *  tabListタグを記述し、個別にタブを定義します。
    058 *  制御可能な項目は、①DBの場合と同等です。
    059 *  タブの名前を定義するname属性は、tabListタグで必ず定義する必要があります。
    060 *  lbl属性が指定されていない場合は、name属性のラベル名称を取得します。
    061 *  タブのリンク先JSP及び、クラス属性については、tabListタグで指定がない場合、tabListタグの値が適用されます。
    062 *
    063 * [共通設定]
    064 * 初期設定では、第1番目の"有効な"タブが自動的に開かれます。(="true")
    065 * 各タブの表示方法で、選択不可能なタブが存在している場合は、それらを読み飛ばした上で、"有効な"タブを
    066 * 検索します。
    067 * また、自動で開くタブは、openTabName属性で指定可能であり、これに変数を定義することで、
    068 * 画面リロード時も、開いていたタブを再度選択された状態で表示することが可能です。
    069 *
    070 * 選択したタブ及び非選択のタブの枠線や、背景色等を変更する場合は、custom.cssでクラスを定義し、
    071 * 変更して下さい。
    072 *
    073 * タブの表示方向(水平方向 or 垂直方向)については、orientation属性で変更することが可能です。
    074 * (初期値は、水平方向)
    075 * 水平方向にした場合は、listCount属性により強制的に一定数のタブを表示する毎に、改行を挿入することができます。
    076 *
    077 * このタグを使用する場合は、headタグで必ずuseTabLink="true"を指定してJavaScriptをロードして下さい。
    078 *
    079 * 各属性は、{&#064;XXXX} 変数が使用できます。
    080 * これは、ServletRequest から、XXXX をキーに値を取り出し,この変数に割り当てます。
    081 * つまり、このXXXXをキーにリクエストすれば、この変数に値をセットすることができます。
    082 *
    083 * @og.formSample
    084 * ●形式：&lt;og:tabLink href="…" … /&gt;
    085 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    086 *
    087 * ●Tag定義：
    088 *   &lt;og:tabLink
    089 *       listType           【TAG】タブの一覧をどこから取得するかを指定します(初期値:AUTO)
    090 *       href               【TAG】リンク先のJSPを指定します(初期値:result.jsp)
    091 *       target             【TAG】リンクのターゲットを指定します(初期値:RESULT)
    092 *       openTab            【TAG】リンク表示にタブリンクを自動で開くかどうか[true/false]を指定します(初期値:true[=開く])
    093 *       openTabName        【TAG】最初に開くタブリンクの名前を指定します
    094 *       constKeys          【TAG】次画面に渡す定数パラメーターのキーを指定します
    095 *       constVals          【TAG】次画面に渡す定数パラメーターの値を指定します
    096 *       listCount          【TAG】1行辺りに表示するタブの数を指定します(初期値:10)
    097 *       selClass           【TAG】選択タブのクラスを指定します(初期値:selTab)
    098 *       unselClass         【TAG】非選択タブのクラスを指定します(初期値:unselTab)
    099 *       orientation        【TAG】タブの方向、横型(Horizontal)か縦型(Vertical)を指定します(初期値:横型)
    100 *       width              【TAG】タブリンクの幅を % 、px 、または "auto" で指定します
    101 *       height             【TAG】タブの高さを、% 、px 、または "auto" で指定します
    102 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    103 *   &gt;   ... Body ...
    104 *   &lt;/og:tabLink&gt;
    105 *
    106 * ●使用例
    107 *   ①DBからタブリストを取得する場合
    108 *
    109 *    Body部分に記述されたクエリよりタブ一覧を生成します。
    110 *
    111 *      &lt;og:tabLink
    112 *          listType        = "DB"                      タブの一覧をどこから取得するか
    113 *          href            = "result.jsp"              リンク先のJSP
    114 *          target          = "RESULT"                  リンクターゲット
    115 *          openTab         = "[true/false]"            タブ表示後にタブを自動で開く
    116 *          openTabName     = "{&#064;PN}               自動で開くタブの名前
    117 *          constKeys       = "KEY1"                    次画面に固定で渡すキー一覧
    118 *          constVals       = "{&#064;VAL1}"            次画面に固定で渡す値一覧
    119 *          listCount       = "10"                      1行辺りに表示するタブの数
    120 *          selClass        = "selTab"                  選択タブのクラス
    121 *          unselClass      = "unselTab"                非選択タブのクラス
    122 *          width           = "100px"                   タブリンクの幅
    123 *          height          = "50px"                    タブリンクの高さ
    124 *       &gt;
    125 *               select PN,HINM,'tabClass','query.jsp','ADMIN','false' from XX01 where PN = '{&#064;PN}' order by PN
    126 *      &lt;/og:tabLink&gt;
    127 *
    128 *   ②tabListタグからタブリストを生成する場合
    129 *
    130 *    tabListタグよりタブ一覧を生成します。
    131 *
    132 *      &lt;og:tabLink
    133 *          listType        = "DB"                      タブの一覧をどこから取得するか
    134 *          href            = "result.jsp"              リンク先のJSP
    135 *          target          = "RESULT"                  リンクターゲット
    136 *          openTab         = "[true/false]"            タブ表示後にタブを自動で開く
    137 *          openTabName     = "{&#064;PN}               自動で開くタブの名前
    138 *          constKeys       = "KEY1"                    次画面に固定で渡すキー一覧
    139 *          constVals       = "{&#064;VAL1}"            次画面に固定で渡す値一覧
    140 *          listCount       = "10"                      1行辺りに表示するタブの数
    141 *          selClass        = "selTab"                  選択タブのクラス
    142 *          unselClass      = "unselTab"                非選択タブのクラス
    143 *          width           = "100px"                   タブリンクの幅
    144 *          height          = "50px"                    タブリンクの高さ
    145 *       &gt;
    146 *          &lt;og:tabList name="TAB1" href="result1.jsp" keys="PN,CDK" vals="ABC,V" /&gt;
    147 *          &lt;og:tabList name="TAB2" href="result2.jsp" keys="PN,CDK" vals="BCD,W" /&gt;
    148 *          &lt;og:tabList name="TAB3" href="result3.jsp" keys="PN,CDK" vals="CDE,X" /&gt;
    149 *      &lt;/og:tabLink&gt;
    150 *
    151 * @og.group 画面表示
    152 *
    153 * @version  0.9.0      2008/09/26
    154 * @author       Nakamura
    155 * @since        JDK1.4,
    156 */
    157public class TabLinkTag extends CommonTagSupport {
    158        private static final String             VERSION                         = "5.1.8.0 (2010/07/01)";
    159        private static final long               serialVersionUID        = 518020100701L ;
    160
    161        /** リストのulタグのclass属性 */
    162        private static final String             UL_TAG_START            = "<ul class=\"tabList\">";
    163        private static final String             UL_TAG_END                      = "</ul>";
    164
    165        /** タブ表示を入れ替えるためのJavaScript関数 */
    166        private static final String             CHANGE_TAB_SCRIPT       = "changeTab";
    167        private static final String             INITIAL_TAB_SCRIPT      = "initialTabSelect";
    168
    169        /** 自動で開くタブに付加されるID */
    170        private static final String             FIRST_TAB_ID            = "firstTab";
    171
    172        /** リスト取得タイプのEnum */
    173        private static enum LIST_TYPE { AUTO, DB, TAG };
    174
    175        /** 内部変数 */
    176        private String          query                   = null;
    177        private transient List<TabData>         tabData         = new ArrayList<TabData>();
    178
    179        /** タグで設定する属性 */
    180        private LIST_TYPE       type                    = LIST_TYPE.AUTO;
    181        private String          href                    = "result.jsp";
    182        private String          target                  = "RESULT";
    183        private boolean         openTab                 = true;
    184        private String          openTabName             = null;
    185        private String[]        constKeys               = null;
    186        private String[]        constVals               = null;
    187        private int                     listCount               = 10;
    188        private String          selClass                = "selTab";
    189        private String          unselClass              = "unselTab";
    190        private boolean         isHorizontal    = true;
    191        private String          width                   = "auto";
    192        private String          height                  = "auto";
    193
    194        /**
    195         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    196         *
    197         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
    198         */
    199        @Override
    200        public int doStartTag() {
    201                return EVAL_BODY_BUFFERED ;     // Body を評価する
    202        }
    203
    204        /**
    205         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    206         *
    207         * @return      後続処理の指示(SKIP_BODY)
    208         */
    209        @Override
    210        public int doAfterBody() {
    211                query = getBodyString().trim();
    212                return SKIP_BODY ;
    213        }
    214
    215        /**
    216         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    217         *
    218         * @og.rev 4.3.5.0 (2008/02/01) 処理及び内部構造を大幅に見直し
    219         *
    220         * @return      後続処理の指示
    221         */
    222        @Override
    223        public int doEndTag() {
    224                debugPrint();
    225                int rtnCode = EVAL_PAGE;
    226
    227                // 種別の自動判定処理
    228                if( type == LIST_TYPE.AUTO ) {
    229                        if( query == null || query.length() == 0 ) {
    230                                type = LIST_TYPE.TAG;
    231                        }
    232                        else {
    233                                if( query.toUpperCase( Locale.JAPAN ).indexOf( "SELECT" ) >= 0 ) {
    234                                        type = LIST_TYPE.DB;
    235                                }
    236                                else {
    237                                        type = LIST_TYPE.TAG;
    238                                }
    239                        }
    240                }
    241
    242                if( type == LIST_TYPE.DB ) {
    243                        makeTabsFromQuery();
    244                }
    245                else if( type == LIST_TYPE.TAG ) {
    246                        makeTabsFromTag();
    247                }
    248
    249                // リンク一覧が何も設定されていない場合は、処理しない
    250                if( ! tabData.isEmpty() ) {
    251                        makeTag();
    252                }
    253
    254                return rtnCode ;
    255        }
    256
    257        /**
    258         * タグリブオブジェクトをリリースします。
    259         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    260         */
    261        @Override
    262        protected void release2() {
    263                super.release2();
    264                query                   = null;
    265                tabData                 = new ArrayList<TabData>();
    266                type                    = LIST_TYPE.AUTO;
    267                href                    = "result.jsp";
    268                target                  = "RESULT";
    269                openTab                 = true;
    270                openTabName             = null;
    271                constKeys               = null;
    272                constVals               = null;
    273                listCount               = 10;
    274                selClass                = "selTab";
    275                unselClass              = "unselTab";
    276                isHorizontal    = true;
    277                width                   = "auto";
    278                height                  = "auto";
    279        }
    280
    281        /**
    282         * DBからタブリンクの一覧を作成します。
    283         * DBTableModelが作成されない(行数が0の場合)は、リンク一覧は生成されません。
    284         */
    285        private void makeTabsFromQuery() {
    286                DBTableModel table = DBTableModelUtil.makeDBTable( query, new String[0], getResource(), getApplicationInfo() );
    287                if( table == null || table.getRowCount() == 0 ) {
    288                        return;
    289                }
    290
    291                boolean isSetLabel = false;
    292                boolean isSetHref = false;
    293                boolean isSetClazz = false;
    294                boolean isSetRoles = false;
    295                boolean isSetVisible = false;
    296                if( table.getColumnCount() > 1 ) { isSetLabel = true; }
    297                if( table.getColumnCount() > 2 ) { isSetHref = true; }
    298                if( table.getColumnCount() > 3 ) { isSetClazz = true; }
    299                if( table.getColumnCount() > 4 ) { isSetRoles = true; }
    300                if( table.getColumnCount() > 5 ) { isSetVisible = true; }
    301
    302                int rowCount = table.getRowCount();
    303                String key = table.getColumnName( 0 );
    304                for( int row=0; row<rowCount; row++ ) {
    305                        String value    = table.getValue( row, 0 );
    306                        String label    = ( isSetLabel ? nval( table.getValue( row, 1 ), value ) : value );
    307                        String newHref  = ( isSetHref  ? nval( table.getValue( row, 2 ), href ) : href );
    308                        String clazz    = ( isSetClazz ? nval( table.getValue( row, 3 ), unselClass ) : unselClass );
    309                        boolean visible = ( isSetRoles ? getUser().isAccess( table.getValue( row, 4 ) ) : true );
    310                        if( visible ) {
    311                                visible         = ( isSetVisible ? Boolean.valueOf( table.getValue( row, 5 ) ) : true );
    312                        }
    313
    314                        // 第1カラムのカラム名とその値はリンクの引数に含める
    315                        newHref = XHTMLTag.addUrlEncode( newHref, XHTMLTag.urlEncode( key, value ) );
    316
    317                        if( visible ) { // visible=falseの場合は表示しない
    318                                tabData.add( new TabData( newHref, value, label, clazz, visible ) );
    319                        }
    320                }
    321        }
    322
    323        /**
    324         * タブリストからタブリンクの一覧を作成します。
    325         * (予めaddTagメソッドにより、リンク一覧が登録されているため、ここでは何も処理しません)
    326         *
    327         * @see #addTag( String, String, String, String, boolean, String[], String[] )
    328         */
    329        private void makeTabsFromTag() {
    330                // 何もありません。(PMD エラー回避)
    331        }
    332
    333        /**
    334         * 子タグであるタブリストタグからタブ情報をセットします。
    335         *
    336         * @param hr 画面URL
    337         * @param name タブの名前
    338         * @param label タブの表示名称
    339         * @param clz 非選択状態のタブに付加するclass名
    340         * @param visible タブが選択可能(中身を表示できるかどうか)
    341         * @param keys リンク先のJSPに渡すキー一覧
    342         * @param vals リンク先のJSPに渡す値一覧
    343         */
    344        protected void addTag( final String hr, final String name, final String label, final String clz
    345                                                        ,final boolean visible, final String[] keys, final String[] vals ) {
    346                String newHref = nval( hr, href );
    347                if( keys != null && keys.length > 0 ) {
    348                        newHref = XHTMLTag.addUrlEncode( newHref, XHTMLTag.urlEncode( keys, vals ) );
    349                }
    350
    351                if( visible ) { // visible=falseの場合は表示しない
    352                        tabData.add( new TabData( newHref, name, nval( label, getLabel( name ) ), nval( clz, unselClass ), visible ) );
    353                }
    354        }
    355
    356        /**
    357         * リンク一覧からHTMLタグを作成します。
    358         *
    359         * @og.rev 5.0.2.0 (2009/11/01) openTab属性がfalseの場合でも、openTabNameに指定されたタブに色付けする。
    360         * @og.rev 5.1.4.0 (2010/03/01) FF対応&FirstTabのID付加に関するバグを修正
    361         */
    362        private void makeTag() {
    363                StringBuilder buf = new StringBuilder();
    364                buf.append( HybsSystem.CR );
    365
    366                boolean isExistFirst = false;
    367                for( int idx=0; idx<tabData.size(); idx++ ) {
    368                        TabData tab = tabData.get( idx );
    369
    370                        if( idx % listCount == 0 ) {
    371                                if( idx > 0 ) {
    372                                        buf.append( UL_TAG_END ).append( HybsSystem.CR );
    373                                }
    374                                buf.append( UL_TAG_START ).append( HybsSystem.CR );
    375                        }
    376
    377                        // openTabNameが定義されていない場合は、1番目の有効なタブを開く
    378                        // 5.1.4.0 (2010/03/01) バグ修正
    379                        if( !isExistFirst && tab.visible
    380                                && ( openTabName == null || openTabName.length() == 0 || openTabName.equals( tab.name ) ) ) {
    381                                buf.append( tab.makeLiTag( idx, true ) );
    382                                isExistFirst = true;
    383                        }
    384                        else {
    385                                buf.append( tab.makeLiTag( idx, false ) );
    386                        }
    387                }
    388                buf.append( UL_TAG_END ).append( HybsSystem.CR );
    389
    390                // タブを自動で開くためのJavaScriptタグを発行
    391                // 5.1.4.0 (2010/03/01) FF対応
    392                if( openTab || ( openTabName != null && openTabName.length() > 0 ) ) {
    393                        buf.append( "<script type=\"text/javascript\">addEvent(window,\"load\", function() { " + INITIAL_TAB_SCRIPT + "(" );
    394                        buf.append( openTab );
    395                        buf.append( "); } );</script>" );
    396                }
    397
    398                jspPrint( buf.toString() );
    399        }
    400
    401        /**
    402         * Tabデータ を管理している 内部クラス
    403         *
    404         * タブの情報を管理するための簡易的な、内部クラスです。
    405         */
    406        private final class TabData {
    407                // 引数として初期設定される変数
    408                private final String href;
    409                private final String name;
    410                private final String label;
    411                private final String clazz;
    412                // 現状の実装では、visible=falseは渡ってきませんが、将来的にdisableの状態で
    413                // 表示したい場合等に対応するため残しておきます。
    414                private final boolean visible;
    415
    416                /**
    417                 * コンストラクタ
    418                 *
    419                 * @param hr 画面URL
    420                 * @param nm タブの名前
    421                 * @param lbl タブの表示名称
    422                 * @param clz 非選択状態のタブに付加するclass名
    423                 * @param vsb タブが選択可能(中身を表示できるかどうか)
    424                 */
    425                public TabData( final String hr, final String nm, final String lbl, final String clz, final boolean vsb ) {
    426                        href    = hr;
    427                        name    = nm;
    428                        label   = lbl;
    429                        clazz   = clz;
    430                        visible = vsb;
    431                }
    432
    433                /**
    434                 * liタグの部分の文字列を生成します。
    435                 *
    436                 * @param idx 生成したタブのインデックス番号
    437                 * @param isFirst 始めの有効なタブかどうか
    438                 * @return liタグ文字列
    439                 */
    440                private String makeLiTag( final int idx, final boolean isFirst ) {
    441                        StringBuilder buf = new StringBuilder();
    442                        buf.append( "<li class=\"" ).append( clazz ).append( "\"" );
    443                        buf.append( " style=\"" );
    444                        buf.append( " width: " ).append( width ).append( ";" );
    445                        buf.append( " height: " ).append( height ).append( ";" );
    446                        // 水平方向の場合のみfloat:leftを付加し、回り込み(+解除)を行う。
    447                        if( isHorizontal ) {
    448                                buf.append( " float: left;" );
    449                                if( idx % listCount == 0 ) {
    450                                        // 行が変わったタイミングで、テキストの折り返しをクリア＆左マージン(+10px)を空ける
    451                                        buf.append( " clear: left; margin-left: " );
    452                                        // 4.3.4.4 (2009/01/01) Math.roundを呼び出す意味がないため削除
    453                                        buf.append( (idx/listCount) * 10 ).append( "px;" );
    454                                }
    455                        }
    456                        buf.append( " \"" );
    457                        buf.append( ">" );
    458                        buf.append( makeLinkTag( isFirst ) );
    459                        buf.append( "</li>" ).append( HybsSystem.CR );
    460
    461                        return buf.toString();
    462                }
    463
    464                /**
    465                 * aタグの部分の文字列を生成します。
    466                 * タブが選択不可能な状態の場合は、タブの表示文字列をそのまま返します。
    467                 *
    468                 * @og.rev 4.3.6.4 戻るボタンがでない問題への対応
    469                 *
    470                 * @param isFirst 始めの有効なタブかどうか
    471                 * @return liタグ文字列
    472                 */
    473                private String makeLinkTag( final boolean isFirst ) {
    474                        String newHref = XHTMLTag.addUrlEncode( href, XHTMLTag.urlEncode( constKeys, constVals ) );
    475                        // 4.3.6.4 (2009/05/01)
    476                        // タブ画面から遷移した時に、タブの読込により、画面IDが消えてしまい
    477                        // 戻るボタンがでない不具合への対応
    478                        newHref = XHTMLTag.addUrlEncode( newHref, "GAMENID=" + getGUIInfoAttri( "KEY" ) );
    479                        TagBuffer tag = new TagBuffer( "a" );
    480                        tag.add( "href", newHref );
    481                        tag.add( "name", name );
    482                        tag.add( "target", target );
    483                        tag.add( "onClick", CHANGE_TAB_SCRIPT + "( this, \"" + selClass + "\" );" );
    484                        if ( isFirst ) {
    485                                tag.add( "id", FIRST_TAB_ID );
    486                        }
    487                        tag.setBody( label );
    488
    489                        return tag.makeTag();
    490                }
    491        }
    492
    493        /**
    494         * 【TAG】タブの一覧をどこから取得するかを指定します(初期値:AUTO)。
    495         *
    496         * @og.tag
    497         * タブの一覧をどこから取得するかを指定します。
    498         * 現状の実装では、クエリを発行して一覧を生成する「DB」と、子タグである
    499         * tabListタグを列挙してタブを定義する「TAG」が実装されています。
    500         *
    501         * また、「AUTO」と指定した場合は、Body部分の内容に応じて自動的に判定されます。
    502         * 初期値は、｢AUTO」です。
    503         *
    504         * @param       tp タブ一覧取得方法(「AUTO」)
    505         */
    506        public void setListType( final String tp ) {
    507                String typeStr = nval( getRequestParameter( tp ), null );
    508                try {
    509                        type = LIST_TYPE.valueOf( typeStr );
    510                }
    511                catch ( IllegalArgumentException ex ) {
    512                        StringBuilder errBuf = new StringBuilder( 100 );
    513                        errBuf.append( "listType は" );
    514                        for ( LIST_TYPE obj : LIST_TYPE.values() ) {
    515                                errBuf.append( ',' );
    516                                errBuf.append( obj.name() );
    517                        }
    518                        errBuf.append( "から選んでください。" );
    519                        throw new HybsSystemException( errBuf.toString(), ex );
    520                }
    521        }
    522
    523        /**
    524         * 【TAG】リンク先のJSPを指定します(初期値:result.jsp)。
    525         *
    526         * @og.tag
    527         * リンク先のJSPを指定します。
    528         * このタブリンクは、あくまで「タブの形をしたリンク」なので、
    529         * target属性と合わせてセットする必要があります。
    530         * 初期値は、｢result.jsp」です。
    531         *
    532         * @param       hr リンク先のJSP
    533         */
    534        public void setHref( final String hr ) {
    535                href = nval( getRequestParameter( hr ), href );
    536        }
    537
    538        /**
    539         * 【TAG】リンクのターゲットを指定します(初期値:RESULT)。
    540         *
    541         * @og.tag
    542         * リンクのターゲットを指定します。
    543         * このタブリンクは、あくまで「タブの形をしたリンク」なので、
    544         * target属性を設定し、別のフレームに実画面を表示するようにします。
    545         * 初期値は、｢RESULT」です。
    546         *
    547         * @param       tgt リンクターゲット
    548         */
    549        public void setTarget( final String tgt ) {
    550                target = nval( getRequestParameter( tgt ), target );
    551        }
    552
    553        /**
    554         * 【TAG】リンク表示にタブリンクを自動で開くかどうか[true/false]を指定します(初期値:true[=開く])。
    555         *
    556         * @og.tag
    557         * リンク表示にタブリンクを自動で開くかを指定します。
    558         * openTabName属性が指定されていない場合、自動で開くタブは
    559         * 「1番目に表示されたタブリンク」です。
    560         * 指定されている場合は、その名前を持つ「1番目」のタブが自動で開かれます。
    561         * タブが選択不可能な状態の場合は、「1番目」の条件から除外されます。
    562         * 初期値は、「true(開く)」です。
    563         *
    564         * @param       flag タブ表示後に自動でタブを開くか[true:自動で開く/false:開かない]
    565         */
    566        public void setOpenTab( final String flag ) {
    567                openTab = nval( getRequestParameter( flag ), openTab );
    568        }
    569
    570        /**
    571         * 【TAG】最初に開くタブリンクの名前を指定します。
    572         *
    573         * @og.tag
    574         * 最初に開くタブリンクのキーを指定します。
    575         *
    576         * @param       name 最初に開くタブリンクの名前
    577         */
    578        public void setOpenTabName( final String name ) {
    579                openTabName = nval( getRequestParameter( name ), openTabName );
    580        }
    581
    582        /**
    583         * 【TAG】次画面に渡す定数パラメーターのキーを指定します。
    584         *
    585         * @og.tag
    586         * 次画面に渡す定数パラメーターのキーを指定します。
    587         * キーはカンマ区切りで複数指定が可能です。
    588         * パラメーターの値は、constVals属性の数と一致している必要があります。
    589         *
    590         * @param       keys 定数パラメーターのキー
    591         * @see         #setConstVals( String )
    592         */
    593        public void setConstKeys( final String keys ) {
    594                constKeys = getCSVParameter( keys );
    595        }
    596
    597        /**
    598         * 【TAG】次画面に渡す定数パラメーターの値を指定します。
    599         *
    600         * @og.tag
    601         * 次画面に渡す定数パラメーターの値を指定します。
    602         * 値はカンマ区切りで複数指定が可能です。
    603         * パラメーターの値は、constKeys属性の数と一致している必要があります。
    604         *
    605         * @param       vals 定数パラメーターのキー
    606         * @see         #setConstKeys( String )
    607         */
    608        public void setConstVals( final String vals ) {
    609                constVals = getCSVParameter( vals );
    610        }
    611
    612        /**
    613         * 【TAG】1行辺りに表示するタブの数を指定します(初期値:10)。
    614         *
    615         * @og.tag
    616         * 1行辺りに表示するタブの数を指定します。
    617         * 1行辺りのタブの数がこの設定を超えると、自動的に折り返します。
    618         * また、折り返し毎に、左に10pxのマージンを設けます。
    619         * 初期値は、10です。
    620         * この属性は、orientationがHorizontal(水平方向)の場合のみ有効です。
    621         *
    622         * @param       cnt 1行辺りに表示するタブの数
    623         */
    624        public void setListCount( final String cnt ) {
    625                listCount = nval( getRequestParameter( cnt ), listCount );
    626        }
    627
    628        /**
    629         * 【TAG】選択タブのクラスを指定します(初期値:selTab)。
    630         *
    631         * @og.tag
    632         * タブが選択されている状態にある場合の、タブ部分のクラス名を指定します。
    633         * このクラス名を変更する場合は、そのクラスをcustom/custom.css等で再定義して下さい。
    634         * 初期値は、selTabです。
    635         *
    636         * @param       cls 選択タブのクラス名
    637         */
    638        public void setSelClass( final String cls ) {
    639                selClass = nval( getRequestParameter( cls ), selClass );
    640        }
    641
    642        /**
    643         * 【TAG】非選択タブのクラスを指定します(初期値:unselTab)。
    644         *
    645         * @og.tag
    646         * タブが選択されていない状態にある場合の、タブ部分のクラス名を指定します。
    647         * このクラス名を変更する場合は、そのクラスをcustom/custom.css等で再定義して下さい。
    648         * 初期値は、unselTabです。
    649         *
    650         * @param       cls 選択タブのクラス名
    651         */
    652        public void setUnselClass( final String cls ) {
    653                unselClass = nval( getRequestParameter( cls ), unselClass );
    654        }
    655
    656        /**
    657         * 【TAG】タブの方向、横型(Horizontal)か縦型(Vertical)を指定します(初期値:横型)。
    658         *
    659         * @og.tag
    660         * タブは、上にタブが並ぶ横型と左にタブが並ぶ縦型があります。
    661         * この属性では、横型は、Horizontal 、縦型は、Vertical を指定します。
    662         * 指定は、文字列の最初の一文字を見ているだけですので、HかVでも構いません。
    663         *
    664         * 縦型(Vertical)にした場合、各タブ要素は、フレームサイズの幅に合わせて
    665         * 最大で表示されます。幅を固定する場合は、width属性を指定して下さい。
    666         *
    667         * 初期値は、横型(Horizontal) です。
    668         *
    669         * @param       ori タブの方向、横型(Horizontal)か縦型(Vertical)を指定
    670         */
    671        public void setOrientation( final String ori ) {
    672                String ori2 = nval( getRequestParameter( ori ),null );
    673                if( ori2 != null && ori2.length() > 0 ) {
    674                        char ch = ori2.toUpperCase(Locale.JAPAN).charAt( 0 );
    675                        if( ch == 'H' ) { isHorizontal = true; }
    676                        else if( ch == 'V' ) { isHorizontal = false; }
    677                        else {
    678                                String errMsg = "orientation の指定は、H(orizontal) または、V(ertical) です。"
    679                                                        + " orientation=" + ori2 ;                      // 5.1.8.0 (2010/07/01) errMsg 修正
    680                                throw new HybsSystemException( errMsg );
    681                        }
    682                }
    683        }
    684
    685        /**
    686         * 【TAG】タブリンクの幅を % 、px 、または "auto" で指定します。
    687         *
    688         * @og.tag
    689         * 初期値は、"auto"(自動設定) です。
    690         * autoの場合、横型表示では、文字の幅に合わせて自動的に調整され、
    691         * 縦型表示の場合は、フレームサイズに合わせて拡大して表示されます。
    692         *
    693         * @param       wh      幅 (% 、px 、または "auto" )
    694         */
    695        public void setWidth( final String wh ) {
    696                width = nval( getRequestParameter( wh ),width );
    697        }
    698
    699        /**
    700         * 【TAG】タブの高さを、% 、px 、または "auto" で指定します。
    701         *
    702         * @og.tag
    703         * タブの高さを、% 、px 、または "auto" で指定します
    704         * 初期値は、"auto"(自動設定) です。
    705         *
    706         * @param       ht      高さ (% 、px 、または "auto" )
    707         */
    708        public void setHeight( final String ht ) {
    709                height = nval( getRequestParameter( ht ),height );
    710        }
    711
    712        /**
    713         * シリアライズ用のカスタムシリアライズ書き込みメソッド
    714         *
    715         * @serialData 一部のオブジェクトは、シリアライズされません。
    716         *
    717         * @param       strm    ObjectOutputStreamオブジェクト
    718         * @throws IOException  入出力エラーが発生した場合
    719         */
    720        private void writeObject( final ObjectOutputStream strm ) throws IOException {
    721                strm.defaultWriteObject();
    722        }
    723
    724        /**
    725         * シリアライズ用のカスタムシリアライズ読み込みメソッド
    726         *
    727         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
    728         *
    729         * @og.rev 5.1.8.0 (2010/07/01) tabData の初期化処理 追加
    730         * @serialData 一部のオブジェクトは、シリアライズされません。
    731         *
    732         * @param       strm    ObjectInputStreamオブジェクト
    733         * @see #release2()
    734         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
    735         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
    736         */
    737        private void readObject( final ObjectInputStream strm ) throws IOException, ClassNotFoundException {
    738                strm.defaultReadObject();
    739                tabData         = new ArrayList<TabData>();
    740        }
    741
    742        /**
    743         * このオブジェクトの文字列表現を返します。
    744         * 基本的にデバッグ目的に使用します。
    745         *
    746         * @return このクラスの文字列表現
    747         */
    748        @Override
    749        public String toString() {
    750                return org.opengion.fukurou.util.ToString.title(this.getClass().getName() )
    751                .println( "VERSION"       , VERSION )
    752                .println( "listType"      , type.toString() )
    753                .println( "href"          , href )
    754                .println( "target"        , target )
    755                .println( "openTab"       , openTab )
    756                .println( "openTabName"   , openTabName )
    757                .println( "constKeys"     , constKeys )
    758                .println( "constVals"     , constVals )
    759                .println( "listCount"     , listCount )
    760                .println( "selClass"      , selClass )
    761                .println( "unselClass"    , unselClass )
    762                .println( "isHorizontal"  , isHorizontal )
    763                .println( "width"         , width )
    764                .println( "height"        , height )
    765                .println( "Other...", getAttributes().getAttribute() ).fixForm().toString();
    766        }
    767}