    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.hayabusa.common.HybsSystemException;
    021import org.opengion.hayabusa.html.TableFormatter;
    022
    023/**
    024 * ヘッダ、フッタ、ボディを指定して作成する、自由レイアウトが可能な、カスタムテーブル表示クラスです。
    025 * 従来は、内部バグのため、thead,tbody,tfoot タグを使わないと処理できませんでしたが、
    026 * viewタグの BODY 部にフォーマットを記述するだけで処理するように改善しました。(5.6.3.3 (2013/04/19))
    027 *
    028 * このタグでは、BODY部、または、bodyFormats を繰り返す処理を行います。
    029 * ヘッダ があれば、最初に、１度のみ実行し、フッタがあれば、最後に実行します。
    030 * このクラスが他と異なるのは、ヘッダのみ記述した場合、ヘッダとして使われず、ボディとしてのみ繰返し
    031 * 使われます。また、bodyFormats のみの記述も可能です。
    032 *
    033 * このクラスは、ViewForm_HTMLFormatTable クラスの代替えとしても使用できます。
    034 * その場合は、thead のみ指定すれば、同じフォームが tbody にも適用されます。
    035 * これは、まさに、ViewForm_HTMLFormatTable と同じです。
    036 * (※ 上記仕様が、未実装でしたので、対応しました。 5.6.3.3 (2013/04/19) )
    037 *
    038 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。
    039 * 各HTMLのタグに必要な setter/getterメソッドのみ，追加定義しています。
    040 *
    041 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。
    042 *
    043 * <table class="plain">
    044 *   <caption>ヘッダ と ボディ の組み合わせ</caption>
    045 *   <tr><th>番号</th><th>headerFormat</th><th>bodyFormats</th><th>現状動作    </th><th>変更後(5.6.3.3以降)      </th></tr>
    046 *   <tr><td>①  </td><td>あり        </td><td>なし       </td><td>headerのみ  </td><td>body の繰り返し          </td></tr>
    047 *   <tr><td>②  </td><td>なし        </td><td>あり       </td><td>エラー      </td><td>bodyFormats のみ繰り返す </td></tr>
    048 *   <tr><td>③  </td><td>あり        </td><td>あり       </td><td>それぞれ動作</td><td>← 同じ                  </td></tr>
    049 *   <tr><td>④  </td><td>なし        </td><td>なし       </td><td>エラー      </td><td>← 同じ                  </td></tr>
    050 * </table>
    051 *
    052 * @og.rev 3.7.1.1 (2005/05/23) 新規作成
    053 * @og.rev 5.6.3.3 (2013/04/19) 処理変更
    054 * @og.group 画面表示
    055 *
    056 * @version  4.0
    057 * @author       Kazuhiko Hasegawa
    058 * @since    JDK5.0,
    059 */
    060public class ViewForm_CustomData extends ViewForm_HTMLTable     {
    061        /** このプログラムのVERSION文字列を設定します。   {@value} */
    062        private static final String VERSION = "6.4.4.2 (2016/04/01)" ;
    063
    064        private TableFormatter          headerFormat    ;
    065        private TableFormatter[]        bodyFormats             ;
    066        private TableFormatter          footerFormat    ;
    067        private int                                     bodyFormatsCount;
    068
    069        private static final int BODYFORMAT_MAX_COUNT = 10;
    070
    071        /**
    072         * デフォルトコンストラクター
    073         *
    074         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    075         */
    076        public ViewForm_CustomData() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    077
    078        /**
    079         * DBTableModel から HTML文字列を作成して返します。
    080         * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
    081         * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
    082         *
    083         * @og.rev 4.3.1.0 (2008/09/08) フォーマットが設定されていない場合のエラー追加・編集行のみを表示する属性(isSkipNoEdit)追加
    084         * @og.rev 5.6.3.3 (2013/04/19) headerFormatのみ、bodyFormatsのみ対応
    085         * @og.rev 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    086         * @og.rev 6.3.9.0 (2015/11/06) 引数にTableFormatterを渡して、処理の共有化を図る。
    087         * @og.rev 6.4.4.2 (2016/04/01) TableFormatterのタイプ別値取得処理の共通部をまとめる。
    088         *
    089         * @param  startNo        表示開始位置
    090         * @param  pageSize   表示件数
    091         *
    092         * @return      DBTableModelから作成された HTML文字列
    093         * @og.rtnNotNull
    094         */
    095        @Override
    096        public String create( final int startNo, final int pageSize )  {
    097                if( getRowCount() == 0 ) { return ""; } // 暫定処置
    098
    099                // 5.6.3.3 (2013/04/19) headerFormatのみ、bodyFormatsのみ対応
    100                headerLine       = null;                // 3.5.3.1 (2003/10/31) キャッシュクリア
    101
    102                final int lastNo = getLastNo( startNo, pageSize );
    103
    104                // 5.6.3.3 (2013/04/19) headerFormatのみ、bodyFormatsのみ対応
    105                if( headerFormat != null ) {
    106                        headerFormat.makeFormat( getDBTableModel() );   // 3.5.6.2 (2004/07/05) 移動
    107                        // 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    108                        setFormatNoDisplay( headerFormat );
    109                }
    110
    111                // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している
    112                // bodyFormatsCount が、0 でない場合は、bodyFormats は、設定済みなので、null チェック不要
    113//              if( bodyFormatsCount != 0 ) {
    114                if( bodyFormatsCount > 0 ) {
    115                        for( int i=0; i<bodyFormatsCount; i++ ) {
    116                                bodyFormats[i].makeFormat( getDBTableModel() );
    117                                // 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    118                                setFormatNoDisplay( bodyFormats[i] );
    119                        }
    120                }
    121
    122                final StringBuilder out = new StringBuilder( BUFFER_LARGE );
    123                out.append( getHeader() );
    124                for( int row=startNo; row<lastNo; row++ ) {
    125                        if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; } // 4.3.1.0 (2008/09/08)
    126                        for( int i=0; i<bodyFormatsCount; i++ ) {
    127                                final TableFormatter bodyFormat = bodyFormats[i];
    128                                if( ! bodyFormat.isUse( row,getDBTableModel() ) ) { continue; }         // 3.5.4.0 (2003/11/25)
    129
    130                                int cl = 0;
    131                                for( ; cl<bodyFormat.getLocationSize(); cl++ ) {
    132                                        final String fmt = bodyFormat.getFormat(cl);
    133                                        out.append( fmt );                      // 3.5.0.0
    134
    135                                        final int loc = bodyFormat.getLocation(cl);     // 3.5.5.0
    136                                        if( loc >= 0 ) {
    137                                                // 6.4.4.2 (2016/04/01) 処理の共通部をまとめる。
    138                                                out.append( getTypeCaseValue( bodyFormat.getType(cl),row,loc ) );
    139                                        }
    140                                        else {
    141                                                out.append( bodyFormat.getSystemFormat(row,loc) );
    142                                        }
    143                                }
    144                                out.append( bodyFormat.getFormat(cl) );
    145                        }
    146                }
    147
    148                if( footerFormat != null ) {
    149                        // 6.3.9.0 (2015/11/06) 引数にTableFormatterを渡して、処理の共有化を図る。
    150                        out.append( getTableFoot( footerFormat ) );
    151                }
    152
    153                return out.toString();
    154        }
    155
    156        /**
    157         * 内容をクリア(初期化)します。
    158         *
    159         */
    160        @Override
    161        public void clear() {
    162                super.clear();
    163                headerFormat                    = null;
    164                bodyFormats                             = null;
    165                footerFormat                    = null;
    166                bodyFormatsCount                = 0;
    167        }
    168
    169        /**
    170         * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。
    171         *
    172         * @og.rev 6.4.4.2 (2016/04/01) TableFormatterのタイプ別値取得処理の共通部をまとめる。
    173         *
    174         * @return      テーブルのヘッダータグ文字列
    175         * @og.rtnNotNull
    176         */
    177        @Override
    178        protected String getHeader() {
    179                // 6.3.9.1 (2015/11/27) A method should have only one exit point, and that should be the last statement in the method.(PMD)
    180
    181                if( headerLine == null ) {
    182                        if( headerFormat == null ) { headerLine = ""; }
    183                        else {
    184                                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    185
    186                                int cl = 0;
    187                                for( ; cl<headerFormat.getLocationSize(); cl++ ) {
    188                                        buf.append( headerFormat.getFormat(cl) );
    189                                        final int loc = headerFormat.getLocation(cl);
    190                                        // 6.4.4.2 (2016/04/01)
    191                                        if( loc >= 0 ) {
    192                                                buf.append( getTypeCaseValue( headerFormat.getType(cl),-1,loc ) );
    193                                        }
    194                                }
    195                                buf.append( headerFormat.getFormat(cl) ).append( CR );
    196
    197                                headerLine = buf.toString();
    198                        }
    199                }
    200                return headerLine ;
    201        }
    202
    203        /**
    204         * DBTableModel から テーブルのタグ文字列を作成して返します。
    205         *
    206         * @og.rev 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    207         * @og.rev 6.3.9.0 (2015/11/06) 引数にTableFormatterを渡して、処理の共有化を図る。
    208         * @og.rev 6.4.4.2 (2016/04/01) TableFormatterのタイプ別値取得処理の共通部をまとめる。
    209         *
    210         * @param       footerFormat TableFormatterオブジェクト
    211         * @return      テーブルのタグ文字列
    212         * @og.rtnNotNull
    213         */
    214        @Override
    215        protected String getTableFoot( final TableFormatter footerFormat ) {
    216                footerFormat.makeFormat( getDBTableModel() );
    217                // 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
    218                setFormatNoDisplay( footerFormat );
    219
    220                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    221
    222                int cl = 0;
    223                for( ; cl<footerFormat.getLocationSize(); cl++ ) {
    224                        final int loc = footerFormat.getLocation(cl);
    225                        // 6.4.4.2 (2016/04/01)
    226                        if( loc >= 0 ) {
    227                                buf.append( getTypeCaseValue( footerFormat.getType(cl),-1,loc ) );
    228                        }
    229                }
    230                buf.append( footerFormat.getFormat(cl) ).append( CR );
    231
    232                return buf.toString();
    233        }
    234
    235        /**
    236         * フォーマットを設定します。
    237         *
    238         * @og.rev 5.6.3.3 (2013/04/19) headerFormatのみの場合、bodyFormats として使う。
    239         *
    240         * @param       list    TableFormatterのリスト
    241         */
    242        @Override
    243        public void setFormatterList( final List<TableFormatter> list ) {               // 4.3.3.6 (2008/11/15) Generics警告対応
    244                bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT];
    245
    246                bodyFormatsCount = 0;
    247                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
    248                for( final TableFormatter format : list ) {
    249//              for( int i=0; i<list.size(); i++ ) {
    250//                      final TableFormatter format = list.get( i );            // 4.3.3.6 (2008/11/15) Generics警告対応
    251
    252                        switch( format.getFormatType() ) {
    253                                case TYPE_HEAD : headerFormat = format; break;
    254                                case TYPE_BODY : bodyFormats[bodyFormatsCount++] = format; break;
    255                                case TYPE_FOOT : footerFormat = format; break;
    256                                default : final String errMsg = "FormatterType の定義外の値が指定されました。";
    257                                                // 4.3.4.4 (2009/01/01)
    258                                                  throw new HybsSystemException( errMsg );
    259                        }
    260                }
    261
    262                // 5.6.3.3 (2013/04/19) headerFormatのみの場合、bodyFormats として使う。
    263                if( bodyFormatsCount == 0 ) {           // bodyFormats がない場合は、headerFormatをコピーする。
    264                        if( headerFormat == null ) {
    265                                final String errMsg = "thead タグか、または、tbody タグによるフォーマットの指定は必須です。";
    266                                throw new HybsSystemException( errMsg );
    267                        }
    268                        else {
    269                                bodyFormats[bodyFormatsCount++] = headerFormat;
    270                                headerFormat = null;
    271                        }
    272                }
    273        }
    274
    275        /**
    276         * フォーマットメソッドを使用できるかどうかを問い合わせます。
    277         *
    278         * @return  使用可能(true)/ 使用不可能 (false)
    279         */
    280        @Override
    281        public boolean canUseFormat() {
    282                return true;
    283        }
    284
    285        /**
    286         * 表示項目の編集(並び替え)が可能かどうかを返します。
    287         *
    288         * @og.rev 5.1.6.0 (2010/05/01) 新規追加
    289         *
    290         * @return      表示項目の編集(並び替え)が可能かどうか(false:不可能)
    291         */
    292        @Override
    293        public boolean isEditable() {
    294                return false;
    295        }
    296}