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 org.opengion.fukurou.util.StringUtil;
019import org.opengion.hayabusa.common.HybsSystemException;
020
021/**
022 * 検索結果を自動的に表形式に変換する、テーブル作成クラスです。
023 *
024 * ユーザー単位に表示するカラムの順番、表示可非を指定できるように対応します。
025 * setColumnDisplay( final String columnName ) に、指定された順番に
026 * 表示するというHTMLFormatTable の簡易版として用意します。
027 * 各HTMLのタグに必要な setter/getterメソッドのみ、追加定義しています。
028 *
029 * AbstractViewForm を継承している為、ロケールに応じたラベルを出力させる事が出来ます。
030 *
031 * @og.group 画面表示
032 * @og.rev 5.1.6.0 (2010/05/01) 新規作成
033 *
034 * @version  4.0
035 * @author       Kazuhiko Hasegawa
036 * @since    JDK5.0,
037 */
038public class ViewForm_HTMLSeqClmTable extends ViewForm_HTMLTable {
039        /** このプログラムのVERSION文字列を設定します。   {@value} */
040        private static final String VERSION = "8.5.6.1 (2024/03/29)" ;
041
042        /** 8.5.6.1 (2024/03/29) thead に、固定の id (header) と class 属性(row_hu)を共通に定義します。 */
043        private static final String THEAD_TAG2  = "<thead id=\"header\" class=\"row_hu\" >" + CR ;
044
045        private int[]   clmNo           ;               // 5.1.6.0 (2010/05/01)
046        private int             clmCnt          = -1;   // 5.1.6.0 (2010/05/01)
047
048        private String  viewClms        ;
049
050        /**
051         * デフォルトコンストラクター
052         *
053         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
054         */
055        public ViewForm_HTMLSeqClmTable() { super(); }          // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
056
057        /**
058         * DBTableModel から HTML文字列を作成して返します。
059         * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
060         * 表示残りデータが pageSize 以下の場合は、残りのデータをすべて出力します。
061         *
062         * @og.rev 5.5.4.2 (2012/07/13) editName指定時の編集対応
063         * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
064         * @og.rev 6.4.2.1 (2016/02/05) clmNo == null のエラー判定を先に行う。
065         * @og.rev 6.8.1.1 (2017/07/22) ckboxTD変数は、&lt;td&gt; から &lt;td に変更します(タグの最後が記述されていない状態でもらう)。
066         *
067         * @param  startNo        表示開始位置
068         * @param  pageSize   表示件数
069         *
070         * @return      DBTableModelから作成された HTML文字列
071         * @og.rtnNotNull
072         */
073        @Override
074        public String create( final int startNo, final int pageSize )  {
075                if( getRowCount() == 0 ) { return ""; } // 暫定処置
076
077                // 6.4.2.1 (2016/02/05) エラー判定を先に行う。
078                if( clmNo == null ) {
079                        final String errMsg = "#setColumnDisplay(String)を先に実行しておいてください。" ;
080                        throw new HybsSystemException( errMsg );
081                }
082
083                headerLine       = null;
084
085                final StringBuilder out = new StringBuilder( BUFFER_LARGE )
086                        .append( getCountForm( startNo,pageSize ) )
087                        .append( getHeader() )
088                        .append("<tbody>").append( CR );                // 6.4.1.1 (2016/01/16) PMD refactoring.
089
090                int bgClrCnt = 0;
091                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point.
092                final String ckboxTD = "  <td";                                 // 6.8.1.1 (2017/07/22)
093                final int lastNo = getLastNo( startNo, pageSize );
094                final int blc = getBackLinkCount();
095                final int hsc = getHeaderSkipCount();                   // 3.5.2.0 (2003/10/20)
096                int hscCnt   = 1;                                                               // 3.5.2.0 (2003/10/20)
097                for( int row=startNo; row<lastNo; row++ ) {
098                        if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; } // 4.3.1.0 (2008/09/08)
099                        out.append(" <tr").append( getBgColorCycleClass( bgClrCnt++,row ) );
100                        if( isNoTransition() ) {        // 4.3.3.0 (2008/10/01)
101                                out.append( getHiddenRowValue( row ) );
102                        }
103                        out.append('>').append( CR );                           // 6.0.2.5 (2014/10/31) char を append する。
104
105                        // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加
106                        if( isNumberDisplay() ) {
107                                out.append( makeCheckbox( ckboxTD, row, blc ) ).append( CR );
108                        }
109
110                        // 5.1.6.0 (2010/05/01)
111                        for( int clm=0; clm<clmCnt; clm++ ) {
112                                final int column = clmNo[clm];
113                                if( isColumnDisplay( column ) ) {
114                                        out.append("  <td>")
115                                                .append( getValueLabel(row,column) )
116                                                .append("</td>").append( CR );
117                                }
118                        }
119
120                        // 5.5.4.2 (2012/07/13) mustとmuntAnyでwritableのものはdisplay:noneで出力する(可能な限り余分なものは出力しない)
121                        for( int column=0; column<clmCnt; column++ ) {
122                                if( !isColumnDisplay( column ) && ( isMustColumn( column ) || isMustAnyColumn(column) ) && isColumnWritable( column) ) {
123                                        out.append("  <td style=\"display:none\">")
124                                                .append( getValueLabel(row,column) )
125                                                .append("</td>").append( CR );
126                                }
127                        }
128
129                        out.append(" </tr>").append( CR );
130
131                        // 3.5.2.0 (2003/10/20) ヘッダー繰り返し属性( headerSkipCount )を採用
132                        if( hsc > 0 && hscCnt % hsc == 0 ) {
133                                out.append( getHeadLine() );
134                                hscCnt = 1;
135                        }
136                        else {
137                                hscCnt ++ ;
138                        }
139                }
140                out.append("</tbody>").append( CR )
141                        .append("</table>").append( CR )
142                        .append( getScrollBarEndDiv() );        // 3.8.0.3 (2005/07/15)
143
144                return out.toString();
145        }
146
147        /**
148         * DBTableModel から テーブルのタグ文字列を作成して返します。
149         *
150         * @og.rev 3.5.1.0 (2003/10/03) Noカラムに、numberType 属性を追加
151         * @og.rev 3.5.2.0 (2003/10/20) ヘッダー繰り返し部をgetHeadLine()へ移動
152         * @og.rev 3.5.3.1 (2003/10/31) VERCHAR2 を VARCHAR2 に修正。
153         * @og.rev 3.5.5.0 (2004/03/12) No 欄そのものの作成判断ロジックを追加
154         * @og.rev 3.5.6.5 (2004/08/09) thead に、id="header" を追加
155         * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属性(CLS_NM)から、DBTYPEに変更
156         * @og.rev 4.0.0.0 (2005/01/31) 新規作成(getColumnClassName ⇒ getColumnDbType)
157         * @og.rev 6.1.2.0 (2015/01/24) HTML5 で colgroup が効かない対応
158         * @og.rev 5.9.1.2 (2015/10/23) 自己終了警告対応
159         * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
160         * @og.rev 6.4.2.1 (2016/02/05) clmNo == null のエラー判定を先に行う。
161         * @og.rev 6.4.4.1 (2016/03/18) NUMBER_DISPLAYを、static final 定数化します。
162         * @og.rev 6.4.5.0 (2016/04/08) メソッド変更( getColumnDbType(int) → getClassName(int) )
163         * @og.rev 6.4.6.1 (2016/06/03) DbType とClassName が複雑化しているため、とりあえずの暫定対策。
164         * @og.rev 5.9.14.3 (2016/11/25) editでの表示順変更に対応
165         * @og.rev 6.8.1.0 (2017/07/14) HTML5対応ヘッダー出力設定時に、ブラウザを互換設定したときの対応。
166         * @og.rev 6.9.5.0 (2018/04/23) USE_IE7_HEADER 廃止(false固定)
167         * @og.rev 7.0.4.0 (2019/05/31) colgroup 廃止
168         * @og.rev 8.5.6.1 (2024/03/29) thead に、固定の id と class 属性を共通に定義します。
169         *
170         * @return      テーブルのタグ文字列
171         * @og.rtnNotNull
172         */
173        @Override
174        protected String getTableHead() {
175                // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
176                // 6.4.2.1 (2016/02/05) エラー判定を先に行う。
177                if( clmNo == null ) {
178                        final String errMsg = "#setColumnDisplay(String)を先に実行しておいてください。" ;
179                        throw new HybsSystemException( errMsg );
180                }
181
182                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
183
184                // 5.7.5.0 (2014/04/04) HTML5 で colgroup が効かない対応
185                // 本当は、tableタグの前に入れたかったが、ややこしいので table タグの直後に入れます。
186                // 互換モードでない場合専用。処理速度を気にするより、処理を一か所にまとめておきます。
187                // 6.9.5.0 (2018/04/23) USE_IE7_HEADER 廃止(false固定)
188//              if( !useIE7Header ) {
189                        // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(type="text/css" 不要)
190//                      buf.append( "<style type=\"text/css\">" ).append( CR );
191                        buf.append( "<style>" ).append( CR );
192                        int ad = 1;
193                        if( isNumberDisplay() ) {
194                                makeNthChild( buf,2,"BIT" );
195                                makeNthChild( buf,3,"S9"  );
196                                ad = 4;
197                        }
198
199                        // 6.4.2.1 (2016/02/05) 変数名がややこしいので、変更しておきます。
200                        // 5.9.14.3 (2016/11/25) editでの表示順変更に対応
201        //              final int cnt = getColumnCount();
202        //              for( int clm=0; clm<cnt; clm++ ) {
203                        for( int clm=0; clm<clmCnt; clm++ ) { // 5.9.14.3 (2016/11/25) 表示順変更に対応していなかった
204                                final int column = clmNo[clm];
205                                if( isColumnDisplay( column ) ) {
206                                        // 6.4.6.1 (2016/06/03) DbType とClassName が複雑化しているため、とりあえずの暫定対策。
207                                        makeNthChild( buf,ad,getClassName(column) );            // 6.4.6.1 (2016/06/03)
208                                        ad++ ;                  // tdタグの順番なので、表示する場合のみカウントする。
209                                }
210                        }
211                        buf.append( "</style>" ).append( CR );
212//              }
213
214//              // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加
215//              // 7.0.4.0 (2019/05/31) colgroup 廃止
216//              if( isNumberDisplay() ) {
217//                      // 5.9.1.2 (2015/10/23) 自己終了警告対応
218//                      // 6.4.4.1 (2016/03/18) NUMBER_DISPLAYを、static final 定数化します。
219//                      buf.append( NUMBER_DISPLAY );           // 6.8.1.0 (2017/07/14) HTML5ネイティブ時でも、出力します。
220//              }
221
222                // 5.1.6.0 (2010/05/01)
223                // 7.0.4.0 (2019/05/31) colgroup 廃止
224//              for( int clm=0; clm<clmCnt; clm++ ) {
225//                      final int column = clmNo[clm];
226//                      if( isColumnDisplay( column ) ) {
227//                              buf.append("<colgroup class=\"" )
228//                                      .append( getClassName(column) )                 // 6.4.5.0 (2016/04/08)
229//                                      // 5.9.1.2 (2015/10/23) 自己終了警告対応
230//                                      .append("\"><!-- --></colgroup>")
231//                                      .append( CR );
232//                      }
233//              }
234
235                // 3.5.2.0 (2003/10/20) ヘッダー繰り返し部をgetHeadLine()へ移動
236//              buf.append("<thead id=\"header\">").append( CR )                                        // 3.5.6.5 (2004/08/09)
237                buf.append( THEAD_TAG2 )                                                                                        // 8.5.6.1 (2024/03/29) ※ row_hu を使用
238                        .append( getHeadLine() )
239                        .append("</thead>").append( CR );
240
241                return buf.toString();
242        }
243
244        /**
245         * ヘッダー繰り返し部を、getTableHead()メソッドから分離。
246         *
247         * @og.rev 3.5.2.0 (2003/10/20) 新規作成
248         * @og.rev 3.5.4.3 (2004/01/05) useCheckControl 属性の機能を追加
249         * @og.rev 3.5.4.5 (2004/01/23) thタグの属性設定出来る様に新規追加。
250         * @og.rev 3.5.4.6 (2004/01/30) numberType="none" 時の処理を追加(Noラベルを出さない)
251         * @og.rev 3.5.4.7 (2004/02/06) ヘッダーにソート機能用のリンクを追加します。
252         * @og.rev 3.7.0.1 (2005/01/31) 全件チェックコントロール処理変更
253         * @og.rev 6.1.2.0 (2015/01/24) キャッシュを返すのを、#getHeadLine() に移動。
254         * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
255         * @og.rev 6.4.2.1 (2016/02/05) clmNo == null のエラー判定を先に行う。
256         * @og.rev 8.5.6.1 (2024/03/29) thead に、固定の id と class 属性を共通に定義します。
257         *
258         * @param       thTag タグの文字列
259         *
260         * @return      テーブルのタグ文字列
261         * @og.rtnNotNull
262         */
263        protected String getHeadLine( final String thTag ) {
264                // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
265                // 6.4.2.1 (2016/02/05) エラー判定を先に行う。
266                if( clmNo == null ) {
267                        final String errMsg = "#setColumnDisplay(String)を先に実行しておいてください。" ;
268                        throw new HybsSystemException( errMsg );
269                }
270
271                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
272//                      .append("<tr class=\"row_hu\">").append( CR );
273                        .append("<tr>").append( CR );                                                   // 8.5.6.1 (2024/03/29) row_h は、theadタグへ
274
275                // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加
276                if( isNumberDisplay() ) {
277                        // 3.5.4.3 (2004/01/05) 追加分
278                        if( isUseCheckControl() && "checkbox".equals( getSelectedType() ) ) {
279                                // 3.5.4.5 (2004/01/23) thタグの属性設定出来る様に変更。
280                                // 6.0.2.5 (2014/10/31) char を append する。
281                                buf.append( thTag ).append("></th>")
282                                        .append( thTag ).append('>').append( getAllCheckControl() ).append("</th>")
283                                        .append( thTag ).append('>').append( getNumberHeader()    ).append("</th>");    // 3.5.4.6 (2004/01/30)
284                        }
285                        else {
286                                // 3.5.4.5 (2004/01/23) thタグの属性設定出来る様に変更。
287                                buf.append( thTag ).append(" colspan='3'>").append( getNumberHeader() ).append("</th>");        // 3.5.4.6 (2004/01/30)
288                        }
289                }
290                buf.append( CR );
291
292                // 5.1.6.0 (2010/05/01)
293                for( int clm=0; clm<clmCnt; clm++ ) {
294                        final int column = clmNo[clm];
295                        if( isColumnDisplay( column ) ) {
296                                // 3.5.4.5 (2004/01/23) thタグの属性設定出来る様に変更。
297                                buf.append( thTag ).append('>')         // 6.0.2.5 (2014/10/31) char を append する。
298                                        .append( getSortedColumnLabel(column) )
299                                        .append("</th>").append( CR );
300                        }
301                }
302                buf.append("</tr>").append( CR );
303
304                return buf.toString();                          // 6.1.2.0 (2015/01/24)
305        }
306
307        /**
308         * 表示可能カラム名を、CSV形式で与えます。
309         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
310         * setColumnDisplay( int column,boolean rw ) の簡易版です。
311         * null を与えた場合は、なにもしません。
312         *
313         * @param       columnName      カラム名
314         */
315        @Override
316        public void setColumnDisplay( final String columnName ) {
317                super.setColumnDisplay( columnName );
318
319                if( columnName != null ) {
320                        final String[] clmNames = StringUtil.csv2Array( columnName );
321                        clmCnt = clmNames.length;
322                        clmNo  = new int[clmCnt];
323                        for( int i=0; i<clmCnt; i++ ) {
324                                clmNo[i] = getColumnNo( clmNames[i] );
325                        }
326                }
327                viewClms = columnName;
328        }
329
330        /**
331         * ビューで表示したカラムの一覧をCSV形式で返します。
332         *
333         * @og.rev 5.1.6.0 (2010/05/01) 新規追加
334         * @og.rev 6.0.2.4 (2014/10/17) Edit機能で、オリジナルのカラム列を取得する必要がある。
335         *
336         * @return      ビューで表示したカラムの一覧
337         */
338        @Override
339        public String getViewClms() {
340                // 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)
341                return viewClms == null ? super.getViewClms() : viewClms ;
342        }
343}