    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.plugin.view;
    017
    018import java.util.List;
    019
    020import org.opengion.fukurou.util.StringUtil;
    021import org.opengion.hayabusa.common.HybsSystemException;
    022import org.opengion.hayabusa.html.TableFormatter;
    023
    024/**
    025 * JavaScript のツリー階層を持ったテーブル表示を行う、ツリーテーブル表示クラスです。
    026 *
    027 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。
    028 * 各HTMLのタグに必要な setter/getterメソッドのみ，追加定義しています。
    029 *
    030 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。
    031 *
    032 * @og.rev 8.2.0.2 (2022/06/24) HTML5廃止対応
    033 * @og.group 画面表示
    034 *
    035 * @version  4.0
    036 * @author   Hiroki Nakamura
    037 * @since    JDK5.0,
    038 */
    039public class ViewForm_HTMLCustomTreeBOM extends ViewForm_HTMLTable  {
    040        /** このプログラムのVERSION文字列を設定します。   {@value} */
    041        private static final String VERSION = "7.3.0.0 (2021/01/06)" ;
    042
    043        private TableFormatter          headerFormat    ;
    044        private TableFormatter[]        bodyFormats             ;
    045        private int                                     bodyFormatsCount;
    046
    047        private static final int BODYFORMAT_MAX_COUNT = 10;
    048
    049        // 6.4.4.1 (2016/03/18) static final 定数化にします。
    050        private static final String FUTTER = "initializeDocument()" + CR + "//-->" + CR + "</script>" + CR + "</table>" + CR ;
    051
    052        // 6.4.4.1 (2016/03/18) static final 定数化にします。
    053        // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(<script> type属性削除)
    054//      private static final String HEADER = "<table id=\"viewTable\" border=\"0\" cellspacing=\"2\" cellpadding=\"0\"  summary=\"bomTable\">"
    055        private static final String HEADER = "<table id=\"viewTable\" border=\"0\" cellpadding=\"0\" style=\"border-spacing:2px;\" >"   // 8.2.0.2 (2022/06/24) Modify
    056//                                                                              + CR + "<script type=\"text/javascript\">" + CR + "<!--" + CR + "aux0 = gFld('" ;
    057                                                                                + CR + "<script>" + CR + "<!--" + CR + "aux0 = gFld('" ;
    058
    059        /**
    060         * デフォルトコンストラクター
    061         *
    062         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    063         */
    064        public ViewForm_HTMLCustomTreeBOM() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    065
    066        /**
    067         * DBTableModel から HTML文字列を作成して返します。
    068         * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
    069         * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
    070         *
    071         * @og.rev 4.3.1.0 (2008/09/08) フォーマットが設定されていない場合のエラー追加
    072         * @og.rev 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    073         * @og.rev 6.4.3.4 (2016/03/11) tdに、[カラム]が無いケースで、次の[カラム]のクラス属性が、前方すべてのtdにセットされてしまう対応。
    074         * @og.rev 6.4.4.1 (2016/03/18) FUTTER を、static final 定数化にします。
    075         * @og.rev 6.4.4.2 (2016/04/01) TableFormatterのタイプ別値取得処理の共通部をまとめる。
    076         * @og.rev 6.4.5.0 (2016/04/08) メソッド変更( getColumnDbType(int) → getClassName(int) )
    077         *
    078         * @param  stNo     表示開始位置
    079         * @param  pgSize   表示件数
    080         *
    081         * @return  DBTableModelから作成された HTML文字列
    082         * @og.rtnNotNull
    083         */
    084        @Override
    085        public String create( final int stNo, final int pgSize )  {
    086                // このクラスでは、テーブル全データを使用します。
    087                if( getRowCount() == 0 ) { return ""; } // 暫定処置
    088
    089                // 4.3.1.0 (2008/09/08)
    090                if( headerFormat == null ) {
    091                        final String errMsg = "ViewTagで canUseFormat() = true の場合、Formatter は必須です。";
    092                        throw new HybsSystemException( errMsg );
    093                }
    094
    095                final int startNo = 0;
    096                final int pageSize = getRowCount();
    097
    098                final int lastNo = getLastNo( startNo, pageSize );
    099
    100                headerFormat.makeFormat( getDBTableModel() );
    101                // 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    102                setFormatNoDisplay( headerFormat );
    103
    104                if( bodyFormatsCount == 0 ) {
    105                        bodyFormats[0] = headerFormat ;
    106                        bodyFormatsCount ++ ;
    107                }
    108                else {
    109                        for( int i=0; i<bodyFormatsCount; i++ ) {
    110                                bodyFormats[i].makeFormat( getDBTableModel() );
    111                                // 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    112                                setFormatNoDisplay( bodyFormats[i] );
    113                        }
    114                }
    115
    116                final StringBuilder out = new StringBuilder( BUFFER_LARGE );
    117                out.append( getHeader() );
    118
    119                int level;
    120                // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
    121                for( int row=startNo; row<lastNo; row++ ) {
    122                        // カラム==０は、レベルを指定する。
    123                        level = Integer.parseInt( getValueLabel(row,0) );
    124                        final boolean isFld = row+1<lastNo && level < Integer.parseInt( getValueLabel(row+1,0) );
    125                        out.append( getLevelScript( level,isFld ) );
    126
    127                        // 開始
    128                        for( int i=0; i<bodyFormatsCount; i++ ) {
    129                                final TableFormatter bodyFormat = bodyFormats[i];
    130
    131                                int cl = 0;
    132                                for( ; cl<bodyFormat.getLocationSize(); cl++ ) {
    133                                        // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
    134                                        String fmt = bodyFormat.getFormat(cl);
    135                                        final int loc = bodyFormat.getLocation(cl);
    136                                        if( ! bodyFormat.isNoClass() && loc >= 0 ) {
    137                                                // 6.4.3.4 (2016/03/11) tdに、[カラム]が無いケースで、次の[カラム]のクラス属性が、前方すべてのtdにセットされてしまう対応。
    138                                                final int idx = fmt.lastIndexOf( "<td" );
    139                                                if( idx >= 0 ) {        // matchしてるので、あるはず
    140                                                        final String tdclass = " class=\"" + getClassName(loc) + "\" ";                 // 6.4.5.0 (2016/04/08)
    141                                                        fmt = fmt.substring( 0,idx+3 ) + tdclass + fmt.substring( idx+3 ) ;
    142                                                }
    143                                        }
    144                                        out.append( fmt );
    145                                        if( loc >= 0 ) {
    146                                                // 6.4.4.2 (2016/04/01) 処理の共通部をまとめる。
    147                                                out.append( getTypeCaseValue( bodyFormat.getType(cl),row,loc ) );
    148                                        }
    149                                }
    150                                out.append( StringUtil.replace( bodyFormat.getFormat(cl), "</tr>", "" ) );
    151                        }
    152                        // 終了
    153
    154                        out.append( "', '', 'gold')" );
    155                        if( level != 0 ) {
    156                                out.append( ')' );              // 6.0.2.5 (2014/10/31) char を append する。
    157                        }
    158                        out.append( CR );
    159                }
    160                out.append( FUTTER );                   // 6.4.4.1 (2016/03/18)
    161
    162                return out.toString();
    163        }
    164
    165        /**
    166         * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。
    167         * JavaScript の TreeBody では、JavaScriptに関連する定義もこのヘッダーに
    168         * 含めます。
    169         *
    170         * @og.rev 6.4.4.1 (2016/03/18) HEADER を、static final 定数化にします。
    171         * @og.rev 7.3.0.0 (2021/01/06) SpotBugs:null チェックなしで null 値を利用対策
    172         *
    173         * @return  テーブルのヘッダータグ文字列
    174         * @og.rtnNotNull
    175         */
    176        @Override
    177        protected String getHeader() {
    178                // 7.3.0.0 (2021/01/06) SpotBugs:null チェックなしで null 値を利用対策
    179                if( headerFormat == null ) {
    180                        final String errMsg = "ViewTagで canUseFormat() = true の場合、Formatter は必須です。";
    181                        throw new HybsSystemException( errMsg );
    182                }
    183
    184                // 6.4.4.1 (2016/03/18) HEADER を、static final 定数化にします。
    185                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ).append( HEADER );
    186
    187                int cl = 0;
    188                // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している
    189                // フレームワークとして、create メソッドからしか、呼ばれないため、nullチェック済みです。
    190                for( ; cl<headerFormat.getLocationSize(); cl++ ) {
    191                        buf.append( StringUtil.replace( headerFormat.getFormat(cl) ,"td","th" ));
    192                        final int loc = headerFormat.getLocation(cl);
    193                        if( loc >= 0 ) { buf.append( getColumnLabel(loc) ); }
    194                        // ヘッダーフォーマット部では、何もしません。
    195                }
    196                buf.append( StringUtil.replace( StringUtil.replace( headerFormat.getFormat(cl) ,"td","th" ), "</tr>", "" ) )
    197                        .append("', '', 'gold')")
    198                        .append( CR );
    199
    200                return buf.toString();
    201        }
    202
    203        /**
    204         * 行のレベルに応じた JavaScript関数のヘッダー部分を返します。
    205         *
    206         * @og.rev 3.5.2.1 (2003/10/27) JavaScript 内のダブルコーテーションをシングルコーテーションに変更する。
    207         *
    208         * @param       lvl             ツリーのレベル
    209         * @param       isFld   フォルダかどうか[true:フォルダ/false:最下層]
    210         *
    211         * @return  JavaScript関数のヘッダー部分
    212         */
    213        private String getLevelScript( final int lvl,final boolean isFld ) {
    214
    215                final String auxX = "\taux" + ( lvl );
    216                final String auxY = "aux" + ( lvl-1 );
    217
    218                final String rtn ;
    219                if( isFld ) {
    220                        rtn = auxX + " = insFld(" + auxY + ", gFld('";
    221                }
    222                else {
    223                        rtn = "\tinsFld(" + auxY + ", gLnk('CONTENTS','";
    224                }
    225
    226                return rtn;
    227        }
    228
    229        /**
    230         * フォーマットを設定します。
    231         *
    232         * @param       list    TableFormatterのリスト
    233         */
    234        @Override
    235        public void setFormatterList( final List<TableFormatter> list ) {               // 4.3.3.6 (2008/11/15) Generics警告対応
    236                bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT];
    237
    238                bodyFormatsCount = 0;
    239                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
    240                for( final TableFormatter format : list ) {
    241//              for( int i=0; i<list.size(); i++ ) {
    242//                      final TableFormatter format = list.get( i );            // 4.3.3.6 (2008/11/15) Generics警告対応
    243                        switch( format.getFormatType() ) {
    244                        case TYPE_HEAD : headerFormat = format; break;
    245                        case TYPE_BODY : bodyFormats[bodyFormatsCount++] = format; break;
    246                        default : final String errMsg = "FormatterType の定義外の値が指定されました。";
    247                        // 4.3.4.4 (2009/01/01)
    248                                          throw new HybsSystemException( errMsg );
    249                        }
    250                }
    251
    252                if( headerFormat == null ) {
    253                        final String errMsg = "og:thead タグの、フォーマットの指定は必須です。";
    254                        throw new HybsSystemException( errMsg );
    255                }
    256        }
    257
    258        /**
    259         * フォーマットメソッドを使用できるかどうかを問い合わせます。
    260         *
    261         * @return  使用可能(true)/ 使用不可能 (false)
    262         */
    263        @Override
    264        public boolean canUseFormat() {
    265                return true;
    266        }
    267
    268        /**
    269         * ビューで表示したカラムの一覧をCSV形式で返します。
    270         *
    271         * @og.rev 5.1.6.0 (2010/05/01) 新規追加
    272         * @og.rev 6.2.0.1 (2015/03/06) TableFormatter#getLocation(int)の有効判定
    273         * @og.rev 6.4.3.4 (2016/03/11) getViewClms(TableFormatter) を使用して表示されたカラム一覧を求めます。
    274         *
    275         * @return      ビューで表示したカラムの一覧
    276         * @og.rtnNotNull
    277         */
    278        @Override
    279        public String getViewClms() {
    280                return getViewClms( headerFormat );
    281        }
    282}