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.html;
017
018import java.util.Arrays;
019import java.util.Iterator;
020import java.util.List;
021import java.util.Map;
022import java.util.concurrent.ConcurrentMap;                                              // 6.4.3.3 (2016/03/04)
023import java.util.stream.Collectors;                                                             // 6.4.3.4 (2016/03/11)
024import java.util.regex.Pattern;                                                                 // 8.5.6.1 (2024/03/29)
025import java.io.Writer;
026import java.io.IOException;
027
028import org.opengion.fukurou.system.HybsConst ;                                  // 6.1.0.0 (2014/12/26)
029import org.opengion.fukurou.util.StringUtil;
030import org.opengion.fukurou.util.Attributes;
031
032import org.opengion.hayabusa.common.HybsSystem;
033import org.opengion.hayabusa.common.HybsSystemException;
034import org.opengion.hayabusa.db.DBColumn;
035import org.opengion.hayabusa.db.DBTableModel;
036import org.opengion.hayabusa.db.DBColumnConfig;
037import org.opengion.hayabusa.resource.ResourceManager;
038
039/**
040 * ViewForm インターフェース の実装Abstractクラスです。
041 * これを共通のスーパークラスとして 各種表示フォーム(例:HTML表示等)に使います。
042 *
043 * このクラス は、setter/getterメソッドのデフォルト実装を提供しています。
044 * 各種表示フォームに対応したサブクラス上で、 create() をオーバーライドして下さい。
045 *
046 * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
047 * @og.group 画面表示
048 *
049 * @version  4.0
050 * @author       Kazuhiko Hasegawa
051 * @since    JDK5.0,
052 */
053public abstract class AbstractViewForm implements ViewForm {
054        // 5.2.1.0 (2010/10/01)
055        // 6.1.1.0 (2015/01/17) BulkSet用の表示サイズは、一覧側のサイズになります。
056
057        /** システムの改行コードを設定します。*/
058        protected static final String CR                 = HybsConst.CR;                        // 6.1.0.0 (2014/12/26) refactoring
059        /** StringBilderなどの初期値を設定します。   {@value} */
060        protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE;     // 6.1.0.0 (2014/12/26) refactoring
061        /** StringBilderなどの初期値を設定します。   {@value} */
062        protected static final int BUFFER_LARGE  = HybsConst.BUFFER_LARGE;      // 6.1.0.0 (2014/12/26) refactoring
063
064        /** 8.5.6.1 (2024/03/29) thead に、固定の id (header) と class 属性(row_h)を共通に定義します。 */
065        protected static final String THEAD_TAG  = "<thead id=\"header\" class=\"row_h\" >" + CR ;
066
067        // 6.4.3.3 (2016/03/04) class属性(ColumnのDBType)置換で、td属性に[カラム]があると、誤ってそちらがセットされてしまう対応。
068        // ※ 正規表現の「.」は、改行を除く任意の文字なので、改行を含みあい場合は、「[\\s\\S]」とします。
069        // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
070        // ViewForm_HTMLCustomTable と ViewForm_HTMLFormatTable で定義していたローカル変数を移動します。
071        private static final Pattern TD_BODY = Pattern.compile( "[\\s\\S]*<td[^>]*>[\\s]*" );           // 6.4.4.2 (2016/04/01) tdタグが完了して、BODY部分の解析に入る。
072        private static final Pattern TD_END  = Pattern.compile( "[^<]*>[^<>]*" );                                       // 何らかのタグが完了して、BODY部分の解析に入る。
073
074        /** 3.8.0.3 (2005/07/15) 新しいヘッダー固定用のDIV要素を分ける。 */
075        private static final String LAYER_ST0 = "" ;
076        private static final String LAYER_END0 = "" ;
077//      private static final String LAYER_END2 = "<a href=\"#top\" name=\"h_end\" id=\"h_end\" ></a></div></div></div></div>" ;
078        private static final String LAYER_END2 = "</div></div></div></div>" ;           // 8.5.4.1 (2023/12/22) HTML5廃止対応
079
080        // 5.1.8.0 (2010/07/01) groupClass のタイプを定義します。
081        /** カラムのグループ化指定の enum static 定数です。 */
082        private enum CLM_GRP { KIGO , CHAR }            // 8.5.4.2 (2024/01/12) PMD 7.0.0 UnnecessarySemicolon
083//      private static enum CLM_GRP { KIGO , CHAR };
084
085        /** メニューの名前 */
086        private String                  name                    = "";
087        private DBTableModel    table                   ;
088        private DBColumn[]              dbColumn                ;
089        private boolean[]               clmWritable             ;
090        private boolean[]               writeCtrl               ;                       // 3.8.0.9 (2005/10/17)
091        private boolean[]               clmDisplay              ;
092        private boolean[]               tdClassClms             ;                       // 8.0.1.0 (2021/11/02)
093        private String                  tdClass                 ;                       // 8.0.1.0 (2021/11/02)
094        private boolean[]               clmGroup                ;                       // 3.8.5.0 (2006/03/20)
095        private String                  groupClass              = "";           // 5.1.8.0 (2010/07/01)
096        private String                  noGroupClass    ;                       // 8.2.1.0 (2022/07/15) 未設定は null で判断します。
097        private boolean                 useGroupDir             ;                       // 6.7.3.0 (2017/01/27)
098        private CLM_GRP                 groupType               ;                       // 5.1.8.0 (2010/07/01)
099        private boolean[]               sortKeys                ;                       // 3.6.0.0 (2004/09/17)
100        private boolean[]               useEventCols    ;                       // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
101        private boolean                 useSorterKeys   ;                       // 3.6.0.0 (2004/09/17) 内部変数
102        private String                  sorterQuery             = "";           // 3.6.0.0 (2004/09/17) 内部変数
103        private String                  viewFormID              ;
104        private int                     startNo                 ;
105        private int                     pageSize                = HybsSystem.sysInt( "HTML_PAGESIZE" ) ;
106        /** 1カラム目が writable か? */
107        private boolean                 rowWritableFlag ;
108        private ViewMarker              viewLink                ;
109        private ViewMarker              viewMarker              ;
110        private ViewMarker              editMarker              ;                               // 3.8.6.1 (2006/10/20)
111        private String                  selectedType    = "checkbox";
112        private String                  numberType              = "sequence" ;  // 3.5.1.0 (2003/10/03) 新規作成
113        private int                             numberTypeClm   = -1;                   // 3.5.1.0 (2003/10/03) 新規作成
114        private String[]                numberTypeData  ;                               // 3.5.1.0 (2003/10/03) 新規作成
115        private String                  optTypeAttri    ;
116        private boolean                 noMessage               ;
117        private int                     backLinkCount   ;
118        /** 0:通常ヘッダ、n:n回ごとに現れる */
119        private int                             headerSkipCount ;
120        private boolean                 skip                    = ViewForm.DEFAULT_SKIP;        // 3.5.3.1 (2003/10/31)
121        private int                             useCheckControl ;                               // 3.7.0.1 (2005/01/31)
122        private boolean                 useTableSorter  = HybsSystem.sysBool( "VIEW_USE_TABLE_SORTER" ) ;       // 3.5.4.7 (2004/02/06)
123        private boolean                 numberDisplay   = true ;                // 3.5.5.0 (2004/03/12)
124        private int                             scrollRowNo             = -1;                   // 3.7.0.3 (2005/03/01)
125
126        /** 3.5.4.6 (2004/01/30) ヘッダー文字列を定義しておきます。 */
127        private static final String NO_HEADER = "No" ;
128
129        // 3.5.4.8 (2004/02/23) ViewParamTag のパラメータを受け取ります。
130        /** 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。 */
131        private ConcurrentMap<String,String> viewParam  ;               // 6.4.3.3 (2016/03/04)
132
133        /** 5.5.8.3 (2012/11/17) Stringでなく、Objectタイプをもてるようにする(積上げガント対応) */
134        private List<String[]> viewArrayList    ; // 5.5.9.0 (2012/12/03) ObjectではなくArrayList
135
136        private int columnCount ;       // 3.5.5.7 (2004/05/10)
137        private int rowCount    ;       // 4.0.0 (2006/01/06)
138
139        /** 3.5.6.2 (2004/07/05) ゼブラ模様の指定を、ViewForm としてサポート */
140        // 0(ゼブラなし)、-1(ワーニング)、-2以下(エラー)、1(ゼブラ)、2以上(行数まとめ)
141        private int bgColorCycle   = 1 ;
142        /** 行ごとに色を変更する時の、デフォルトクラス属性 */
143        private static final String BG_COLOR_ROW0 = " class=\"row_0\"";
144        /** 行ごとに色を変更する時の、切り替え後クラス属性 */
145        private static final String BG_COLOR_ROW1 = " class=\"row_1\"";
146
147        /** 行ごとに色を変更する時の、切り替え後クラス属性 */
148        private static final String BG_COLOR_ROWSEL = " class=\"row_sel\"";             // 3.7.0.3 (2005/03/01)
149
150        /** 警告時の行ごとに色を変更する時の、デフォルトクラス属性 */
151        private static final String BG_WARNING_COLOR_ROW0 = " class=\"row_0 row_warning\"";
152        /** 警告時の行ごとに色を変更する時の、切り替え後クラス属性 */
153        private static final String BG_WARNING_COLOR_ROW1 = " class=\"row_1 row_warning\"";
154
155        /** エラー時の行ごとに色を変更する時の、デフォルトクラス属性 */
156        private static final String BG_ERROR_COLOR_ROW0 = " class=\"row_0 row_error\"";
157        /** エラー時の行ごとに色を変更する時の、切り替え後クラス属性 */
158        private static final String BG_ERROR_COLOR_ROW1 = " class=\"row_1 row_error\"";
159
160        private String colorRow0 = BG_COLOR_ROW0 ;
161        private String colorRow1 = BG_COLOR_ROW1 ;
162
163        /** 5.1.8.0 (2010/07/01) 行に対して、動的にクラス属性を付与するカラム名を指定します。 */
164        private int bgColorClsClmNo  = -1;
165
166        // 3.5.6.4 (2004/07/16)
167        private boolean useScrollBar = HybsSystem.sysBool( "VIEW_USE_SCROLLBAR" ) ;
168
169        // 3.6.0.0 (2004/09/17)
170        private boolean firstChecked    ;
171
172        /** 3.7.1.1 (2005/05/31) SEL_ROW機能使用時に、BG_COLOR_ROWSEL の使用 有/無を指定します。 */
173        private boolean useSelRowColor  ;
174
175        /** 4.0.0 (2007/04/16) tableタグを出力するときに付与します。 */
176        private String  clazz                   = "viewTable";
177
178        /** 4.0.0.0 (2007/11/27) ResourceManagerを設定します。(クロス集計で使用) */
179        private ResourceManager resourceManager ;
180
181        /** 4.2.0.0 (2008/03/03) ビューの幅と高さを指定できるようにします。 */
182        private String  height          ;
183        private String  width           ;
184
185        // 4.3.1.0 (2008/09/08)
186        private boolean skipNoEdit      ;
187
188        /** 4.3.3.0 (2008/10/01) 画面遷移なしモード時に各行に出力する行番号及び改廃Cのキーを定義します。 */
189        private static final String HIDDEN_ROW_KEY =    "rid";          // 6.4.1.1 (2016/01/16) hiddenRowKey  → HIDDEN_ROW_KEY refactoring
190        private static final String HIDDEN_CDKH_KEY =   "kh";           // 6.4.1.1 (2016/01/16) hiddenCdkhKey → HIDDEN_CDKH_KEY refactoring
191
192        private boolean noTransition    ;
193
194        /** 5.1.7.0 (2010/06/01) ViewFormのキャッシュ復元を画面ID単位に行う */
195        private String gamenId                  ;
196
197        /** 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能を利用するカラムを指定します。 */
198        private boolean[]       clmBulkSet      ;
199
200        // 5.5.4.2 (2012/07/13) mustとmustAnyを保持する
201        private String[]        nullCheck       ;
202        private String[]        mustAnyCheck;           // 3.8.0.9 (2005/10/17)
203
204        // 5.9.5.3 (2016/02/26)
205        // 6.4.6.1 (2016/06/03) tableId 廃止(利用目的を明確にするため、パラメータ名をviewClassに変更)
206        private String viewClass = "VIEW_" + HybsSystem.TBL_MDL_KEY;    // 初期値
207
208        /**
209         * デフォルトコンストラクター
210         *
211         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
212         */
213        protected AbstractViewForm() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
214
215        /**
216         * 初期化します。
217         * ここでは、内部で使用されているキャッシュをクリアし、
218         * 新しいモデル(DBTableModel)と言語(lang) を元に内部データを再構築します。
219         * なお、テーブルモデルに対してViewFormで変更を加える場合は、変更処理を行った後に
220         * このメソッドを実行するようにして下さい。
221         *
222         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
223         * @og.rev 3.5.6.1 (2004/06/25) lang 言語コード 属性を削除します。
224         * @og.rev 3.5.6.3 (2004/07/12) 呼ばれたら、必ず初期化するように修正(元に戻す)
225         * @og.rev 3.6.0.0 (2004/09/17) sortKeys 追加
226         * @og.rev 3.8.0.9 (2005/10/17) writeCtrl 追加
227         * @og.rev 3.8.5.0 (2006/03/20) clmGroup 追加
228         * @og.rev 4.0.0.0 (2006/01/06) rowCount 追加
229         * @og.rev 4.0.1.0 (2007/12/13) コメントの追加
230         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
231         * @og.rev 5.2.0.0 (2010/09/01) 2回連続登録時に選択行にスクロールしないバグを修正。
232         * @og.rev 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能を利用するカラム(clmBulkSet) 追加
233         * @og.rev 5.5.4.2 (2012/07/13) mustとmustany保持
234         * @og.rev 8.0.1.0 (2021/11/02) tdClassClms,tdClass追加
235         *
236         * @param       table   DBTableModelオブジェクト
237         */
238        @Override       // ViewForm
239        public void init( final DBTableModel table ) {
240                this.table = table;
241                if( table != null ) {
242                        rowCount        = table.getRowCount();                  // 4.0.0 (2006/01/06)
243                        columnCount = table.getColumnCount();
244                        clmWritable = new boolean[columnCount];
245                        writeCtrl       = new boolean[columnCount];             // 3.8.0.9 (2005/10/17)
246                        clmDisplay      = new boolean[columnCount];
247                        tdClassClms     = new boolean[columnCount];             // 8.0.1.0 (2021/11/02)
248                        tdClass         = null  ;                                               // 8.0.1.0 (2021/11/02)
249                        clmGroup        = new boolean[columnCount];             // 3.8.5.0 (2006/03/20)
250                        sortKeys        = new boolean[columnCount];             // 3.6.0.0 (2004/09/17)
251                        dbColumn        = new DBColumn[columnCount];
252                        useEventCols= new boolean[columnCount];         // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
253                        clmBulkSet  = new boolean[columnCount];         // 5.2.1.0 (2010/10/01)
254                        Arrays.fill( clmWritable,DEFAULT_CLM_WRITABLE );        // カラムの書込み許可
255                        Arrays.fill( writeCtrl,false );                                         // 書き込み制御の許可
256                        Arrays.fill( clmDisplay ,true );                                        // カラムの表示許可
257                        Arrays.fill( tdClassClms ,false );                                      // 8.0.1.0 (2021/11/02) tdClassClms,tdClass追加
258                        Arrays.fill( clmGroup ,false );                                         // 3.8.5.0 (2006/03/20) カラムのグループ化
259                        Arrays.fill( sortKeys ,false );                                         // すべてリンクしないに設定する。
260                        Arrays.fill( useEventCols, false );                                     // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
261                        Arrays.fill( clmBulkSet, false );                                       // 5.2.1.0 (2010/10/01)
262                        for( int i=0; i<columnCount; i++ ) {
263                                dbColumn[i] = table.getDBColumn( i );
264                        }
265
266                        // 1カラム目(最初のカラム=配列0番目)が writable か?
267                        rowWritableFlag = "WRITABLE".equalsIgnoreCase( getColumnName(0) );
268
269                        // 5.2.0.0 (2010/09/01) 2回連続登録時に選択行にスクロールしないバグを修正。
270                        scrollRowNo = -1;
271                        firstChecked = false;
272
273                        // 5.5.4.2 (2102/07/13)
274                        nullCheck        = table.getMustArray();
275                        mustAnyCheck = table.getMustAnyArray();
276                }
277        }
278
279        /**
280         * 内部の DBTableModel を返します。
281         *
282         * @return      DBTableModelオブジェクト
283         */
284        @Override       // ViewForm
285        public DBTableModel getDBTableModel() {
286                return table;
287        }
288
289        /**
290         * ViewForm の識別IDをセットします。
291         * これは、ViewFormFactory でプールする場合の識別キーになります。
292         * プールに戻すときに自分自身に この識別IDを使用します。
293         *
294         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
295         * @og.rev 3.5.6.2 (2004/07/05) メソッド名がまぎらわしい為、変更します。
296         *
297         * @param       viewFormID 識別ID
298         */
299        @Override       // ViewForm
300        public void setId( final String viewFormID ) {
301                this.viewFormID = viewFormID;
302        }
303
304        /**
305         * ViewForm の識別IDを返します。
306         * これは、ViewFormFactory でプールする場合の識別キーになります。
307         * プールに戻すときに自分自身に この識別IDを使用します。
308         *
309         * @og.rev 3.5.6.2 (2004/07/05) メソッド名がまぎらわしい為、変更します。
310         *
311         * @return      識別ID
312         */
313        @Override       // ViewForm
314        public String getId() {
315                return viewFormID;
316        }
317
318        /**
319         * DBTableModel から HTML文字列を作成して返します。
320         *
321         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
322         *
323         * @return      DBTableModelから作成された HTML文字列
324         */
325        @Override       // ViewForm
326        public String create() {
327                return create( 0, rowCount );
328        }
329
330        /**
331         * DBTableModel から View文字列を作成して、Writer にセットします。
332         * 処理内容は、create( int , int ) と同じですが、中間の文字列(StringBuilder)
333         * を作成せずに、直接、Writer に書き出します。
334         * よって、データ作成途中でエラーが発生しても、すでにいくつかのデータは
335         * クライアントに返されています。
336         *
337         * @og.rev 5.0.0.1 (2009/08/15) 直接出力用の Writer 引数追加
338         *
339         * @param  startNo        表示開始位置
340         * @param  pageSize   表示件数
341         * @param  wrt            直接登録用の Writer
342         */
343        @Override       // ViewForm
344        public void create( final int startNo, final int pageSize, final Writer wrt ) throws IOException {
345                final String errMsg = "このメソッドは、直接登録用の Writer のビューでのみ使用できます。";
346                throw new UnsupportedOperationException( errMsg );
347        }
348
349        /**
350         * 内容をクリア(初期化)します。
351         *
352         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
353         * @og.rev 3.5.1.0 (2003/10/03) displayNumber 廃止。numberType 新規追加。
354         * @og.rev 3.5.2.0 (2003/10/20) headerSkipCount属性を追加
355         * @og.rev 3.5.3.1 (2003/10/31) skip属性を追加
356         * @og.rev 3.5.4.3 (2004/01/05) useCheckControl属性を追加
357         * @og.rev 3.5.4.3 (2004/01/05) viewFormID属性を削除(初期化しない)
358         * @og.rev 3.5.4.7 (2004/02/06) useTableSorter属性を追加
359         * @og.rev 3.5.4.7 (2004/02/06) columnMaxSize は使用されていないので削除します。
360         * @og.rev 3.5.4.8 (2004/02/23) ViewParamTag のパラメータを追加します。
361         * @og.rev 3.5.5.0 (2004/03/12) numberType 属性の "delete" 値追加に伴なう、numberDisplay 変数の追加。
362         * @og.rev 3.5.6.2 (2004/07/05) bgColorCycle 変数の追加。
363         * @og.rev 3.5.6.4 (2004/07/16) useScrollBar 変数の追加。
364         * @og.rev 3.6.0.0 (2004/09/17) sortKeys , firstChecked , useSorterKeys , sorterQuery 変数の追加。
365         * @og.rev 3.7.0.1 (2005/01/31) 全件チェックコントロール変更( boolean ⇒ int )
366         * @og.rev 3.7.1.1 (2005/05/31) useSelRowColor 変数の追加。
367         * @og.rev 3.8.0.3 (2005/07/15) scrollBarType 変数の追加
368         * @og.rev 3.8.0.9 (2005/10/17) writeCtrl 変数の追加
369         * @og.rev 3.8.5.0 (2006/03/20) clmGroup 変数の追加
370         * @og.rev 3.8.6.1 (2006/10/20) editMarker 変数の追加
371         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
372         * @og.rev 5.1.8.0 (2010/07/01) groupClass , groupType 変数の追加
373         * @og.rev 5.1.8.0 (2010/07/01) bgColorClsClmNo 属性を追加します。
374         * @og.rev 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能を利用するカラム(clmBulkSet) 追加
375         * @og.rev 5.5.4.2 (2012/07/13) mustとmustany追加
376         * @og.rev 5.5.9.0 (2012/12/03) viewArrayList追加(viewObjectは削除)
377         * @og.rev 6.7.3.0 (2017/01/27) useGroupDir追加
378         * @og.rev 8.0.1.0 (2021/11/02) tdClassClms,tdClass追加
379         * @og.rev 8.2.1.0 (2022/07/15) noGroupClass 変数の追加
380         */
381        @Override       // ViewForm
382        public void clear() {
383                name                    = "";                   // メニューの名前
384                table                   = null;
385                dbColumn                = null;
386                clmWritable             = null;
387                writeCtrl               = null;                 // 3.8.0.9 (2005/10/17)
388                clmDisplay              = null;
389                tdClassClms             = null;                 // 8.0.1.0 (2021/11/02)
390                tdClass                 = null;                 // 8.0.1.0 (2021/11/02)
391                clmGroup                = null;                 // 3.8.5.0 (2006/03/20)
392                groupClass              = "";                   // 5.1.8.0 (2010/07/01)
393                noGroupClass    = null;                 // 8.2.1.0 (2022/07/15)
394                useGroupDir             = false;                // 6.7.3.0 (2017/01/27)
395                groupType               = null;                 // 5.1.8.0 (2010/07/01)
396                sortKeys                = null;                 // 3.6.0.0 (2004/09/17)
397                useSorterKeys   = false;                // 3.6.0.0 (2004/09/17)
398                sorterQuery             = "";                   // 3.6.0.0 (2004/09/17)
399                startNo                 = 0 ;
400                pageSize                = HybsSystem.sysInt( "HTML_PAGESIZE" ) ;
401                rowWritableFlag = false;        // 1カラム目が writable か?
402                viewLink                = null;
403                viewMarker              = null;
404                editMarker              = null;         // 3.8.6.1 (2006/10/20)
405                backLinkCount   = 0;
406                selectedType    = "checkbox";
407                numberType              = "sequence";
408                numberTypeClm   = -1;
409                numberTypeData  = null;
410                headerSkipCount = 0;    // 0:通常ヘッダ、n:n回ごとに現れる
411                skip                    = ViewForm.DEFAULT_SKIP;        // 3.5.3.1 (2003/10/31)
412                useCheckControl = 0 ;           // 3.7.0.1 (2005/01/31)
413                viewParam               = null;         // 3.5.4.8 (2004/02/23)
414                viewArrayList   = null;         // 5.5.8.3 (2012/12/03)
415                numberDisplay   = true ;        // 3.5.5.0 (2004/03/12)
416                columnCount             = 0;            // 3.5.5.7 (2004/05/10)
417                bgColorCycle    = 1;            // 3.5.6.2 (2004/07/05)
418                bgColorClsClmNo = -1;           // 5.1.8.0 (2010/07/01)
419                colorRow0               = BG_COLOR_ROW0 ;               // 3.5.6.2 (2004/07/05)
420                colorRow1               = BG_COLOR_ROW1 ;               // 3.5.6.2 (2004/07/05)
421                useScrollBar    = HybsSystem.sysBool( "VIEW_USE_SCROLLBAR" ) ;  // 3.5.6.4 (2004/07/16)
422                firstChecked    = false;
423                useSelRowColor  = false;        // 3.7.1.1 (2005/05/31)
424                height                  = null;         // 4.2.0.0 (2008/03/18)
425                width                   = null;         // 4.2.0.0 (2008/03/18)
426                skipNoEdit              = false;        // 4.3.2.0 (2008/09/10)
427                useEventCols    = null;         // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
428                clmBulkSet              = null;         // 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能を利用するカラム(clmBulkSet) 追加
429                nullCheck               = null;         // 5.5.4.2 (2012/07/13)
430                mustAnyCheck    = null;         // 5.5.4.2 (2012/07/13)
431        }
432
433        /**
434         * テーブルのヘッダーの前に、そのデータの表示範囲を示す文字列を作成します。
435         * [開始No - 終了No]/[件数] です。
436         *
437         * ※ result_info.jsp に id="rowCountMessage" を記述しておき、resultScript.js 内部で
438         *    orgRowCntMsg を見つけて rowCountMessage の場所まで移動させています。
439         *
440         * @og.rev 2.0.0.2 (2002/09/24) [1 - 4]/[4] 等のメッセージ出力後の &lt;br&gt; 出力を中止。
441         * @og.rev 4.3.6.0 (2008/04/01) [1 - 4]/[4]のメッセージをJavaScriptで入れ替えるように変更
442         * @og.rev 4.3.8.0 (2009/08/01) 同メッセージ複数対応及びheadでコントロール可能にする
443         *
444         * @param  stNo    表示開始位置
445         * @param  pgSize  表示件数
446         *
447         * @return      テーブルのヘッダータグ文字列
448         * @og.rtnNotNull
449         */
450        protected String getCountForm( final int stNo, final int pgSize ) {
451                if( noMessage ) { return ""; }
452
453                final int lstNo = stNo+pgSize > rowCount ? rowCount : (stNo+pgSize) ;
454
455                // 8.5.5.1 (2024/02/29) toString() で、return する。
456                // 6.0.2.5 (2014/10/31) char を append する。
457//              final StringBuilder out = new StringBuilder( BUFFER_MIDDLE )
458                return new StringBuilder( BUFFER_MIDDLE )
459                        .append( "<div class=\"orgRowCntMsg\">[" )
460                        .append( stNo+1 ).append( " - " ).append( lstNo )
461                        .append( "]/[" ).append( rowCount )
462                        .append( "]</div>" )
463                        .toString() ;
464//              return out.toString() ;
465        }
466
467        /**
468         * カラムのラベル名を返します。
469         * カラムの項目名に対して、見える形の文字列を返します。
470         * 一般には、リソースバンドルと組合せて、各国ロケール毎にラベルを
471         * 切替えます。
472         *
473         * @param       column カラム番号
474         *
475         * @return      カラムのラベル名
476         */
477        protected String getColumnLabel( final int column ) {
478                return dbColumn[column].getLabel();
479        }
480
481        /**
482         * カラム名を返します。
483         * データベースで検索したときのカラムの項目名を返します。
484         *
485         * @param       column カラム番号
486         *
487         * @return      カラム名
488         */
489        protected String getColumnName( final int column ) {
490                return dbColumn[column].getName();
491        }
492
493        /**
494         * row行、colum列 のデータの値を返します。
495         *
496         * @param       row     行番号
497         * @param       column カラム番号
498         *
499         * @return      row行、colum列 のデータの値
500         */
501        protected String getValue( final int row,final int column ) {
502                return table.getValue( row,column ) ;
503        }
504
505        /**
506         * row行、colum列 のデータの値を返します。
507         * これは、データの値そのものではなく、その値のラベル文字を返します。
508         *
509         * @og.rev 3.8.0.9 (2005/10/17) 互換性確保のメソッド
510         *
511         * @param       row     行番号
512         * @param       column カラム番号
513         *
514         * @return      row行、colum列 のデータの値
515         * @og.rtnNotNull
516         */
517        protected String getRendererValue( final int row,final int column) {
518                return getRendererValue( row,column,getValue( row,column ) );
519        }
520
521        /**
522         * row行、colum列 のデータの値を返します。
523         * これは、データの値そのものではなく、その値のラベル文字を返します。
524         *
525         * @og.rev 3.8.0.9 (2005/10/17) writableControl 追加による引数変更
526         * @og.rev 3.8.5.0 (2006/03/20) clmGroup 追加によるグループ化処理
527         * @og.rev 4.0.0.0 (2005/11/30) 行番号に対応した値を返すように変更します。
528         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
529         * @og.rev 5.1.8.0 (2010/07/01) カラムグループの groupClass 対応
530         * @og.rev 6.7.3.0 (2017/01/27) useGroupDir 追加
531         * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 CollapsibleIfStatements 対応
532         * @og.rev 8.2.1.0 (2022/07/15) noGroupClass 変数の追加
533         *
534         * @param       row             行番号
535         * @param       column  カラム番号
536         * @param       inVal   データの値
537         *
538         * @return      row行、colum列 のデータの値
539         */
540        protected String getRendererValue( final int row,final int column , final String inVal ) {
541                String val = dbColumn[column].getRendererValue( row,inVal );
542
543                // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
544                if( useEventCols[column] && isWritable( row ) ) {
545                        val = dbColumn[column].getEventColumnTag( val, getValue( row,column ), row, false );
546                }
547                if( viewLink != null ) {
548                        val = viewLink.getMarkerString( row,column,val );
549                }
550                if( viewMarker != null ) {
551                        val = viewMarker.getMarkerString( row,column,val );
552                }
553
554                // 5.1.8.0 (2010/07/01) groupClass 対応:空文字の場合を考慮し、最後に処理を行う。
555                // 出力する値が、空文字列なら、前行と同じでも、空文字にしておきます。
556
557                // 6.7.3.0 (2017/01/27) useGroupDir 追加
558                // 8.5.4.2 (2024/01/12) PMD 7.0.0 CollapsibleIfStatements
559//              if( groupType != null && clmGroup[column] && inVal != null && val != null && val.length() > 0 ) {
560//                      if( useGroupDir && column > 0 && inVal.equals( getValue( row,column-1 ) ) ||
561//                              !useGroupDir && row > 0 && row != startNo && inVal.equals( getValue( row-1,column ) ) ) {
562//
563//                              val = groupType == CLM_GRP.KIGO ? groupClass
564//                                                                                              : "<span class=\"" + groupClass + "\">" + val + "</span>";
565//                      }
566//              }
567                if( groupType != null && clmGroup[column] && inVal != null && val != null && val.length() > 0
568                        && ( useGroupDir && column > 0 && inVal.equals( getValue( row,column-1 ) ) ||
569                                !useGroupDir && row > 0 && row != startNo && inVal.equals( getValue( row-1,column ) ) ) ) {
570                                        val = groupType == CLM_GRP.KIGO ? groupClass
571                                                                                                        : "<span class=\"" + groupClass + "\">" + val + "</span>";
572                }
573
574                // 8.2.1.0 (2022/07/15) noGroupClass 変数の追加
575                // 8.5.4.2 (2024/01/12) PMD 7.0.0 CollapsibleIfStatements
576//              if( noGroupClass != null && clmGroup[column] && inVal != null && val != null && val.length() > 0 ) {
577//                      if( useGroupDir && column > 0 && !inVal.equals( getValue( row,column-1 ) ) ||
578//                              !useGroupDir && row > 0 && row != startNo && !inVal.equals( getValue( row-1,column ) ) ) {
579//                              val = "<span class=\"" + noGroupClass + "\">" + val + "</span>";
580//                      }
581//              }
582                if( noGroupClass != null && clmGroup[column] && inVal != null && val != null && val.length() > 0
583                        && ( useGroupDir && column > 0 && !inVal.equals( getValue( row,column-1 ) ) ||
584                                !useGroupDir && row > 0 && row != startNo && !inVal.equals( getValue( row-1,column ) ) ) ) {
585                                        val = "<span class=\"" + noGroupClass + "\">" + val + "</span>";
586                }
587
588                return val;
589        }
590
591        /**
592         * row行、colum列 のデータの値をHTML文字列に変換して返します。
593         * リソースバンドルが登録されている場合は、リソースに応じた
594         * HTML文字列を作成します。
595         *
596         * @og.rev 3.8.0.9 (2005/10/17) writableControl 追加による引数変更
597         * @og.rev 3.8.6.1 (2006/10/20) editMarker 追加
598         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
599         *
600         * @param       row             行番号
601         * @param       column  カラム番号
602         * @param       inVal   データの値
603         *
604         * @return      row行、colum列 のデータの値
605         */
606        protected String getEditorValue( final int row, final int column, final String inVal ) {
607                String val = dbColumn[column].getEditorValue( row,inVal );
608                // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
609                if( useEventCols[column] ) {
610                        val = dbColumn[column].getEventColumnTag( val, getValue( row,column ), row, true );
611                }
612                if( editMarker != null ) {
613                        val = editMarker.getMarkerString( row,column,val );
614                }
615
616                return val;
617        }
618
619        /**
620         * row行、colum列 のデータの値をHTML文字列に変換して返します。
621         * リソースバンドルが登録されている場合は、リソースに応じた
622         * HTML文字列を作成します。
623         * リソースバンドルが登録されていない場合は、getValue( int row,int column )を
624         * 返します。
625         * 新規機能として、writableControl によるエディター・レンデラー指定が出来ます。
626         * その場合、表示/編集ともに、先頭のアンダーバーは削除されます。
627         *
628         * @og.rev 3.8.0.9 (2005/10/17) writableControl によるエディター・レンデラー指定
629         *
630         * @param       row     行番号
631         * @param       column カラム番号
632         *
633         * @return      row行、colum列 のデータの値
634         * @og.rtnNotNull
635         */
636        protected String getValueLabel( final int row, final int column ) {
637                String val = getValue( row,column ) ;
638                boolean isEdit = isColumnWritable( column ) && isWritable( row ) ;
639                if( writeCtrl[column] && val != null && val.length() > 0 && val.charAt(0) == '_' ) {
640                        isEdit = false;
641                        val = val.substring(1);         // 先頭の '_' を削除
642                }
643
644                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
645                return isEdit ? getEditorValue( row,column,val ) : getRendererValue( row,column,val );
646        }
647
648        /**
649         * カラムのクラスを文字列にした名称を返します。
650         * これは、HTML上の各種タグに、データベース定義に応じたクラスを
651         * セットし、CSS(Cascading Style Sheet)の class="xxxxx" とする事により
652         * 各種スタイルを表現するのに使用します。
653         *
654         * ここでは、カラムリソースの DBTYPE 属性で指定の文字列(X,S9,KXなど)を返します。
655         *
656         * ※ 従来は、class属性に使用する値を取得していましたが、
657         *    org.opengion.plugin.view.ViewForm_HTMLTable#makeNthChild( StringBuilder , int , String )
658         *    の引数に渡すことをメインに使用します。
659         *
660         * @og.rev 4.0.0.0 (2005/01/31) 新規作成(getColumnClassName ⇒ getColumnDbType)
661         * @og.rev 5.2.2.0 (2010/11/01) className が VARCHAR2,NUMBER以外の場合は、合わせて出力します。
662         * @og.rev 6.4.4.2 (2016/04/01) contains 判定を行う新しいメソッドを使用します。
663         * @og.rev 6.4.5.0 (2016/04/08) protected化と、純粋なDBTYPE 属性を返すように変更。
664         *
665         * @param   column カラム番号
666         *
667         * @return  カラムの DBTYPE 属性
668         */
669        protected String getColumnDbType( final int column ) {
670                return dbColumn[column].getDbType();
671        }
672
673        /**
674         * カラムのクラスを文字列にした名称を返します。
675         * 内容的には、カラムの className の値と、dbTypeの値をマージした値になります。
676         * さらに、editorAttributesの "class"キーワードの値もマージします。
677         * ただし、この値には、must属性も設定されているため、それだけは除外します。
678         * 各種スタイルを表現するのに使用します。
679         *
680         * @og.rev 6.4.5.0 (2016/04/08) 新規追加
681         *
682         * @param   column カラム番号
683         *
684         * @return  カラムの DBTYPE 属性
685         */
686        protected String getClassName( final int column ) {
687                return dbColumn[column].getClassName();
688        }
689
690        /**
691         * カラムのクラスを文字列を、既存の StringBuilder に追加します。
692         * class 属性を複数使用する場合は、スペースで連結します。
693         * カラム番号より、getClassName(column)で取得した class名を使用します。
694         * idx 以降に存在する class 文字列を見つけて追記します。
695         * 戻り値はなく、引数のStringBuilder を書き換えます。
696         *
697         * @og.rev 8.5.4.2 (2024/01/12) class 属性がフォーマット中に存在する場合、追記になる。
698         * @og.rev 8.5.6.1 (2024/03/29) class属性を挿入する位置(コーテーション の次)を求める
699         *
700         * @param   buf StringBuilderオブジェクト
701         * @param   column カラム番号
702         * @param   idx class属性の検索を開始する文字数
703         */
704        protected void insertClassName( final StringBuilder buf,final int column,final int idx ) {
705                // 8.5.6.1 (2024/03/29) class属性を挿入する位置(コーテーション の次)を求める
706                final int clsidx = insertClassIndx( buf.toString(),idx );               // メソッドの共通化のため。処理速度はとりあえず無視
707                if( clsidx >= 0 ) {                                                                                             // メソッド側で、+1 しているので、0 は来ない
708                        buf.insert( clsidx, getClassName(column) + " " );                       // class=" の直後に追加し、スペースを入れて連結する。
709                }
710                else {
711                        final String tdclass = " class=\"" + getClassName(column) + "\" ";
712                        buf.insert( idx+3, tdclass );   // +3 は、"<td" の後ろという意味。fmtでなくそれ以前に戻る必要がある。
713                }
714
715//              final int clsidx = buf.indexOf( "class",idx );
716//              if( clsidx >= 0 ) {
717//                      // さらに、コーテーションの位置を探す。
718//                      final int didx = buf.indexOf( "\"",clsidx );    // ダブルコーテーション の位置
719//                      final int sidx = buf.indexOf( "'",clsidx );             // シングルコーテーション の位置
720//                      final int insidx;
721//                      if( didx >= 0 && sidx >= 0 ) {                                  // どちらも存在する場合は、
722//                              insidx = didx < sidx ? didx : sidx;                     // class に近い方が優先
723//                      }
724//                      else {                                                                                  // それ以外(どちらかが 負)
725//                              insidx = didx > sidx ? didx : sidx;                     // 正(大きい方)を優先
726//                      }
727//
728//                      buf.insert( insidx+1, getClassName(column) + " " );     // class=" の直後に追加し、スペースを入れて連結する。
729//              }
730//              else {
731//                      final String tdclass = " class=\"" + getClassName(column) + "\" ";
732//                      buf.insert( idx+3, tdclass );   // +3 は、"<td" の後ろという意味。fmtでなくそれ以前に戻る必要がある。
733//              }
734        }
735
736        /**
737         * カラムのクラスを文字列を、既存の String に追加します。
738         * Stringなので、insert ではなく、前後の substring に分割して合成します。
739         * class 属性を複数使用する場合は、スペースで連結します。
740         * カラム番号より、getClassName(column)で取得した class名を使用します。
741         * idx 以降に存在する class 文字列を見つけて追記します。
742         * 戻り値は合成した文字列を返します。
743         *
744         * @og.rev 8.5.4.2 (2024/01/12) class 属性がフォーマット中に存在する場合、追記になる。
745         * @og.rev 8.5.6.1 (2024/03/29) class属性を挿入する位置(コーテーション の次)を求める
746         *
747         * @param   str Stringオブジェクト
748         * @param   column カラム番号
749         * @param   idx class属性の検索を開始する文字数
750         *
751         * @return  合成した文字列
752         */
753        protected String insertClassName( final String str,final int column,final int idx ) {
754                final String rtn;
755
756                // 8.5.6.1 (2024/03/29) class属性を挿入する位置(コーテーション の次)を求める
757                final int clsidx = insertClassIndx( str,idx );
758                if( clsidx >= 0 ) {                                                                                             // メソッド側で、+1 しているので、0 は来ない
759                        rtn = str.substring( 0,clsidx ) + getClassName(column) + " " + str.substring( clsidx ) ;
760                }
761                else {
762                        final String tdclass = " class=\"" + getClassName(column) + "\" ";
763                        rtn = str.substring( 0,idx+3 ) + tdclass + str.substring( idx+3 ) ;             // idx+3 は、<tr の3文字分
764                }
765                return rtn;
766
767//              final int clsidx = str.indexOf( "class",idx );
768//              if( clsidx >= 0 ) {
769//                      // さらに、コーテーションの位置を探す。
770//                      final int didx = str.indexOf( '"',clsidx );             // ダブルコーテーション の位置
771//                      final int sidx = str.indexOf( '\'',clsidx );    // シングルコーテーション の位置
772//                      final int insidx;
773//                      if( didx >= 0 && sidx >= 0 ) {                                  // どちらも存在する場合は、
774//                              insidx = didx < sidx ? didx : sidx;                     // class に近い方が優先
775//                      }
776//                      else {                                                                                  // それ以外(どちらかが 負)
777//                              insidx = didx > sidx ? didx : sidx;                     // 正(大きい方)を優先
778//                      }
779//
780//                      rtn = str.substring( 0,insidx+1 ) + getClassName(column) + " " + str.substring( insidx+1 ) ;
781//              }
782//              else {
783//                      final String tdclass = " class=\"" + getClassName(column) + "\" ";
784//                      rtn = str.substring( 0,idx+3 ) + tdclass + str.substring( idx+3 ) ;
785//              }
786//              return rtn;
787        }
788
789        /**
790         * class属性を挿入する位置(コーテーション の次)を返します。
791         *
792         * class属性を含まない場合は、-1 を返します。
793         *
794         * @og.rev 8.5.6.1 (2024/03/29) class属性を挿入する位置(コーテーション の次)を求める
795         *
796         * @param       str 検査対象となる文字列オブジェクト
797         * @param   idx class属性の検索を開始する位置
798         *
799         * @return      class属性を含む場合の挿入位置。含まない場合は、-1
800         */
801        private int insertClassIndx( final String str,final int idx ) {
802                int clsidx = str.indexOf( "class",idx );
803                if( clsidx >= 0 ) {
804                        // さらに、コーテーションの位置を探す。
805                        final int didx = str.indexOf( '"',clsidx );             // ダブルコーテーション の位置
806                        final int sidx = str.indexOf( '\'',clsidx );    // シングルコーテーション の位置
807                        if( didx >= 0 && sidx >= 0 ) {                                  // どちらも存在する場合は、
808                                clsidx = didx < sidx ? didx : sidx;                     // class に近い方が優先
809                        }
810                        else {                                                                                  // それ以外(どちらかが 負)
811                                clsidx = didx > sidx ? didx : sidx;                     // 正(大きい方)を優先
812                        }
813                        clsidx++;               // 挿入位置なので、+1 しておきます。
814                }
815                return clsidx;
816        }
817
818        /**
819         * カラムが書き込み可能かどうかを返します。
820         *
821         * @param       column カラム番号
822         *
823         * @return      書込み可能(true)/不可能(false)
824         */
825        protected boolean isColumnWritable( final int column ) {
826                return clmWritable[column];
827        }
828
829        /**
830         * カラムが書き込み可能かどうかをセットします。
831         *
832         * @param       column カラム番号
833         * @param       rw 書込み可能(true)/不可能(false)
834         */
835        @Override       // ViewForm
836        public void setColumnWritable( final int column,final boolean rw ) {
837                clmWritable[column] = rw;
838        }
839
840        /**
841         * 書き込み可能カラム名を、CSV形式で与えます。
842         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
843         * setColumnWritable( int column,boolean rw ) の簡易版です。
844         * null を与えた場合は、なにもしません。
845         * また、全カラムについて、有効にする場合は、columnName="*" を設定します。
846         *
847         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
848         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
849         *
850         * @param       columnName      カラム名
851         */
852        @Override       // ViewForm
853        public void setColumnWritable( final String columnName ) {
854                if( columnName != null ) {
855                        setBooleanArray( columnName,true,clmWritable );
856
857                        // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
858                        setUseEventCols();
859                }
860        }
861
862        /**
863         * 書き込み不可カラム名を、CSV形式で与えます。
864         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
865         * null を与えた場合は、なにもしません。
866         * また、全カラムについて、有効にする場合は、columnName="*" を設定します。
867         *
868         * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
869         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
870         *
871         * @param       columnName      カラム名
872         */
873        @Override       // ViewForm
874        public void setNoWritable( final String columnName ) {
875                if( columnName != null ) {
876                        setBooleanArray( columnName,false,clmWritable );
877                        // 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
878                        setUseEventCols();
879                }
880        }
881
882        /**
883         * 各項目がイベントカラムをするかどうかをセットします。
884         *
885         * @og.rev 5.1.7.0 (2010/06/01) 新規作成(動的プルダウン実装見直し)
886         */
887        private void setUseEventCols() {
888                for( int column=0; column<dbColumn.length; column++ ) {
889                        final String evCols = dbColumn[column].getEventColumn();
890                        if( evCols != null && evCols.length() > 0 ) {
891                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
892//                              final String[] evColsArr = StringUtil.csv2Array( evCols );
893//                              for( int i=0; i<evColsArr.length; i++ ) {
894//                                      String evCol = evColsArr[i];
895                                final String[] evColsArr = StringUtil.csv2Array( evCols );
896                                for( final String tmp : evColsArr ) {
897                                        String evCol = tmp;
898                                        if( evCol.charAt(0) == '_' ) { evCol = evCol.substring( 1 ); }
899                                        if( isColumnWritable( table.getColumnNo( evCol ) ) ) {
900                                                useEventCols[column] = true;
901                                                break;
902                                        }
903                                }
904                        }
905                }
906        }
907
908        /**
909         * 行指定の書込み許可を返します。
910         *
911         * @og.rev 3.5.4.2 (2003/12/15) writable カラムが "2" のときも、書き込み許可とする
912         * @og.rev 3.5.5.7 (2004/05/10) 判定ロジックを若干見直します。
913         *
914         * @param       row     行番号
915         *
916         * @return      書込み可能(true)/不可能(false)
917         */
918        protected boolean isWritable( final int row ) {
919                boolean rtn = table.isRowWritable( row );
920                if( rtn && rowWritableFlag ) {
921                        final String val = table.getValue( row,0 );
922                        rtn = "TRUE".equalsIgnoreCase( val )
923                                                || "1".equalsIgnoreCase( val )
924                                                || "2".equalsIgnoreCase( val ) ;
925
926                        if( ! rtn &&
927                                ! "FALSE".equalsIgnoreCase( val ) &&
928                                ! "0".equalsIgnoreCase( val ) &&
929                                ! "".equalsIgnoreCase( val ) ) {
930                                        final String errMsg = "writable は、TRUE,FALSE,0,1,2,null 以外指定できません。" +
931                                                                        "  row=[" + (row+1) + "]  val=[" + val + "]";
932                                        throw new HybsSystemException( errMsg );
933                        }
934                }
935                return rtn;
936        }
937
938        /**
939         * 書き込み可能な行(rowWritable == true)のチェックボックスに対して
940         * 初期値を 選択済みにするか、非選択済みにするかを指定します。
941         *
942         * @og.rev 3.5.4.2 (2003/12/15) writable カラムが "2" のとき、チェックを付ける。
943         *
944         * @param       row 行の指定
945         *
946         * @return      チェックON(true)/チェックOFF(false)
947         */
948        protected boolean isChecked( final int row ) {
949                boolean rtn = table.isRowChecked( row );
950                if( rowWritableFlag ) {
951                        final String val = table.getValue( row,0 );
952                        rtn = rtn || "2".equalsIgnoreCase( val ) ;
953                }
954                return rtn;
955        }
956
957        /**
958         * チェック済みの行の先頭に、フォーカスを当てる処理で、チェックの一つ前の
959         * 行番号欄にダミーのリンクを作成する為の判定を行います。
960         * つまり、指定の行番号の次の値が、チェックされているかどうかを判断します。
961         * さらに、これは、一番上位にチェックされている番号の時のみ
962         * 返します。(表示テーブル中、最高一回のみ、true が返る。)
963         *
964         * @og.rev 3.6.0.0 (2004/09/17) 新規作成
965         * @og.rev 3.7.0.3 (2005/03/01) setScrollRowNo の対応
966         * @og.rev 3.8.8.3 (2007/02/09) 最初の選択行 より指定行番号へのフォーカスを優先
967         * @og.rev 4.2.3.1 (2008/06/11) 1件目がチェックされている場合は、対象外とする。
968         * @og.rev 4.2.4.0 (2008/06/25) 1件目対象外の判定で、指定行番号へのフォーカスを優先する。
969         * @og.rev 5.1.1.1 (2009/12/02) 選択行アンカーは、自身の行に出す(default.js#focus2()も合わせて変更)
970         *
971         * @param       row     行の指定
972         *
973         * @return      チェックON(true)/チェックOFF(false)
974         */
975        protected boolean isFirstChecked( final int row ) {
976
977                // 最初の1回のみ、true を返す。よって、元がtrue なら、false を返す。
978                if( firstChecked ) { return false; }
979
980                // 指定の次の行を見るため、範囲オーバーしていないか確認
981                if( row >= rowCount ) { return false; } // 5.1.1.1 (2009/12/02)
982
983                final boolean rtn;
984                // 3.8.8.3 (2007/02/09) 最初の選択行 より指定行番号へのフォーカスを優先
985                if( scrollRowNo >= 0 ) {
986                        rtn = row == scrollRowNo ; // 5.1.1.1 (2009/12/02)
987                }
988                else {
989                        // 1件目がチェックされている場合は、対象外とする。4.2.3.1 (2008/06/11)
990                        if( row == 0 && table.isRowChecked( row ) ) {
991                                firstChecked = true;
992                                return false;
993                        }
994
995                        rtn = table.isRowChecked( row ); // 5.1.1.1 (2009/12/02)
996                }
997
998                // 最初の1回のみ、true を返す。よって、元がtrue なら、false を返す。
999                if( rtn ) { firstChecked = true; }
1000                return rtn;
1001        }
1002
1003        /**
1004         * その行が、処理対象かどうかをチェックします。
1005         * 処理対象かどうかは、書き込み可能な行(rowWritable == true)
1006         * で且つ チェックされた行(rowChecked == true) とします。
1007         * 例えば、NEXT/PREVでスキップ等の処理を行う場合は、 処理対象以外を
1008         * スキップすることで実現できます。
1009         *
1010         * @param       row     行番号
1011         *
1012         * @return       処理対象(true)/処理対象でない(false)
1013         */
1014        @Override       // ViewForm
1015        public boolean isMarked( final int row ) {
1016                return isWritable( row ) && isChecked( row ) ;
1017        }
1018
1019        /**
1020         * カラムが表示可能かどうかを返します。
1021         * もし、表示不可の場合は、このカラムの全データが表示対象から外されます。
1022         *
1023         * @param       column カラム番号
1024         *
1025         * @return      表示可能(true)/不可能(false)
1026         */
1027        protected boolean isColumnDisplay( final int column ) {
1028                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
1029                // 条件変更注意
1030                return !( rowWritableFlag && column == 0 ) && clmDisplay[column];
1031        }
1032
1033        /**
1034         * 表示可能なカラムの数を返します。
1035         *
1036         * @return      表示可能なカラム数
1037         */
1038        protected int getColumnDisplayCount() {
1039                int rtn = 0;
1040                for( int i=0; i<columnCount; i++ ) {
1041                        if( isColumnDisplay(i) ) { rtn++ ; }
1042                }
1043
1044                return rtn;
1045        }
1046
1047        /**
1048         * カラムが表示可能かどうかをセットします。
1049         * DBColumnのROLE属性による表示可否は、ViewFormTag で設定されます。
1050         *
1051         * @param       column カラム番号
1052         * @param       rw 表示可能(true)/不可能(false)
1053         */
1054        @Override       // ViewForm
1055        public void setColumnDisplay( final int column,final boolean rw ) {
1056                clmDisplay[column] = rw;
1057        }
1058
1059        /**
1060         * 表示可能カラム名を、CSV形式で与えます。
1061         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
1062         * setColumnDisplay( int column,boolean rw ) の簡易版です。
1063         * null を与えた場合は、なにもしません。
1064         * また、全カラムについて、有効にする場合は、columnName="*" を設定します。
1065         *
1066         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
1067         *
1068         * @param       columnName      カラム名
1069         */
1070        @Override       // ViewForm
1071        public void setColumnDisplay( final String columnName ) {
1072                setBooleanArray( columnName,true,clmDisplay );
1073        }
1074
1075        /**
1076         * 表示不可カラム名を、CSV形式で与えます。
1077         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
1078         * null を与えた場合は、なにもしません。
1079         * また、全カラムについて、有効にする場合は、columnName="*" を設定します。
1080         *
1081         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
1082         *
1083         * @param       columnName      カラム名
1084         */
1085        @Override       // ViewForm
1086        public void setNoDisplay( final String columnName ) {
1087                setBooleanArray( columnName,false,clmDisplay );
1088        }
1089
1090        /**
1091         * 指定のカラム(CSV指定)に、指定のクラス属性を追加します。。
1092         *
1093         * どちらかが、nullか、空文字列の場合は、無視します。
1094         *
1095         * @og.rev 8.0.1.0 (2021/11/02) tdClassClms,tdClass追加
1096         *
1097         * @param       clms    指定のクラス属性をtd に追加するカラム (CSV形式) (例:"OYA,KO,HJO,SU,DYSET,DYUPD")
1098         * @param       tdCls   td に追加するクラス属性
1099         */
1100        @Override       // ViewForm
1101        public void setTdClass( final String clms,final String tdCls ) {
1102                if( !StringUtil.isNull( clms,tdCls ) ) {
1103                        setBooleanArray( clms,true,tdClassClms );
1104                        tdClass = " class='" + tdCls + "'" ;
1105                }
1106        }
1107
1108        /**
1109         * setTdClassでクラス属性が指定されている場合は、class属性を追加した文字列を返します。
1110         *
1111         * 無指定の場合は、空文字列を返します。
1112         *
1113         * @og.rev 8.0.1.0 (2021/11/02) tdClassClms,tdClass追加
1114         *
1115         * @param       column カラム番号
1116         * @return      display:none;(true)/通常(false)
1117         */
1118        protected String getTdClass( final int column ) {
1119                return tdClassClms[column] ? tdClass : "" ;
1120        }
1121
1122        /**
1123         * 同一表示データをまとめる(表示しない)カラム名を、CSV形式で与えます。
1124         *
1125         * これは、カラムのグループ化指定を行います。
1126         * 同じカラム番号で一つ上の行番号と同じ内容の場合に、表示しないというものです。
1127         * 対応は、表示(Renderer)時のみとします。
1128         * カラム単位なので、新しいゼブラによる色分けは行いません。(任意のカラムに適用できる為)
1129         * また、ファイル出力などのデータ自身は変更されていませんので、そのままデータが落ちます。
1130         * また、全カラムについて、有効にする場合は、group="*" を設定します。
1131         *
1132         * @og.rev 3.8.5.0 (2006/03/20) 新規追加
1133         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
1134         *
1135         * @param       group まとめるカラム名(CSV形式)
1136         */
1137        @Override       // ViewForm
1138        public void setColumnGroup( final String group ) {
1139                if( group != null ) {
1140                        if( groupType == null ) { groupType = CLM_GRP.KIGO ; }
1141                        setBooleanArray( group,true,clmGroup );
1142                }
1143        }
1144
1145        /**
1146         * 同一表示データをまとめないカラム名を、CSV形式で与えます。
1147         *
1148         * これは、カラムのグループ化指定で、同一でもまとめないカラムを指定するほうが簡単な場合に
1149         * 使用します。例えば、キー情報以外は、グループ化指定したい場合などに便利です。
1150         * 動作は、columnGroup の動きと同じです。(まとめないカラムを指定するだけです。)
1151         *
1152         * これは、同一表示データをまとめるカラム名の指定(columnGroup)と同時にセットする
1153         * ことは出来ません。
1154         * また、全カラムについて、有効にする場合は、group="*" を設定します。
1155         *
1156         * @og.rev 5.1.8.0 (2010/07/01) 新規追加
1157         *
1158         * @param       group まとめるカラム名(CSV形式)
1159         */
1160        public void setNoGroup( final String group ) {
1161                if( group != null ) {
1162                        if( groupType == null ) { groupType = CLM_GRP.KIGO ; }
1163                        setBooleanArray( group,false,clmGroup );
1164                }
1165        }
1166
1167        /**
1168         * 同一表示データをまとめる場合の、表示方法を指定します。
1169         *
1170         * これは、カラムのグループ化指定(columnGroup)を行う場合の、まとめ表示の方法を指定します。
1171         * なにも指定しない場合は、まとめカラムは、表示しない(ゼロ文字列)になります。
1172         * その場合、先の行と同じ場合も、変更されたカラムが、NULL(ゼロ文字列)であった場合も、
1173         * 同じ用に表示されるため、区別が付きません。
1174         * そこで、前の行と同じデータの場合に、特殊な処理を行うことで、区別できるようにします。
1175         * 指定方法が特殊なので、注意が必要です。
1176         *   記号の場合:
1177         *       記号(-- , → , ↓ , * など)が指定された場合は、そのままの文字に置き換えられます。
1178         *   アルファベットの場合:
1179         *       アルファベット(a-z,A-Z)の場合は、&lt;span class="アルファベット"&gt;元の文字&lt;/span&gt;
1180         * 例えば、バックカラーに色を付ける、文字を薄い灰色にする、などできます。
1181         * ただし、データ量が圧倒的に増えるため、大量のデータ等で使用するのは避けたほうが良いと思います。
1182         *
1183         * @og.rev 3.8.5.0 (2006/03/20) 新規追加
1184         * @og.rev 6.3.9.0 (2015/11/06) 判定条件の記述が間違っていた。
1185         *
1186         * @param       grpCls まとめ表示の方法
1187         */
1188        public void setGroupClass( final String grpCls ) {
1189                if( grpCls != null ) {
1190                        groupClass = grpCls ;
1191                        if( groupClass.isEmpty() ) {    // ゼロ文字列の場合
1192                                groupType = CLM_GRP.KIGO ;
1193                        }
1194                        else {
1195                                final char ch = groupClass.charAt(0);
1196                                if( ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ) {        // 6.3.9.0 (2015/11/06)         6.9.7.0 (2018/05/14) PMD Useless parentheses.
1197                                        groupType = CLM_GRP.CHAR ;
1198                                }
1199                                else {
1200                                        groupType = CLM_GRP.KIGO ;
1201                                }
1202                        }
1203                }
1204        }
1205
1206        /**
1207         * 同一表示データ以外の箇所の表示方法を指定します。
1208         *
1209         * これは、カラムのグループ化指定(columnGroup)を行う場合の、まとめ表示しないカラムの表示方法を指定します。
1210         * groupClass と異なり、何らかの値が存在しているはずなので、ここで指定するのは、spanタグ内に
1211         * class属性を付ける場合です。
1212         * groupClass の指定に、アルファベットを使用した場合の動きと同じになります。
1213         *    &lt;span class="アルファベット"&gt;元の文字&lt;/span&gt;
1214         * 例えば、バックカラーに色を付ける、文字を薄い灰色にする、などできます。
1215         * ただし、データ量が圧倒的に増えるため、ほとんどが同じデータで、一部異なる場合に使用するのがお勧めです。
1216         *
1217         * @og.rev 8.2.1.0 (2022/07/15) 新規追加
1218         *
1219         * @param       grpCls まとめ表示の方法
1220         */
1221        public void setNoGroupClass( final String grpCls ) {
1222                if( grpCls != null ) {
1223                        noGroupClass = grpCls ;
1224                }
1225        }
1226
1227        /**
1228         * 同一表示データをまとめる場合に、行(row)か列(column)を指定します(初期値:false:ROW)
1229         *
1230         * これは、カラムのグループ化指定(columnGroup)を行う場合の、まとめ表示の方向を指定します。
1231         * ROW(初期値:false)を指定すると、指定のカラムで、行単位に同一データかどうかを判定します。
1232         * COLUMN(true)を指定すると、columnGroup で指定した順番に、列方向に同一データかどうかを判定します。
1233         * DBTableModelの登録順で、ひとつ前のカラムと比較します。
1234         *
1235         * @og.rev 6.7.3.0 (2017/01/27) 新規追加
1236         *
1237         * @param       dir まとめ表示の方向(false:ROW/true:COLUMN)
1238         * @see         #setColumnGroup( String )
1239         */
1240        @Override       // ViewForm
1241        public void setGroupDir( final boolean dir ) {
1242                useGroupDir = dir;
1243        }
1244
1245        /**
1246         * カラム名リンクソートを表示するカラム名を、CSV形式で与えます。
1247         *
1248         * ヘッダーにソート用リンクを作成する useTableSorter 属性 に対して、
1249         * カラム個別に作成する場合のカラム名をCSV形式で指定します。
1250         * この tableSorterKeys 属性は、useTableSorter 属性 と無関係に、指定した
1251         * カラムのみ、リンクを表示します。
1252         * また、全カラムについて、有効にする場合は、columnName="*" を設定します。
1253         * 例:"OYA,KO,HJO,SU,DYSET,DYUPD"
1254         *
1255         * @og.rev 3.6.0.0 (2004/09/17) 新規作成
1256         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
1257         *
1258         * @param       columnName      カラム名
1259         */
1260        @Override       // ViewForm
1261        public void setTableSorterKeys( final String columnName ) {
1262                if( columnName != null ) {
1263                        setBooleanArray( columnName,true,sortKeys );
1264
1265                        useSorterKeys = true;                           // 使用したことを記憶
1266                }
1267        }
1268
1269        /**
1270         * 各カラムのフィールドのデータ長を返します。
1271         *
1272         * @og.rev 3.5.5.5 (2004/04/23) DBColumn の size と maxlength の 意味を変更
1273         *
1274         * @param       column カラム番号
1275         *
1276         * @return      カラム数
1277         */
1278        protected int getColumnSize( final int column ) {
1279                return dbColumn[column].getTotalSize(); // 4.0.0 (2005/01/31) メソッド名変更
1280        }
1281
1282        /**
1283         * カラム数を返します。
1284         *
1285         * @return      カラム数
1286         */
1287        protected int getColumnCount() {
1288                return columnCount ;
1289        }
1290
1291        /**
1292         * 行数を返します。
1293         *
1294         * @return      行数
1295         */
1296        protected int getRowCount() {
1297                return rowCount;
1298        }
1299
1300        /**
1301         * リストボックスを作成する場合の name をセットします。
1302         *
1303         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1304         *
1305         * @param  name 属性
1306         */
1307        protected void setName( final String name ) {
1308                this.name = name;
1309        }
1310
1311        /**
1312         * リストボックスを作成する場合の name を返します。
1313         *
1314         * @return      name属性
1315         */
1316        protected String getName() {
1317                return name;
1318        }
1319
1320        /**
1321         * カラム名をもとに、そのカラム番号を返します。
1322         * カラム名が存在しない場合は、 HybsSystemException を throw します。
1323         *
1324         * @param       columnName       カラム名
1325         *
1326         * @return      カラム番号
1327         */
1328        protected int getColumnNo( final String columnName ) {
1329                return table.getColumnNo( columnName );
1330        }
1331
1332        /**
1333         * 表示開始位置を返します。
1334         *
1335         * @return      表示開始位置
1336         */
1337        @Override       // ViewForm
1338        public int getStartNo() {
1339                return startNo;
1340        }
1341
1342        /**
1343         * 表示開始位置をセットします。
1344         *
1345         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1346         *
1347         * @param  no    表示開始位置
1348         */
1349        @Override       // ViewForm
1350        public void setStartNo( final int no ) {
1351                if( no >= 0 ) { startNo = no; }
1352        }
1353
1354        /**
1355         * 先頭へ戻るリンク間隔を返します。
1356         *
1357         * @return      backLinkCount    リンク間隔
1358         */
1359        @Override       // ViewForm
1360        public int getBackLinkCount() {
1361                return backLinkCount;
1362        }
1363
1364        /**
1365         * 先頭へ戻るリンク間隔をセットします。
1366         *
1367         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1368         *
1369         * @param  no   リンク間隔
1370         */
1371        @Override       // ViewForm
1372        public void setBackLinkCount( final int no ) {
1373                if( no >= 0 ) { backLinkCount = no; }
1374        }
1375
1376        /**
1377         * ヘッダーを出力する間隔を取得します。
1378         *
1379         * @og.rev 3.5.2.0 (2003/10/20) 新規作成
1380         *
1381         * @return      ヘッダーの表示間隔 ( 0:通常ヘッダ、n:n回ごとに現れる )
1382         */
1383        @Override       // ViewForm
1384        public int getHeaderSkipCount() {
1385                return headerSkipCount;
1386        }
1387
1388        /**
1389         * ヘッダーを出力する間隔をセットします。
1390         *
1391         * 0を指定すると、繰り返しません(つまり、ヘッダーを最初に表示するだけです。)
1392         * 数字を指定すると、その回数毎に、ヘッダーをデータの行に挿入します。
1393         *
1394         * @og.rev 3.5.2.0 (2003/10/20) 新規作成
1395         *
1396         * @param       hsc ヘッダーの表示間隔 ( 0:通常ヘッダ、n:n回ごとに現れる )
1397         */
1398        @Override       // ViewForm
1399        public void setHeaderSkipCount( final int hsc ) {
1400                headerSkipCount = hsc;
1401        }
1402
1403        /**
1404         * 表示件数を取得します。
1405         *
1406         * @return      表示件数
1407         */
1408        @Override       // ViewForm
1409        public int getPageSize() {
1410                return pageSize;
1411        }
1412
1413        /**
1414         * 表示件数をセットします。
1415         *
1416         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1417         *
1418         * @param       psize 表示件数
1419         */
1420        @Override       // ViewForm
1421        public void setPageSize( final int psize ) {
1422                if( psize > 0 ) { pageSize = psize; }
1423        }
1424
1425        /**
1426         * 指定のフォーマットで処理された結果を、引数の StringBuilder に追加します。
1427         *
1428         * 主に、ViewForm_HTMLCustomTable と ViewForm_HTMLFormatTable で使用している
1429         * 同一ソースコードの処理をまとめたメソッドです。
1430         *
1431         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
1432         *
1433         * @param out フォーマットされたデータを追記するための StringBuilder オブジェクト
1434         * @param format データをフォーマットするのに使用する TableFormatter オブジェクト
1435         * @param row データ取得時の行番号
1436         */
1437        protected void addFormatBody( final StringBuilder out, final TableFormatter format, final int row ) {
1438                int cl = 0;
1439                boolean isTdBody = false;                                                                               // 6.4.3.3 (2016/03/04) tdBody処理を行ってよいかどうかのフラグ
1440                for( ; cl<format.getLocationSize(); cl++ ) {
1441                        String fmt = format.getFormat(cl);                              // 3.5.0.0 (2003/09/17)
1442                        final int loc = format.getLocation(cl);                 // 3.5.5.0 (2004/03/12)
1443                        if( ! format.isNoClass() && loc >= 0 ) {                // 3.5.5.7 (2004/05/10)
1444                                if( isTdBody && TD_END.matcher( fmt ).matches() ) {             // 6.4.3.3 (2016/03/04) tdBody許可があり、TDが閉じた場合。
1445                                        isTdBody = false;
1446                                        final int idx = out.lastIndexOf( "<td" );
1447                                        if( idx >= 0 ) {
1448                                                // 8.5.4.2 (2024/01/12) class 属性がフォーマット中に存在する場合、追記になる。
1449                                                insertClassName( out,loc,idx );                                 // 8.5.4.2 (2024/01/12)
1450
1451                                //              final String tdclass = " class=\"" + getClassName(loc) + "\" ";                 // 6.4.5.0 (2016/04/08)
1452                                //              out.insert( idx+3, tdclass );                                   // +3 は、"<td" の後ろという意味。fmtでなくそれ以前に戻る必要がある。
1453                                        }
1454                                }
1455                                if( TD_BODY.matcher( fmt ).matches() ) {                                // 6.4.3.3 (2016/03/04) TDが閉じた場合。
1456                                        // 6.4.3.4 (2016/03/11) tdに、[カラム]が無いケースで、次の[カラム]のクラス属性が、前方すべてのtdにセットされてしまう対応。
1457                                        final int idx = fmt.lastIndexOf( "<td" );
1458                                        if( idx >= 0 ) {        // matchしてるので、あるはず
1459                                                // 8.5.4.2 (2024/01/12) class 属性がフォーマット中に存在する場合、追記になる。
1460                                                fmt = insertClassName( fmt,loc,idx );                   // 8.5.4.2 (2024/01/12)
1461
1462                                //              final String tdclass = " class=\"" + getClassName(loc) + "\" ";                 // 6.4.5.0 (2016/04/08)
1463                                //              fmt = fmt.substring( 0,idx+3 ) + tdclass + fmt.substring( idx+3 ) ;
1464                                        }
1465                                        isTdBody = false;                                                                       // 6.4.3.3 (2016/03/04) これは、要らない・・・はず。
1466                                }
1467                                else {
1468                                        isTdBody = true;                                                                        // TDが閉じていない。
1469                                }
1470                        }
1471                        out.append( fmt );                      // 3.5.0.0
1472
1473                        // 3.5.5.7 (2004/05/10) #,$ 対応
1474                        if( loc >= 0 ) {
1475                                // 6.4.4.2 (2016/04/01) 処理の共通部をまとめる。
1476                                out.append( getTypeCaseValue( format.getType(cl),row,loc ) );
1477                        }
1478                        else {
1479                                out.append( format.getSystemFormat(row,loc) );
1480                        }
1481                }
1482                out.append( format.getFormat(cl) )
1483                        .append("</tbody>").append( CR );
1484        }
1485
1486        /**
1487         * 指定のフォーマットを使用したヘッダー繰り返し文字列を作成します。
1488         *
1489         * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD
1490         *
1491         * @param       format ヘッダーをフォーマットするのに使用する TableFormatter オブジェクト
1492         * @param       thTag タグの文字列
1493         *
1494         * @return      テーブルのタグ文字列
1495         * @og.rtnNotNull
1496         */
1497        protected String getFormatHeadLine( final TableFormatter format, final String thTag ) {
1498                // 7.3.0.0 (2021/01/06) SpotBugs:null チェックなしで null 値を利用対策
1499                if( format == null ) {
1500                        final String errMsg = "ViewTagで canUseFormat() = true の場合、Formatter は必須です。";
1501                        throw new HybsSystemException( errMsg );
1502                }
1503
1504                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
1505                                .append( format.getTrTag() ).append( CR );
1506
1507                // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加
1508                if( isNumberDisplay() ) {
1509                        // 6.1.2.0 (2015/01/24) thTag に、headerFormat.getRowspan() を含ませて受け取る。
1510                        // 3.5.4.3 (2004/01/05) 追加分
1511                        if( isUseCheckControl() && "checkbox".equals( getSelectedType() ) ) {
1512                                buf.append( thTag ).append( "></th>" )
1513                                        .append( thTag ).append( '>' ).append( getAllCheckControl() ).append( "</th>" )
1514                                        .append( thTag ).append( '>' ).append( getNumberHeader()    ).append( "</th>" );
1515                        }
1516                        else {
1517                                buf.append( thTag ).append( " colspan=\"3\">" ).append( getNumberHeader() ).append( "</th>" );  // 6.0.2.5 (2014/10/31) char を append する。
1518                        }
1519                }
1520
1521                int cl = 0;
1522                // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している
1523                // フレームワークとして、create メソッドからしか、呼ばれないため、nullチェック済みです。
1524                for( ; cl<format.getLocationSize(); cl++ ) {
1525                        buf.append( StringUtil.replace( format.getFormat(cl) ,"td","th" ));
1526                        final int loc = format.getLocation(cl);
1527                        // 6.4.3.4 (2016/03/11) ヘッダーでもTableFormatterのType(#,$,!)に対応した値を出すようにする。
1528                        if( loc >= 0 ) {
1529                                // 6.4.4.2 (2016/04/01) 処理の共通部をまとめる。
1530                                buf.append( getTypeCaseValue( format.getType(cl),-1,loc ) );
1531                        }
1532                }
1533                buf.append( StringUtil.replace( format.getFormat(cl) ,"td","th" ) ).append( CR );
1534
1535                return buf.toString();                          // 6.1.2.0 (2015/01/24)
1536
1537        }
1538
1539        /**
1540         * フォーマットを設定します。
1541         * ※ このクラスでは実装されていません。
1542         *
1543         * @og.rev 3.5.4.0 (2003/11/25) 新規作成
1544         * @param list TableFormatterのリスト
1545         */
1546        @Override       // ViewForm
1547        public void setFormatterList( final List<TableFormatter> list ) {               // 4.3.3.6 (2008/11/15) Generics警告対応
1548                final String errMsg = "このメソッドは、フォーマット関係のビューでのみ使用できます。";
1549                throw new UnsupportedOperationException( errMsg );
1550        }
1551
1552        /**
1553         * TableFormatterのタイプ値に対応した値を返します。
1554         *
1555         * タイプ値は、(#,$,!) が指定可能です。
1556         * rowが、-1 の場合は、getSortedColumnLabel(col) を返します。
1557         *
1558         * TableFormatterのタイプ別に値を返します。
1559         *   '#'      : getColumnLabel(loc)
1560         *   '$'      : getRendererValue(row,loc)
1561         *   '!'      : getValue(row,loc)
1562         *   それ以外 : getValueLabel(row,loc)/getSortedColumnLabel(loc)
1563         *
1564         * @og.rev 6.4.4.2 (2016/04/01) TableFormatterのタイプ別値取得
1565         * @og.rev 8.5.5.1 (2024/02/29) switch式の使用
1566         *
1567         * @param type  TableFormatterのタイプ
1568         * @param row    データを取得する行番号
1569         * @param col    データを取得する列番号
1570         * @return タイプ別の値
1571         */
1572        protected String getTypeCaseValue( final char type , final int row , final int col ) {
1573                final String rtn ;
1574
1575                // 8.5.5.1 (2024/02/29) switch式の使用
1576                if( row < 0 ) {
1577//                      switch( type ) {
1578//                              case '#' : rtn = getColumnLabel(col);           break;
1579//                              case '$' : rtn = getRendererValue(0,col);       break;
1580//                              case '!' : rtn = getValue(0,col);                       break;
1581//                              default  : rtn = getSortedColumnLabel(col);     break;          // row が負の場合
1582//                      }
1583                        rtn = switch( type ) {
1584                                case '#' -> getColumnLabel(col);
1585                                case '$' -> getRendererValue(0,col);
1586                                case '!' -> getValue(0,col);
1587                                default  -> getSortedColumnLabel(col);          // row が負の場合
1588                        };
1589                }
1590                else {
1591//                      switch( type ) {
1592//                              case '#' : rtn = getColumnLabel(col);           break;
1593//                              case '$' : rtn = getRendererValue(row,col);     break;
1594//                              case '!' : rtn = getValue(row,col);                     break;
1595//                              default  : rtn = getValueLabel(row,col);        break;          //
1596//                      }
1597                        rtn = switch( type ) {
1598                                case '#' -> getColumnLabel(col);
1599                                case '$' -> getRendererValue(row,col);
1600                                case '!' -> getValue(row,col);
1601                                default  -> getValueLabel(row,col);
1602                        };
1603                }
1604
1605                return rtn;
1606        }
1607
1608        /**
1609         * 表示時の選択用オブジェクトのタイプを指定します。
1610         * ・複数選択可能時は "checkbox" を指定します。
1611         * ・一つだけ選ばせる場合は、"radio" を指定します。
1612         * ・隠しフィールドで全件を選ぶ場合は、"hidden" を指定します。
1613         * ・行番号に関する情報を出さない場合は、"none" を指定します(行番号は表示します)。
1614         * 初期値は、"checkbox" です。
1615         *
1616         * @og.rev 2.2.0.0 (2002/12/17) 選択用オブジェクトのタイプとして"hidden" を追加
1617         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1618         * @og.rev 3.5.1.0 (2003/10/03) displayNumber 廃止。numberType 新規追加。
1619         *
1620         * @param       type 選択用オブジェクトのタイプ( "checkbox"/"radio"/"hidden"/"null" )
1621         */
1622        @Override       // ViewForm
1623        public void setSelectedType( final String type ) {
1624                if( type != null ) {
1625                        if( "checkbox".equalsIgnoreCase( type  ) ||
1626                                "radio".equalsIgnoreCase( type  ) ||
1627                                "hidden".equalsIgnoreCase( type ) ) {
1628                                        selectedType = type;
1629                        }
1630                        else {
1631                                selectedType = null;
1632                        }
1633                }
1634        }
1635
1636        /**
1637         * 表示時の行番号の表示方法を指定します。
1638         * ・sequenceは、1から始まる連番です。
1639         * ・none を指定すると、番号は表示されません。
1640         * ・delete を指定すると、行番号表示そのもののタグを取り除きます。(3.5.5.0 追加)
1641         * ・skip=カラム名を指定すると、そのカラムの値が NULL の場合は、番号をスキップします。
1642         * ・view=カラム名を指定すると、そのカラムの値が、使用されます。(ラベルは付きません)
1643         * skip=XX と、view=XX は、=の前後にスペースを入れないで下さい。
1644         * 初期値は、"sequence" です。
1645         *
1646         * @og.rev 3.5.1.0 (2003/10/03) 新規作成
1647         * @og.rev 3.5.5.0 (2004/03/12) numberType 属性の "delete" 値追加に伴なう、numberDisplay 変数の追加。
1648         * @og.rev 5.3.0.0 (2010/12/01) 左右分割スクロール(SplitViewTag)対応。numberType 再設定時のnumberDisplay初期化
1649         *
1650         * @param       type 行番号の表示方法のタイプ( /sequence/none/delete/skip=カラム名/view=カラム名/ )
1651         */
1652        @Override       // ViewForm
1653        public void setNumberType( final String type ) {
1654
1655                numberType = type ;
1656                numberDisplay = true;   // 5.3.0.0 (2010/12/01) numberType 再設定時のnumberDisplay初期化
1657                if( type != null && !type.startsWith( "seq" ) && !type.startsWith( "none" ) ) {
1658                        if( type.startsWith( "skip=" ) ) {
1659                                numberTypeClm = table.getColumnNo( type.substring( 5 ) );
1660                                numberTypeData = new String[rowCount];
1661                                int cnt = 1;
1662                                for( int i=0; i<rowCount; i++ ) {
1663                                        final String tmp = table.getValue( i,numberTypeClm );
1664                                        if( tmp != null && tmp.length() > 0 ) {
1665                                                numberTypeData[i] = String.valueOf( cnt );
1666                                                cnt++ ;
1667                                        }
1668                                        else {
1669                                                numberTypeData[i] = "" ;
1670                                        }
1671                                }
1672                        }
1673                        else if( type.startsWith( "view=" ) ) {
1674                                numberTypeClm = getColumnNo( type.substring( 5 ) );
1675                        }
1676                        // 3.5.5.0 (2004/03/12)
1677                        else if( type.startsWith( "delete" ) ) {
1678                                numberDisplay = false;
1679                        }
1680                        else {
1681                                // 3.5.5.0 (2004/03/12) 不正な値をエラーチェック
1682                                final String errMsg = "numberType属性の値が不正です。numberType=[" + numberType + "]" +
1683                                                CR +
1684                                                "設定できるのは、sequence/none/delete/skip=カラム名/view=カラム名/ です。";
1685                                throw new HybsSystemException( errMsg );
1686                        }
1687                }
1688        }
1689
1690        /**
1691         * 表示時の選択用オブジェクトのタイプを返します。
1692         * 複数選択可能時は "checkbox"  一つだけ選ばせる場合は、"radio" を指定します。
1693         * 初期値は、"checkbox" です。
1694         * "checkbox"/"radio"/"hidden" 以外の文字列の場合は、null を返します。
1695         *
1696         * @return       選択用オブジェクトのタイプ( "checkbox"/"radio"/"hidden"/"null" )
1697         */
1698        protected String getSelectedType() {
1699                return selectedType ;
1700        }
1701
1702        /**
1703         * No カラムの文字列を取得します。
1704         * setNumberType で指定した、(sequence / none / skip=カラム名 / view=カラム名)に
1705         * 応じた値(レンデラーの値)を返します。
1706         *
1707         * @og.rev 3.5.1.0 (2003/10/03) 新規作成
1708         *
1709         * @param   row 行番号
1710         *
1711         * @return      Noカラムの文字列
1712         */
1713        protected String getNumberData( final int row ) {
1714                String rtn = null;
1715
1716                if( numberType == null || numberType.startsWith( "se" ) ) {     // sequence
1717                        rtn = String.valueOf( row + 1 );
1718                }
1719                else {
1720                        if( numberType.startsWith( "no" ) ) {                   // none
1721                                rtn = "";
1722                        }
1723                        else if( numberType.startsWith( "vi" ) ) {              // view
1724                                rtn = getRendererValue( row,numberTypeClm );
1725                        }
1726                        else if( numberType.startsWith( "sk" ) ) {              // skip
1727                                rtn = numberTypeData[row];
1728                        }
1729                }
1730
1731                return rtn ;
1732        }
1733
1734        /**
1735         * No カラムのヘッダー文字列を取得します。
1736         * setNumberType で指定した、(sequence / none / skip=カラム名 / view=カラム名)に
1737         * 応じた値(ラベル)を返します。
1738         * 具体的には、none 以外は、"No" という文字を、none の時は、""(ゼロストリング)を返します。
1739         *
1740         * @og.rev 3.5.4.6 (2004/01/30) 新規作成
1741         *
1742         * @return       Noカラムのヘッダー文字列
1743         */
1744        protected String getNumberHeader() {
1745                String rtn = NO_HEADER;
1746
1747                if( numberType.startsWith( "no" ) ) {                   // none
1748                        rtn = "";
1749                }
1750
1751                return rtn ;
1752        }
1753
1754        /**
1755         * テーブル等のチェックボックスに属性を付加します
1756         * JavaScript などの HTML基本タグ以外の属性を、そのまま
1757         * チェックボックス/ラジオボタン等に使用します。
1758         *
1759         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
1760         *
1761         * @param       option オプション属性文字列
1762         */
1763        @Override       // ViewForm
1764        public void setOptionTypeAttributes( final String option ) {
1765                optTypeAttri = option;
1766        }
1767
1768        /**
1769         * テーブル等のチェックボックスに属性を付加します
1770         * JavaScript などの HTML基本タグ以外の属性を、そのまま
1771         * チェックボックス/ラジオボタン等に使用します。
1772         *
1773         * @return      オプション属性
1774         */
1775        protected String getOptionTypeAttributes() {
1776                return optTypeAttri ;
1777        }
1778
1779        /**
1780         * 最終表示番号を取得します。
1781         * 最終表示番号は、表示開始位置 + 表示件数 で求まります。
1782         * lastNo = startNo +  pageSize;
1783         *
1784         * ただし、最終表示番号 > データ件数 の場合は、 最終表示番号 = データ件数
1785         * とします。
1786         * なお、表示件数 が -1 の場合は、デフォルトの表示件数を使用します。
1787         *
1788         * @param       startNo    表示開始位置
1789         * @param       pageSize   表示件数
1790         *
1791         * @return      最終表示番号
1792         */
1793        protected int getLastNo( final int startNo, final int pageSize ) {
1794                int lastNo = startNo + ( pageSize < 0 ? getPageSize() : pageSize );
1795                if( lastNo > rowCount ) {
1796                        lastNo = rowCount ;
1797                }
1798
1799                if( rowCount < 0 || startNo < 0 || lastNo < 0 ) {
1800                        final String errMsg = "startNo lastNo の範囲が不正です。" + CR
1801                                                + " startNo=" + startNo + " , lastNo=" + lastNo + " , RowCount=" + rowCount;
1802                        throw new HybsSystemException( errMsg );
1803                }
1804
1805                return lastNo ;
1806        }
1807
1808        /**
1809         * ビューフォームのタイプを返します。
1810         * これは、ViewFormFactory で、org.opengion.hayabusa.html.ViewForm_ + 『type』
1811         * で作成されるサブクラスの 『type』 部分を返します。
1812         *
1813         * @og.rev 3.5.4.3 (2004/01/05) viewFormID を使用するように変更します。
1814         *
1815         * @return      ビューフォームのタイプ
1816         */
1817        @Override       // ViewForm
1818        public String getViewFormType() {
1819                return viewFormID ;
1820        }
1821
1822        /**
1823         * ビューリンクオブジェクトを設定します。
1824         * これは、ViewLink タグで作成された キー(カラム名)とリンク文字列を
1825         * 持っている Attributes オブジェクトを受け取り、内部でリンク表示に
1826         * 使用します。
1827         *
1828         * @og.rev 3.5.6.4 (2004/07/16) table が null の場合は、セットしません。
1829         *
1830         * @param       link    ビューリンクオブジェクト
1831         */
1832        @Override       // ViewForm
1833        public void setViewLink( final ViewMarker link ) {
1834                viewLink = link;
1835                if( viewLink != null && table != null ) {
1836                        viewLink.setDBTableModel( table ) ;
1837                }
1838        }
1839
1840        /**
1841         * ビューマーカーオブジェクトを設定します。
1842         * これは、ViewMarker タグで作成された キー(カラム名)とマーカー文字列を
1843         * 持っている Attributes オブジェクトを受け取り、内部でマーカー表示に
1844         * 使用します。
1845         *
1846         * @og.rev 3.5.6.4 (2004/07/16) table が null の場合は、セットしません。
1847         *
1848         * @param       marker  ビューマーカーオブジェクト
1849         */
1850        @Override       // ViewForm
1851        public void setViewMarker( final ViewMarker marker ) {
1852                viewMarker = marker;
1853                if( viewMarker != null && table != null ) {
1854                        viewMarker.setDBTableModel( table ) ;
1855                }
1856        }
1857
1858        /**
1859         * 編集マーカーオブジェクトを設定します。
1860         * これは、ViewMarker タグで、isRendere="false" で作成された 編集キー(カラム名)と
1861         * マーカー文字列を持っている Attributes オブジェクトを受け取り、内部でマーカー表示に
1862         * 使用します。
1863         *
1864         * @og.rev 3.8.6.1 (2006/10/20) 新規追加
1865         *
1866         * @param       marker  ビューマーカーオブジェクト
1867         */
1868        @Override       // ViewForm
1869        public void setEditMarker( final ViewMarker marker ) {
1870                editMarker = marker;
1871                if( editMarker != null && table != null ) {
1872                        editMarker.setDBTableModel( table ) ;
1873                }
1874        }
1875
1876        /**
1877         * 検索結果メッセージを表示する/しないを設定します
1878         * 初期値は、表示する(false)です。
1879         *
1880         * @param       noMessage [true:表示しない/false:表示する]
1881         */
1882        @Override       // ViewForm
1883        public void setNoMessage( final boolean noMessage ) {
1884                this.noMessage = noMessage;
1885        }
1886
1887        /**
1888         * DBColumn オブジェクトを返します。
1889         *
1890         * @og.rev 3.1.8.0 (2003/05/16) DBColumn オブジェクト取得用のメソッド追加
1891         *
1892         * @param       column カラム番号
1893         *
1894         * @return  DBColumnオブジェクト
1895         */
1896        protected DBColumn getDBColumn( final int column ) {
1897                return dbColumn[column];
1898        }
1899
1900        /**
1901         * カラム(列)にカラムオブジェクトを割り当てます。
1902         * カラムオブジェクトは、ラベルやネームなど、そのカラム情報を
1903         * 保持したオブジェクトです。
1904         *
1905         * @og.rev 5.6.2.3 (2013/03/22) 新規追加
1906         *
1907         * @param   column  カラムオブジェクト
1908         * @param   clm       ヘッダーを適応するカラム(列)
1909         */
1910        protected void setDBColumn( final int column, final DBColumn clm ) {
1911                dbColumn[column] = clm;
1912        }
1913
1914        /**
1915         * チェックの入った行のみを表示させるかどうか指定します。
1916         *
1917         * "true" で、チェックの入った行のみを表示させます。
1918         * 従来は、TextField系のViewに対して、NEXT,PREVでチェックの
1919         * 入った行のみを表示させる機能でしたが、Table系のViewに対しても、
1920         * 同様に機能するように、しました。
1921         * 初期値は、ViewForm.DEFAULT_SKIP です。
1922         *
1923         * @og.rev 3.5.3.1 (2003/10/31) 新規追加
1924         *
1925         * @param       skp チェックの入った行のみを表示させるかどうか(true:のみ表示/false:前件表示)
1926         */
1927        @Override       // ViewForm
1928        public void setSkip( final boolean skp ) {
1929                skip = skp;
1930        }
1931
1932        /**
1933         * チェックの入った行のみを表示させるかどうか(スキップするかどうか)を返します。
1934         *
1935         * skip=true で、かつ、チェックの入っていない行の場合に、trueを返します。
1936         * つまり、skip=trueの場合は、チェックの入っていない行は、スキップするという
1937         * 判断を行います。
1938         * skip属性の初期値は、ViewForm.DEFAULT_SKIP です。
1939         *
1940         * @og.rev 3.5.3.1 (2003/10/31) 新規追加
1941         *
1942         * @param       row     行番号
1943         *
1944         * @return      スキップする(true)/スキップしない(false)
1945         */
1946        protected boolean isSkip( final int row ) {
1947                return skip && ! isChecked( row );
1948        }
1949
1950        /**
1951         * チェックボックスの全チェックを選択するJavaScript の機能を使用するかどうかを指定します。
1952         *
1953         * 1 で、コントロール用のチェックボックスが現れて、この機能を使用することができるようになります。
1954         * 0 は、従来どおりです。
1955         * 使用するにあたり、jsp/commpn/default.js にJavaScriptを設定しておきます。(設定済み)
1956//       * 初期値は、システムパラメータ の VIEW_USE_CHECK_CONTROL です。(0:使用しない)
1957         *
1958         * @og.rev 3.5.4.3 (2004/01/05) 新規追加
1959         * @og.rev 3.7.0.1 (2005/01/31) 全件チェックコントロール変更( boolean ⇒ int )
1960         *
1961         * @param       chCtrl チェックボックスの全チェックを選択する機能を使用するかどうか
1962         *                      (1:使用する/0:使用しない/2:初期値チェック済み)
1963         */
1964        @Override       // ViewForm
1965        public void setUseCheckControl( final int chCtrl ) {
1966                useCheckControl = chCtrl;
1967        }
1968
1969        /**
1970         * チェックボックスの全チェックを選択するJavaScript の機能を使用するかどうかを返します。
1971         *
1972         * 内部的には、(1:使用する/0:使用しない/2:初期値チェック済み)の値を保持していますが、
1973         * タグを作成する場合には、まず、使用するかどうかを指定する必要があるため、
1974         * 1:使用する/2:初期値チェック済み は、true:使用する、0 は、false:使用しない
1975         * を返します。
1976         *
1977         * @og.rev 3.5.4.3 (2004/01/05) 新規追加
1978         *
1979         * @return      チェックボックスの全チェックを選択する機能を使用するかどうか(true:使用する/false:使用しない)
1980         */
1981        protected boolean isUseCheckControl() {
1982                return useCheckControl > 0;
1983        }
1984
1985        /**
1986         * チェックボックスの全チェックを選択する タグ文字列を返します。
1987         *
1988         * 内部的には、(1:使用する/0:使用しない/2:初期値チェック済み)の値を
1989         * 保持していますので、それに対応した文字列を返します。
1990         *
1991         * @og.rev 3.7.0.1 (2005/01/31) 新規追加
1992         * @og.rev 5.1.8.0 (2010/07/01) 全チェックを押した状態で画面遷移した場合にチェック状態を保持する。
1993         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
1994         * @og.rev 8.5.5.1 (2024/02/29) switch式の使用
1995         *
1996         * @return      チェックボックスの全チェックを選択する機能を使用するかどうか
1997         *                      (1:使用する/0:使用しない/2:初期値チェック済み)
1998         */
1999        protected String getAllCheckControl() {
2000                // 8.5.5.1 (2024/02/29) switch式の使用
2001//              final String rtn;
2002//              switch( useCheckControl ) {
2003////                    case 1: rtn = "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" />" ;
2004//                      case 1: rtn = "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" >" ;
2005//                                      break;
2006////                    case 2: rtn = "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" checked=\"checked\" />" ;
2007//                      case 2: rtn = "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" checked=\"checked\" >" ;
2008//                                      break;
2009//                      default : rtn = "" ;
2010//                                      break;          // 6.0.2.5 (2014/10/31) break追記
2011//              }
2012//              return rtn ;
2013                return switch( useCheckControl ) {
2014                        case 1 -> "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" >" ;
2015                        case 2 -> "<input type=\"checkbox\" name=\"ALL_CHECK\" value=\"2\" onclick=\"checkbox(this);\" checked=\"checked\" >" ;
2016                        default -> "" ; // 6.0.2.5 (2014/10/31) break追記
2017                };
2018        }
2019
2020        /**
2021         * ヘッダーにソート用リンクを作成するかどうかを指定します。
2022         *
2023         * "true" で、ヘッダーにソート用リンクを作成します。
2024         * false は、作成しません。
2025         *
2026         * @og.rev 3.5.4.7 (2004/02/06) 新規追加
2027         *
2028         * @param       flag ヘッダーにソート用リンクを作成するかどうか(true:作成する/false:作成しない)
2029         */
2030        @Override       // ViewForm
2031        public void setUseTableSorter( final boolean flag ) {
2032                useTableSorter = flag;
2033        }
2034
2035        /**
2036         * ヘッダーにソート用リンクを作成する時の、リクエスト引数のMapを設定します。
2037         *
2038         * ソート用URLに、リクエスト時の引数を設定する必要があります。
2039         * そのため、リクエスト時のキーと値のセットをMapで指定します。
2040         * このMap は、リクエストキャッシュより取り出します。
2041         * 実装では、このMapを元に、URLのQuery部文字列を作成します。処理過程において、
2042         * このMap を書き換えることは行いません。
2043         *
2044         * @og.rev 3.6.0.0 (2004/09/17) 新規作成
2045         * @og.rev 3.6.0.0 (2004/09/22) 引数が null の時の処理追加
2046         * @og.rev 4.0.0.0 (2005/01/31) Map.keySet より Map.entrySet を使用するように変更
2047         * @og.rev 5.10.1.1 (2018/07/13) keyのマルチバイト文字エンコード対応
2048         *
2049         * @param       map ヘッダーソート時のリンクに追加するリクエスト変数のキャッシュMap
2050         */
2051        @Override       // ViewForm
2052        public void makeTableSorterQuery( final Map<?,?> map ) {                                // 4.3.3.6 (2008/11/15) Generics警告対応
2053                if( map == null ) { return; }                                                                           // 3.6.0.0 (2004/09/22)
2054
2055                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
2056                final Iterator<?> ite = map.entrySet().iterator() ;                                                     // 4.0.0 (2005/01/31)
2057                while( ite.hasNext() ) {
2058                        final Map.Entry<?,?> entry = (Map.Entry<?,?>)ite.next();                                // 4.3.3.6 (2008/11/15) Generics警告対応
2059                        final String key = (String)entry.getKey();
2060                        if( key != null
2061//                                       &&     ! key.equalsIgnoreCase( "command" )
2062                                         &&     ! "command".equalsIgnoreCase( key )                                                     // 8.5.4.2 (2024/01/12) PMD 7.0.0 LiteralsFirstInComparisons
2063                                         &&     ! key.equalsIgnoreCase( HybsSystem.SORT_COLUMNS ) ) {
2064                                final String[] vals = (String[])entry.getValue();                                       // 4.0.0 (2005/01/31)
2065                                if( vals != null ) {
2066                                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
2067//                                      for( int i=0; i<vals.length; i++ ) {
2068                                        for( final String val : vals ) {
2069//                                              buf.append( '&' ).append( key ).append( '=' );                          // 6.0.2.5 (2014/10/31) char を append する。
2070                                                buf.append( '&' ).append( StringUtil.urlEncode( key ) ).append( '=' )   // 5.10.1.1 (2018/07/13)
2071//                                                      .append( StringUtil.urlEncode( vals[i] ) );
2072                                                        .append( StringUtil.urlEncode( val ) );
2073                                        }
2074                                }
2075                        }
2076                }
2077
2078                if( buf.length() > 0 ) {
2079                        sorterQuery = buf.toString();
2080                }
2081        }
2082
2083        /**
2084         * カラムソート機能(リンク)の付いたラベル名を返します。
2085         * カラムの項目名に対して、見える形の文字列を返します。
2086         * 一般には、リソースバンドルと組合せて、各国ロケール毎にラベルを
2087         * 切替えます。
2088         *
2089         * @og.rev 3.5.4.7 (2004/02/06) 新規追加
2090         * @og.rev 3.6.0.0 (2004/09/17) sortKeys の使用によるカラム個別のリンク有無追加
2091         * @og.rev 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能を利用する場合の処理を追加
2092         * @og.rev 5.2.3.0 (2010/12/01) チェックボックスでは、onchange ではなく、onclick でイベントを発生させます。
2093         * @og.rev 5.6.9.1 (2013/10/11) カラム長にカンマが入った場合の対応
2094         * @og.rev 5.7.8.1 (2014/07/18) カラム長が 1000 では、少ない為。(HTML5ではエラーになる為)
2095         * @og.rev 6.0.2.0 (2014/09/19) Bulkset エラー回避
2096         * @og.rev 6.1.1.0 (2015/01/17) Bulkset関係( ViewLength を使用、左寄せ、SLABEL設定 )
2097         * @og.rev 6.2.0.0 (2015/02/27) class="W100" を追加することで、テーブル幅いっぱいの入力枠にする。
2098         * @og.rev 6.2.1.0 (2015/03/13) 動的カラム(COLUMN)は、TEXT に置き換える。
2099         * @og.rev 6.2.2.2 (2015/04/03) NO_MAXLEN キーの値が、"true" の場合、maxlength を強制削除する。
2100         * @og.rev 6.2.2.4 (2015/04/24) class="W100"の追加条件に、dbType 制限をかけます。
2101         * @og.rev 5.9.23.0 (2017/08/10) useSorterKeysが無い場合でもspanは外側に付ける
2102         * @og.rev 6.8.1.4 (2017/08/25) must の取り消し。これは、config.setEditorAttributes( attri ); の副作用で、config から、must をremoveする必要が出てきました。
2103         * @og.rev 6.9.9.2 (2018/09/18) ソートキーのマルチバイト文字エンコード対応
2104         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
2105         * @og.rev 8.5.3.0 (2023/09/08) DynamicAttributes対応
2106         *
2107         * @param       column カラム番号
2108         *
2109         * @return      ソート機能(リンク)の付いたラベル名
2110         */
2111        protected String getSortedColumnLabel( final int column ) {
2112                // 6.4.2.1 (2016/02/05) PMD refactoring. Prefer StringBuffer over += for concatenating strings
2113                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
2114
2115                final String clmLbl = getColumnLabel( column ) ;
2116
2117                if( useSorterKeys && sortKeys[column] || ! useSorterKeys && useTableSorter ) {  // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
2118                        rtn.append( "<a href=\"?command=VIEW&" )
2119                                .append( HybsSystem.SORT_COLUMNS ).append( '=' )
2120        //                      .append( dbColumn[column].getName() )
2121                                .append( StringUtil.urlEncode( dbColumn[column].getName() ) )                   // 6.9.9.2 (2018/09/18) ソートキーのマルチバイト文字エンコード対応
2122                                .append( sorterQuery ).append( "\">" )
2123                                .append( clmLbl ).append( "</a>" );
2124                }
2125                else {
2126                        rtn.append( "<span>" ).append( clmLbl ).append( "</span>" );    // 5.9.23.0 (2017/08/10)
2127                }
2128
2129                // 5.2.1.0 (2010/10/01) 一括入力カラムのアシスト機能対応(bulkSet)
2130                if( isClmBulkSet( column ) ) {
2131                        final DBColumnConfig config = dbColumn[column].getConfig();
2132                        config.setAddNoValue( true );
2133                        // 6.2.2.2 (2015/04/03) NO_MAXLEN キーの値が、"true" の場合、maxlength を強制削除する。
2134                        final String editor = config.getEditor();
2135                        if( "RADIO".equals( editor ) ) {                        // 6.2.2.2 (2015/04/03)
2136                                config.setEditor( "MENU" );
2137                        }
2138                        // 6.2.1.0 (2015/03/13) 動的カラム(COLUMN)は、TEXT に置き換える。
2139                        else if( "COLUMN".equals( editor ) ) {          // 6.2.2.2 (2015/04/03)
2140                                config.setEditor( "TEXT" );
2141                        }
2142
2143                        final Attributes attri = new Attributes();
2144                        // 5.2.3.0 (2010/12/01) チェックボックスでは、onchange ではなく、onclick でイベントを発生させます。
2145                        if( "CHBOX".equals( editor ) ) {                        // 6.2.2.2 (2015/04/03)
2146                                attri.add( "onclick",  "bulkSet(this);" );
2147                        }
2148                        else {
2149                                attri.add( "onchange",  "bulkSet(this);" );
2150                                attri.add( "ondblclick","bulkPaste(this);" );
2151                                // 6.2.2.2 (2015/04/03) NO_MAXLEN キーの値が、"true" の場合、maxlength を強制削除する。
2152                                attri.set( "p_NO_MAXLEN", "true" );                             // W100 と連動 8.5.3.0 (2023/09/08) 先頭に"p_"付与
2153                                attri.add( "style",             "float:left;" );                // 6.1.1.0 (2015/01/17) CHBOX以外は左寄せ
2154
2155        //                      // 6.2.2.4 (2015/04/24) class="W100"の追加条件に、dbType 制限をかけます。
2156                                final String dbType = "," + config.getDbType() + ",";
2157                                if( ",X,K,KX,XK,ALL,".contains( dbType ) ) {
2158                                        attri.add( "class", "W100" );                           // 6.2.0.0 (2015/02/27) テーブル幅いっぱいの入力枠にする。
2159                                        config.setFieldSize( "1" );                                     // 6.2.2.2 (2015/04/03) ここで設定しないと、後付けされる。
2160                                }
2161                        }
2162                        attri.add( "onkeydown", "ctrlCV(this);" );
2163
2164                        config.setEditorAttributes( attri );
2165                        config.removeEditorAttributes( "class" , "must" );      // 6.8.1.4 (2017/08/25) must の取り消し
2166                        config.setUseSLabel( "true" );                                          // 6.1.1.0 (2015/01/17) SLABEL設定。ほんとはMENU系のみでよい。
2167
2168                        final String key = config.getName();
2169                        config.setName( "h_" + key );
2170
2171                        final DBColumn clm = new DBColumn( config );
2172
2173                        // 6.0.2.0 (2014/09/19) Bulkset エラー回避
2174                        try {
2175                                // 6.4.2.1 (2016/02/05) PMD refactoring. Prefer StringBuffer over += for concatenating strings
2176//                              rtn.append( "<br />" ).append( clm.getEditorValue( null ) );    // 注意:検索用のEditorが呼ばれる。
2177                                rtn.append( "<br>" ).append( clm.getEditorValue( null ) );              // 注意:検索用のEditorが呼ばれる。
2178                        }
2179                        catch( final RuntimeException ex ) {
2180                                final String errMsg = "bulkSet でエラーが発生しました。" + CR
2181                                                        + " Label=" + rtn + " , Column=" + key + " , Editor=" + editor          // 6.2.2.2 (2015/04/03)
2182                                                        + CR
2183                                                        + ex.getMessage();
2184                                System.err.println( errMsg );
2185                        }
2186                }
2187
2188                return rtn.toString();                  // 6.4.2.1 (2016/02/05)
2189        }
2190
2191        /**
2192         * 指定カラムNoがmust指定されているかどうか。
2193         *
2194         * @og.rev 5.5.4.2 (2012/07/13)
2195         *
2196         * @param       column カラムNO
2197         * @return must指定されているかどうか[true:されている/false:されていない]
2198         */
2199        protected boolean isMustColumn( final int column){
2200                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
2201                boolean flag = false;
2202
2203                if( nullCheck != null && nullCheck.length > 0 ){
2204                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
2205//                      for( int i=0; i<nullCheck.length; i++ ){
2206//                              if( nullCheck[i].equals( dbColumn[column].getName() ) ){
2207                        for( final String nullClm : nullCheck ){
2208                                if( nullClm.equals( dbColumn[column].getName() ) ){
2209//                                      return true;
2210                                        flag = true;
2211                                        break;
2212                                }
2213                        }
2214                }
2215//              return false;
2216                return flag;
2217        }
2218
2219        /**
2220         * 指定カラムNoがmustAny指定されているかどうか。
2221         *
2222         * @og.rev 5.5.4.2 (2012/07/13)
2223         *
2224         * @param       column カラムNO
2225         * @return mustAny指定されているかどうか[true:されている/false:されていない]
2226         */
2227        protected boolean isMustAnyColumn( final int column){
2228                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
2229                boolean flag = false;
2230
2231                if( mustAnyCheck != null && mustAnyCheck.length > 0 ){
2232                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
2233//                      for( int i=0; i<mustAnyCheck.length; i++ ){
2234//                              if( mustAnyCheck[i].equals( dbColumn[column].getName() ) ){
2235                        for( final String mustClm : mustAnyCheck ){
2236                                if( mustClm.equals( dbColumn[column].getName() ) ){
2237//                                      return true;
2238                                        flag = true;
2239                                        break;
2240                                }
2241                        }
2242                }
2243//              return false;
2244                return flag;
2245        }
2246
2247        /**
2248         * ViewForm のサブクラスに渡すパラメータマップを設定します。
2249         *
2250         * @og.rev 3.5.4.8 (2004/02/23) ViewParamTag のパラメータを追加します。
2251         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
2252         *
2253         * @param       map パラメータマップ
2254         */
2255        @Override       // ViewForm
2256        public void setParam( final ConcurrentMap<String,String> map ) {
2257                viewParam = map ;
2258        }
2259
2260        /**
2261         * ViewForm のサブクラスに渡すパラメータマップの値を返します。
2262         * パラメータが 存在しない(null)か、値が 存在しない(null)の場合は、
2263         * 初期値を返します。
2264         *
2265         * @og.rev 3.5.5.9 (2004/06/07) 新規追加
2266         *
2267         * @param       key     パラメータの取り出すキー
2268         * @param       def     パラメータが存在しない場合の初期値
2269         *
2270         * @return      パラメータ値
2271         */
2272        protected String getParam( final String key, final String def ) {
2273                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
2274                // 注釈:viewParamは、ConcurrentMap なので、value に null はセットできません。(値が null は考慮していない)
2275                return viewParam == null
2276                                        ? def
2277                                        : viewParam.getOrDefault( key,def ) ;
2278
2279//              if( viewParam == null ) { return def; }
2280//              final String rtn = viewParam.get( key );                // 4.3.3.6 (2008/11/15) Generics警告対応
2281//
2282//              // 6.4.1.1 (2016/01/16) 条件反転
2283//              return ( rtn == null ) ? def : rtn ;
2284        }
2285
2286        /**
2287         * ViewForm のサブクラスに渡すパラメータマップの値を返します。
2288         * パラメータは、初期値が設定されているものとし、そのまま、値を返します。
2289         *
2290         * @og.rev 5.5.5.6 (2012/08/31) 新規追加
2291         *
2292         * @param       key     パラメータの取り出すキー
2293         *
2294         * @return      パラメータ値
2295         */
2296        protected String getParam( final String key ) {
2297                return (viewParam == null) ? null : viewParam.get( key );
2298        }
2299
2300        /**
2301         * ViewForm のサブクラスに渡すパラメータマップの値を int で返します。
2302         * パラメータは、初期値が設定されているものとし、null の場合は、-1 を返します。
2303         *
2304         * @og.rev 5.5.5.6 (2012/08/31) 新規追加
2305         *
2306         * @param       key     パラメータの取り出すキー
2307         *
2308         * @return      パラメータ値(未設定時は、-1)
2309         */
2310        protected int getIntParam( final String key ) {
2311                final String rtn = viewParam == null ? null : viewParam.get( key );
2312                return rtn == null ? -1 : Integer.parseInt( rtn );
2313        }
2314
2315        /**
2316         * ViewForm のサブクラスに渡すパラメータマップの値を boolean で返します。
2317         * パラメータは、初期値が設定されているものとし、null の場合は、false を返します。
2318         *
2319         * @og.rev 5.5.5.6 (2012/08/31) 新規追加
2320         * @og.rev 6.3.9.1 (2015/11/27) 3項演算子を || or &amp;&amp; で簡素化できる(PMD)。
2321         *
2322         * @param       key     パラメータの取り出すキー
2323         *
2324         * @return      パラメータ値(未設定時は、false)
2325         */
2326        protected boolean getBoolParam( final String key ) {
2327                // 6.3.9.1 (2015/11/27) Boolean#parseBoolean(String) は、引数が null の場合、false を返す(引数のnullチェックは不要)。
2328                return viewParam != null && Boolean.parseBoolean( viewParam.get( key ) );
2329        }
2330
2331        /**
2332         * ViewForm のサブクラスに渡すパラメータ(文字列配列のArrayList)を設定します。
2333         *
2334         * @og.rev 5.5.8.3 (2012/11/17) ViewParamTag のパラメータを追加します。
2335         * @og.rev 5.5.9.0 (2012/12/03) ArrayListに変更
2336         *
2337         * @param       list 文字列配列のArrayList
2338         */
2339        @Override       // ViewForm
2340        public void setViewArrayList( final List<String[]> list ) {
2341                viewArrayList = list ;
2342        }
2343
2344        /**
2345         * ViewForm のサブクラスに渡すパラメータ(文字列配列のArrayList)の値を返します。
2346         * パラメータは、初期値が設定されているものとし、そのまま、値を返します。
2347         *
2348         * @og.rev 5.5.8.3 (2012/11/17) 新規追加
2349         * @og.rev 5.5.9.0 (2012/12/03) ArrayListに変更
2350         *
2351         * @return      パラメータ値
2352         */
2353        protected List<String[]> getViewArrayList() {
2354                return viewArrayList;
2355        }
2356
2357        /**
2358         * No 欄そのものを作成するかどうかを返します。
2359         *
2360         * numberType 属性に、"delete" という値を設定した場合は、No 欄そのものを
2361         * 作成しません。それ以外は、作成します。
2362         * 初期値は、作成する(true)です。
2363         *
2364         * @og.rev 3.5.5.0 (2004/03/12) 新規追加
2365         *
2366         * @return      No欄そのものを作成するかどうか(true:作成する/false:作成しない)
2367         */
2368        protected boolean isNumberDisplay() {
2369                return numberDisplay;
2370        }
2371
2372        /**
2373         * マーカーオブジェクト(リンク、マーカー)を設定します。
2374         * ここでは、旧 ViewForm 属性を 新ViewForm に直接セットします。
2375         *
2376         * @og.rev 3.5.6.1 (2004/06/25) 新規追加
2377         * @og.rev 3.8.6.1 (2006/10/20) editMarker 追加
2378         *
2379         * @param       view ViewFormオブジェクト
2380         */
2381        @Override       // ViewForm
2382        public void markerSet( final ViewForm view ) {
2383                if( view instanceof AbstractViewForm ) {
2384                        viewLink   = ((AbstractViewForm)view).viewLink ;
2385                        if( viewLink != null ) { viewLink.setDBTableModel( table ); }
2386                        viewMarker = ((AbstractViewForm)view).viewMarker;
2387                        if( viewMarker != null ) { viewMarker.setDBTableModel( table ); }
2388                        editMarker = ((AbstractViewForm)view).editMarker;
2389                        if( editMarker != null ) { editMarker.setDBTableModel( table ); }
2390                }
2391                else {
2392                        final String errMsg = "AbstractViewForm 以外の view は、サポートしていません。"
2393                                        + " view=[" + view + "]" ;
2394                        throw new HybsSystemException( errMsg );
2395                }
2396        }
2397
2398        /**
2399         * テーブルのバックグラウンドカラーの入れ替えのサイクルをセットします。
2400         * 0(ゼブラなし)、-1(ワーニング)、-2以下(エラー)、1(ゼブラ)、2以上(行数まとめ)
2401         * 初期値は、1(ゼブラ)です。
2402         *
2403         * @og.rev 3.5.6.2 (2004/07/05) ViewForm_HTMLTable より移動
2404         *
2405         * @param  sycle  0(ゼブラなし)、-1(ワーニング)、-2以下(エラー)、1(ゼブラ)、2以上(行数まとめ)
2406         */
2407        @Override       // ViewForm
2408        public void setBgColorCycle( final int sycle ) {
2409                bgColorCycle    = 1;            // 強制的に設定
2410
2411                if( sycle > 0 ) {                                               // 1(ゼブラ)、2以上(行数まとめ)
2412                        colorRow0               = BG_COLOR_ROW0 ;
2413                        colorRow1               = BG_COLOR_ROW1 ;
2414                        bgColorCycle    = sycle;                        // このケースのみ引数を設定
2415                }
2416                else if( sycle == -1 ) {                                        // -1(ワーニング)
2417                        colorRow0               = BG_WARNING_COLOR_ROW0 ;
2418                        colorRow1               = BG_WARNING_COLOR_ROW1 ;
2419                }
2420                else if( sycle < -1 ) {                                 // -2以下(エラー)
2421                        colorRow0               = BG_ERROR_COLOR_ROW0 ;
2422                        colorRow1               = BG_ERROR_COLOR_ROW1 ;
2423                }
2424                else {                                                                                  // 0(ゼブラなし)
2425                        colorRow0               = "" ;
2426                        colorRow1               = "" ;
2427                }
2428        }
2429
2430        /**
2431         * テーブルのバックグラウンドカラーのクラスに指定するカラム名を指定します。
2432         *
2433         * 通常のゼブラ模様は、tr 属性のクラス指定として、row_0、row_1 が指定されます。
2434         * その代わりに、ここで指定されたカラムの値がクラス属性として設定されます。
2435         * (指定するのはカラム名です。行単位にクラス属性の値を変えることが可能です。)
2436         * 選択行(row_sel)は、優先して使用されます。
2437         * 出力されるクラス名は、"row_" + 属性値 になります。
2438         *
2439         * @og.rev 5.1.8.0 (2010/07/01) 新規追加
2440         *
2441         * @param  clsClm ゼブラ模様の替わりに指定するクラスを格納したカラム名
2442         */
2443        @Override       // ViewForm
2444        public void setBgColorClsClm( final String clsClm ) {
2445                if( clsClm != null ) {
2446                        bgColorClsClmNo = table.getColumnNo( clsClm );
2447                }
2448        }
2449
2450        /**
2451         * テーブルのバックグラウンドカラーの値をセットします。
2452         * これは、DBTableModele が指定の行番号の時に、BG_COLOR_ROWSEL を
2453         * 返します。それ以外は、通常の getBgColorCycleClass( int )と
2454         * 同じ結果を返します。
2455         * BG_COLOR_ROWSEL の使用有無は、システムパラメータの
2456         * VIEW_USE_SELROW_COLOR 属性で指定できます。
2457         *
2458         * @og.rev 3.7.0.3 (2005/03/01) 新規追加
2459         * @og.rev 3.7.1.1 (2005/05/31) SEL_ROW機能使用時に、BG_COLOR_ROWSEL の使用 有/無を指定
2460         *
2461         * @param       indx 先頭からの連番( 0から始める )
2462         * @param       row 行番号
2463         *
2464         * @return      行の色を指定する class 属性( cssファイルで指定 )
2465         * @see #getBgColorCycleClass( int )
2466         */
2467        protected String getBgColorCycleClass( final int indx,final int row ) {
2468                return useSelRowColor && scrollRowNo == row ? BG_COLOR_ROWSEL : getBgColorCycleClass( indx ) ;          // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses.
2469        }
2470
2471        /**
2472         * テーブルのバックグラウンドカラーの値をセットします。
2473         * 行番号は、0から始まるので、偶数を HTML_BG_COLOR_ROW0、
2474         * 奇数行を HTML_BG_COLOR_ROW1 とします。
2475         * setBgColorCycle で、設定値変換しています。
2476         * bgColorClsClm が指定されている場合は、その値を利用したクラス属性を返します。
2477         * クラス名は、"row_" + 指定カラムの値 です。
2478         * 指定カラムの値 が、null または、空文字列の場合は、従来のゼブラ模様が優先されます。
2479         * また、行選択があれば、そちらが最優先されます。
2480         *
2481         * @og.rev 3.5.6.2 (2004/07/05) ViewForm_HTMLTable より移動
2482         * @og.rev 5.1.8.0 (2010/07/01) bgColorClsClmNo 対応
2483         *
2484         * @param       row 行番号( 0から始める )
2485         *
2486         * @return      行の色を指定する class 属性( cssファイルで指定 )
2487         * @see         #setBgColorClsClm( String )
2488         */
2489        protected String getBgColorCycleClass( final int row ) {
2490                String rtn = null ;
2491
2492                // 5.1.8.0 (2010/07/01) bgColorClsClmNo 対応
2493                if( bgColorClsClmNo >= 0 ) {
2494                        final String val = table.getValue( row,bgColorClsClmNo );
2495                        if( val != null && val.length() > 0 ) {
2496                                rtn = " class=\"row_" + val + "\"";
2497                        }
2498                }
2499
2500                if( rtn == null ) {
2501                        if( (row/bgColorCycle) % 2 == 0 ) {
2502                                rtn = colorRow0;                // 偶数の場合
2503                        }
2504                        else {
2505                                rtn = colorRow1;                // 奇数の場合
2506                        }
2507                }
2508
2509                return rtn ;
2510        }
2511
2512        /**
2513         * スクロールバー用のDIV要素を出力するかどうか(初期値はシステムパラメータ)
2514         *
2515         * スクロールバー対応する為、テーブルの先頭に、DIV要素を出力します。
2516         * 初期値は、システムパラメータ の VIEW_USE_SCROLLBAR です。
2517         * ※ 互換性の関係より、false になっています。
2518         * ※ 互換性の関係より、新しいタイプのヘッダー固定を、TYPE2 とします。
2519         *
2520         * @og.rev 3.5.6.4 (2004/07/16) 新規追加
2521         * @og.rev 3.8.0.3 (2005/07/15) barType 変数の追加
2522         * @og.rev 4.0.0.0 (2007/04/10) ヘッダー固定のスクロールタイプは、TYPE2 のみにする。
2523         *
2524         * @param  useBar  スクロールバー用のDIV要素の出力 [true:出力する/false:出力しない]
2525         */
2526        @Override       // ViewForm
2527        public void setUseScrollBar( final boolean useBar ) {
2528                useScrollBar  = useBar;
2529        }
2530
2531        /**
2532         * スクロールバー用の開始DIV要素返します。
2533         *
2534         * スクロールバー対応する為、テーブルの先頭に、DIV要素を出力します。
2535         * 初期値は、システムパラメータ の VIEW_USE_SCROLLBAR で指定されたDIV要素です。
2536         * DIV要素の開始タグになります。
2537         *
2538         * @og.rev 3.8.0.3 (2005/07/15) 新規追加
2539         * @og.rev 4.2.0.0 (2008/03/18) outerにwidthとheightを出すように修正
2540         *
2541         * @return  LAYER_ST スクロールバー用の開始DIV要素
2542         */
2543        protected String getScrollBarStartDiv() {
2544                final String layerStart ;
2545                if( useScrollBar ) {
2546                        // 6.1.0.0 (2014/12/26) refactoring:Prefer StringBuffer over += for concatenating strings
2547                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
2548                                .append( "<div id=\"divPos\" style=\"" );
2549                        if( height != null ){
2550                                buf.append( "height:" ).append( height ).append( ';' );
2551                        }
2552                        if( width != null ){
2553                                buf.append( "width:" ).append( width ).append( ';' );
2554                        }
2555                        buf.append( "\" ><div id=\"outer\"><div id=\"layer\" onscroll=\"SetScrollHeader(this);\"><div id=\"divHide\">" );
2556
2557                        layerStart = buf.toString();
2558                }
2559                else {
2560                        layerStart = LAYER_ST0;
2561                }
2562
2563                return layerStart;
2564        }
2565
2566        /**
2567         * スクロールバー用の終了DIV要素返します。
2568         *
2569         * スクロールバー対応する為、テーブルの終了に、DIV要素を出力します。
2570         * 初期値は、システムパラメータ の VIEW_USE_SCROLLBAR で指定されたDIV要素です。
2571         * DIV要素の終了タグになります。
2572         *
2573         * @og.rev 3.8.0.3 (2005/07/15) 新規追加
2574         *
2575         * @return  スクロールバー用の終了DIV要素
2576         */
2577        protected String getScrollBarEndDiv() {
2578                String layerEnd = LAYER_END0 ;
2579                if( useScrollBar ) {
2580                        layerEnd = LAYER_END2 ;
2581                }
2582                return layerEnd;
2583        }
2584
2585        /**
2586         * 指定の行番号まで画面をスクロールさせる場合の行番号を設定します。
2587         *
2588         * 画面をスクロール後、リンク等で他画面を表示後、戻ってきた場合に、
2589         * 先のスクロール位置まで戻します。
2590         * ただし、厳密に戻すことはできないため、大体のあたりに戻します。
2591         * 指定しない場合(クリアする場合)は、-1 をセットしてください。
2592         * useSelRowColor は、選択行に色づけするかどうかを指定します。
2593         *
2594         * @og.rev 3.7.0.3 (2005/03/01) 新規追加
2595         * @og.rev 3.7.1.1 (2005/05/31) 選択行マーカーの使用有無
2596         *
2597         * @param       rowNo   指定の行番号まで画面をスクロールさせる場合の行番号
2598         * @param       useSelRowColor  選択行マーカーの使用有無
2599         */
2600        @Override       // ViewForm
2601        public void setScrollRowNo( final int rowNo, final boolean useSelRowColor ) {
2602                scrollRowNo = rowNo;
2603                firstChecked = false;
2604                this.useSelRowColor = useSelRowColor;
2605        }
2606
2607        /**
2608         * 設定値に "_" が含まれている場合にレンデラーを使用するカラムをCSV形式で指定します。
2609         *
2610         * これは、従来の カラム定義の WRITABLE エディターと同等の働きを行うように
2611         * カラム属性を指定します。
2612         * WRITABLE エディターは、設定値にアンダーバー "_" が含まれている場合に、
2613         * その値を書込み禁止にする機能です。これは、エディター自身が値を判断して
2614         * 書き込み許可か禁止かを判断しています。
2615         * この動きを汎用的にするため、指定のカラムをCSV形式(CSV)で指定
2616         * することにより、レンデラーとエディターを設定値によって動的に切り替える
2617         * 機能を実現します。
2618         * その場合、表示/編集ともに、先頭のアンダーバーは削除されます。
2619         * また、全カラムについて、有効にする場合は、writableControl="*" を設定します。
2620         *
2621         * @og.rev 3.8.0.9 (2005/10/17) 新規追加
2622         * @og.rev 5.1.8.0 (2010/07/01) 内部ロジック変更(setBooleanArray)
2623         * @og.rev 7.0.1.5 (2018/12/10) writeCtrlで出力時のアンダーバー削除
2624         *
2625         * @param  wrtCtrl 書き込み制御を行いたいカラムをCSV形式で指定
2626         */
2627        @Override       // ViewForm
2628        public void setWritableControl( final String wrtCtrl ) {
2629                setBooleanArray( wrtCtrl,true,writeCtrl );
2630
2631                for( int i=0; i<writeCtrl.length; i++ ) {
2632                        if( writeCtrl[i] ) {
2633                                final DBColumnConfig config = dbColumn[i].getConfig();
2634                                config.setWriteControl( true );
2635                                dbColumn[i] = new DBColumn( config );
2636                                table.setDBColumn( i,dbColumn[i] );                             // DBTableModel にも書き戻す必要がある。
2637                        }
2638                }
2639        }
2640
2641        /**
2642         * CSV形式で指定されたカラムに、true/false の初期設定を行います。
2643         *
2644         * 従来は、各クラスで実装されていた処理を、一箇所にまとめます。
2645         * これにより、各種機能をあらかじめ実装しておきます。
2646         * 指定のカラムが、null の場合は、何も処理を行いません。(つまり、初期値のまま)
2647         * 指定のカラムが、* の場合は、すべてのカラムが指定されたとみなし、配列に値を設定します。
2648         * 指定のカラムが、""(ゼロ文字列)と、"-" の場合は、なにもカラムが指定されていないものとみなされ、
2649         * 初期値の逆で埋められます。
2650         *
2651         * @og.rev 5.1.8.0 (2010/07/01) 新規追加
2652         * @og.rev 6.2.1.0 (2015/03/13) カラム名のゼロ文字列と、"-" も除外する。
2653         * @og.rev 5.9.27.0 (2017/12/01) protectedにして子クラスでも使えるようにしておく
2654         *
2655         * @param  clsm    指定のカラムをCSV形式で指定
2656         * @param  def     設定する値
2657         * @param       arrays  設定するboolean配列
2658         */
2659        protected void setBooleanArray( final String clsm , final boolean def , final boolean[] arrays ) {
2660                if( clsm != null ) {
2661                        // 書き込み制御の許可 をカラム単位で設定。* の場合は、全カラム許可
2662                        if( "*".equals( clsm ) ) {
2663                                Arrays.fill( arrays,def );              // 全部埋める
2664                        }
2665                        // 6.2.1.0 (2015/03/13) カラム名のゼロ文字列と、"-" も除外する。
2666                        else if( "-".equals( clsm ) || clsm.isEmpty() ) {
2667                                Arrays.fill( arrays,!def );             // 全部逆で埋める
2668                        }
2669                        else {
2670                                Arrays.fill( arrays,!def );             // 一旦、全部逆で埋める
2671                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
2672//                              final String[] clmNames = StringUtil.csv2Array( clsm );
2673//                              for( int i=0; i<clmNames.length; i++ ) {
2674//                                      if( clmNames[i] != null && clmNames[i].length() > 0 ) {
2675//                                              final int no = table.getColumnNo( clmNames[i] );
2676//                                              if( no >= 0 ) { arrays[no] = def; }
2677//                                      }
2678//                              }
2679                                for( final String clmNm : StringUtil.csv2Array( clsm ) ) {
2680                                        if( clmNm != null && clmNm.length() > 0 ) {
2681                                                final int no = table.getColumnNo( clmNm );
2682                                                if( no >= 0 ) { arrays[no] = def; }
2683                                        }
2684                                }
2685                        }
2686                }
2687        }
2688
2689//      /**
2690//       * ogPopup で検索結果の値を返すキーを、CSV形式で指定します。
2691//       *
2692//       * popup の検索結果を返す画面で、結果のラジオボタンにイベントセットします。
2693//       * この場合、オープンもとのwindow に値を返しますが、そのキーをCSV形式で
2694//       * 指定します。
2695//       * なお、このメソッドは、一覧表示(HTMLTable)関係のビューのみでサポートして
2696//       * いますが、チェックメソッドの関係で、それ以外のビューに適用しても素通り
2697//       * するようにします。(エラーにしません)
2698//       *
2699//       * @og.rev 3.8.6.1 (2006/10/20) 新規追加
2700//       * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 EmptyMethodInAbstractClassShouldBeAbstract 対応
2701//       *
2702//       * @param  rtnKeys ogPopupで値を返すカラム文字列(CSV形式)
2703//       */
2704//      @Override       // ViewForm
2705//      public void setPopupReturnKeys( final String rtnKeys ) {
2706//              // このメソッドは、一覧表示(HTMLTable)関係のビューのみでサポートして
2707//              // いますが、チェックメソッドの関係で、それ以外のビューに適用しても素通り
2708//              // するようにします。(エラーにしません)
2709//      }
2710
2711        /**
2712         * table要素に対して class 属性を設定します。
2713         *
2714         * 従来の システムリソースでのテーブルレイアウトの設定を廃止し、
2715         * CSSファイルで、指定するように変更しています。
2716         * これに伴い、CSSファイルのキーとして、クラス属性を出力します。
2717         * view(または、出力されるtableタグ)のレイアウトは、このクラス属性で
2718         * 指定することが可能になります。
2719         * 初期値は、viewTable です。
2720         *
2721         * @og.rev 4.0.0.0 (2007/04/16) 新規追加
2722         *
2723         * @param       cls     class属性を表す文字列
2724         */
2725        @Override       // ViewForm
2726        public void setTableClass( final String cls ) {
2727                if( cls != null ) {
2728                        clazz = cls;
2729                }
2730        }
2731
2732        /**
2733         * table要素に対して class 属性を返します。
2734         *
2735         * @og.rev 4.0.0.0 (2007/04/16) 新規追加
2736         * @og.rev 5.9.5.3 (2016/02/26) classにtableIdを付加して返す
2737         * @og.rev 6.4.6.1 (2016/06/03) tableId 廃止(利用目的を明確にするため、パラメータ名をviewClassに変更)
2738         *
2739         * @return      class属性を表す文字列
2740         */
2741        protected String getTableClass() {
2742                return clazz + " " + viewClass;                         // 6.4.6.1 (2016/06/03)
2743        }
2744
2745        /**
2746         * outerのIDを持つDIV要素にheightを指定します。
2747         *
2748         * ビューの高さ、幅を指定できるようにします。
2749         * 内部的には、useScrollBar="true" 時に、div id="divPos" に、
2750         * style 属性を設定しています。(実際は、もう少し複雑)
2751         * これによって1画面に2つのビューを出力する事も可能となります。
2752         * セットする場合は、単位(pt,% など)を付けてください。
2753         * 初期値はnullです。
2754         *
2755         * @og.rev 4.2.0.0 (2008/03/18) 新規追加
2756         *
2757         * @param       high    ビューの高さ
2758         */
2759        @Override       // ViewForm
2760        public void setHeight( final String high ) {
2761                height = high;
2762        }
2763
2764        /**
2765         * 設定されたheightを返します。
2766         *
2767         * テーブル以外に、高さ、幅を使用する場合に、値を取得できるようにしています。
2768         * これは、セットされた文字列そのものを返しますので、
2769         * 単位(pt,% など)が付いています。
2770         * 初期値はnullです。
2771         *
2772         * @og.rev 6.9.7.0 (2018/05/14) 新規追加
2773         *
2774         * @return      ビューの高さ(未設定の場合は、null)
2775         */
2776        protected String getHeight() {
2777                return height;
2778        }
2779
2780        /**
2781         * outerのIDを持つDIV要素にwidthを指定します。
2782         *
2783         * ビューの高さ、幅を指定できるようにします。
2784         * 内部的には、useScrollBar="true" 時に、div id="divPos" に、
2785         * style 属性を設定しています。(実際は、もう少し複雑)
2786         * これによって1画面に2つのビューを出力する事も可能となります。
2787         * セットする場合は、単位(pt,% など)を付けてください。
2788         * 初期値はnullです。
2789         *
2790         * @og.rev 4.2.0.0 (2008/03/18) 新規追加
2791         *
2792         * @param       wide    ビューの高さ
2793         */
2794        @Override       // ViewForm
2795        public void setWidth( final String wide ) {
2796                width = wide;
2797        }
2798
2799        /**
2800         * 設定されたwidthを返します。
2801         *
2802         * テーブル以外に、高さ、幅を使用する場合に、値を取得できるようにしています。
2803         * これは、セットされた文字列そのものを返しますので、
2804         * 単位(pt,% など)が付いています。
2805         *
2806         * @og.rev 6.9.7.0 (2018/05/14) 新規追加
2807         *
2808         * @return      ビューの高さ(未設定の場合は、null)
2809         */
2810        protected String getWidth() {
2811                return width;
2812        }
2813
2814        /**
2815         * リソースマネージャを設定します。
2816         * クロス集計時に、useColumnHeader="true"とした場合のみ設定されます。
2817         *
2818         * @og.rev 4.0.0.0 (2007/11/29) 新規作成
2819         *
2820         * @param       res リソースマネージャー
2821         */
2822        @Override       // ViewForm
2823        public void setResourceManager( final ResourceManager res ) {
2824                resourceManager = res;
2825        }
2826
2827        /**
2828         * リソースマネージャを取得します。
2829         *
2830         * @og.rev 4.0.0.0 (2007/11/29) 新規作成
2831         *
2832         * @return      ResourceManagerリソースマネージャー
2833         */
2834        protected ResourceManager getResourceManager() {
2835                return resourceManager;
2836        }
2837
2838        /**
2839         * 改廃Cのついていない行をスキップするかどうか指定します。
2840         *
2841         * "true" で、改廃Cのついた行をスキップします。
2842         * 初期値はfalseです。
2843         *
2844         * @og.rev 4.3.1.0 (2008/09/08) 新規追加
2845         *
2846         * @param       sne 改廃Cのついていない行をスキップするかどうか(true:スキップする/false:スキップしない)
2847         */
2848        @Override       // ViewForm
2849        public void setSkipNoEdit( final boolean sne ) {
2850                skipNoEdit = sne;
2851        }
2852
2853        /**
2854         * 改廃Cのついていない行をスキップするかどうか指定します。
2855         *
2856         * skipNoEdit="true"でかつ、編集されていない(改廃Cがついていない)場合のみ
2857         * trueを返します。
2858         *
2859         * @og.rev 4.3.1.0 (2008/09/08) 新規追加
2860         *
2861         * @param       row     行番号
2862         *
2863         * @return      スキップ対象行か
2864         */
2865        protected boolean isSkipNoEdit( final int row ) {
2866                return skipNoEdit && ( table.getModifyType( row ) == null || table.getModifyType( row ).isEmpty() );
2867        }
2868
2869        /**
2870         * 画面遷移なしモードに対応した形で処理を行うかを指定します。
2871         *
2872         * "true" で、画面遷移なしモードに対応します。
2873         * 初期値はfalseです。
2874         *
2875         * @og.rev 4.3.3.0 (2008/10/01) 新規追加
2876         *
2877         * @param       flag 画面遷移なしモードに対応するかどうか(true:対応する/false:対応しない)
2878         */
2879        @Override       // ViewForm
2880        public void setNoTransition( final boolean flag ) {
2881                noTransition = flag;
2882        }
2883
2884        /**
2885         * 画面遷移なしモードに対応した形で処理を行うかを返します。
2886         *
2887         * "true" で、画面遷移なしモードに対応します。
2888         * 初期値はfalseです。
2889         *
2890         * @og.rev 4.3.3.0 (2008/10/01) 新規追加
2891         *
2892         * @return      画面遷移なしモードに対応するかどうか(true:対応する/false:対応しない)
2893         */
2894        protected boolean isNoTransition() {
2895                return noTransition;
2896        }
2897
2898        /**
2899         * 該当行の行番号と改廃Cを出力します。
2900         * 出力形式は、rid="[行番号]" kh="[改廃C]" です。
2901         * 改廃Cが付加されていない場合は、改廃Cがnullの場合は、kh属性は出力されません。
2902         * (画面遷移なしモードで使用します)
2903         *
2904         * @og.rev 4.3.3.0 (2008/10/01) 新規作成
2905         *
2906         * @param       row 行番号( 0から始める )
2907         *
2908         * @return      該当行の行番号と改廃C
2909         * @og.rtnNotNull
2910         */
2911        protected String getHiddenRowValue( final int row ) {
2912                String kh = "";
2913                if( table.getModifyType( row ) != null && table.getModifyType( row ).length() > 0 ) {
2914                        kh = " " + HIDDEN_CDKH_KEY + "=\"" + table.getModifyType( row ) + "\"";
2915                }
2916                return " " + HIDDEN_ROW_KEY + "=\"" + row + "\"" + kh;
2917        }
2918
2919        /**
2920         * ビューで表示したカラムの一覧をCSV形式で返します。
2921         *
2922         * @og.rev 5.1.6.0 (2010/05/01) 新規追加
2923         *
2924         * @return      ビューで表示したカラムの一覧
2925         * @og.rtnNotNull
2926         */
2927        @Override       // ViewForm
2928        public String getViewClms() {
2929                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
2930                for( int i=0; i<clmDisplay.length; i++ ) {
2931                        if( clmDisplay[i] && !( rowWritableFlag && i==0 ) ) {
2932                                if( buf.length() > 0 ) { buf.append( ',' ); }
2933                                buf.append( dbColumn[i].getName() );
2934                        }
2935                }
2936                return buf.toString();
2937        }
2938
2939        /**
2940         * ビューで表示したカラムの一覧をCSV形式で返します。
2941         *
2942         * このメソッドでは、TableFormatter を使用して表示されたカラム一覧を求めます。
2943         *
2944         * @og.rev 6.4.3.4 (2016/03/11) TableFormatter を使用して表示されたカラム一覧を求めます。
2945         *
2946         * @param       format TableFormatterオブジェクト
2947         * @return      ビューで表示したカラムの一覧
2948         * @og.rtnNotNull
2949         */
2950        protected String getViewClms( final TableFormatter format ) {
2951                return format.getLocationStream()                                                                               // IntStream の取得
2952                                                .filter(   loc -> loc >= 0 )                                                    // 処理条件
2953                                                .mapToObj( loc -> table.getColumnName( loc ) )                  // int から String へStreamの変換
2954                                                .collect( Collectors.joining( "," ) );                                  // CSV連結
2955        }
2956
2957        /**
2958         * 表示項目の編集(並び替え)が可能かどうかを返します。
2959         *
2960         * @og.rev 5.1.6.0 (2010/05/01) 新規追加
2961         *
2962         * @return      表示項目の編集(並び替え)が可能かどうか(true:可能)
2963         */
2964        @Override       // ViewForm
2965        public boolean isEditable() {
2966                return true;
2967        }
2968
2969        /**
2970         * このViewFormが作成された画面IDをセットします。
2971         *
2972         * @og.rev 5.1.7.0 (2010/06/01) 新規追加
2973         *
2974         * @param gamenId 画面ID
2975         */
2976        @Override       // ViewForm
2977        public void setGamenId( final String gamenId ) {
2978                this.gamenId = gamenId;
2979        }
2980
2981        /**
2982         * このViewFormが作成された画面IDを返します。
2983         *
2984         * @og.rev 5.1.7.0 (2010/06/01) 新規追加
2985         *
2986         * @return      画面ID
2987         */
2988        @Override       // ViewForm
2989        public String getGamenId() {
2990                return gamenId;
2991        }
2992
2993        /**
2994         * カラムが一括入力アシスト機能を利用するかどうかを返します。
2995         *
2996         * 条件は、一括入力アシストカラムで、かつ、書き込み許可(isColumnWritable(clm)==true)の場合とする。
2997         *
2998         * @og.rev 5.2.1.0 (2010/10/01) 新規作成
2999         *
3000         * @param       column カラム番号
3001         *
3002         * @return      利用する(true)/しない(false)
3003         */
3004        protected boolean isClmBulkSet( final int column ) {
3005                return clmBulkSet[column] && clmWritable[column];
3006        }
3007
3008        /**
3009         * 一括入力カラムのアシスト機能を利用するカラム名を、CSV形式で与えます。
3010         *
3011         * これは、カラムの書き込み時に、一括入力可能なカラムをヘッダーに表示し、
3012         * 一括登録できる機能を提供します。
3013         * この機能は、jsp/common/bulkSet.js JavaScript とともに提供されます。
3014         * IE については、クリップボードも利用できます。Ctrl-C と Ctrl-V でそれぞれ
3015         * 一連のカラムの値の取り出しと書き込みが可能になります。
3016         * "*" を指定すると、すべてのカラムを(columnBulkSet)指定したことになります。
3017         *
3018         * @og.rev 5.2.1.0 (2010/10/01) 新規作成
3019         * @og.rev 6.2.0.0 (2015/02/27) Popup(isRenderer=false のviewMarker)のBuikSet Off化対応
3020         *
3021         * @param       columnName      例:"OYA,KO,HJO,SU,DYSET,DYUPD"
3022         */
3023        @Override       // ViewForm
3024        public void setColumnBulkSet( final String columnName ) {
3025                setBooleanArray( columnName,true,clmBulkSet );
3026
3027                // 6.2.0.0 (2015/02/27) Popup(isRenderer=false のviewMarker)のBuikSet Off化対応
3028                // result.jsp から update.jsp に画面遷移するときに、再セットされるので、
3029                // 旧のView属性のコピーが必要。(コピーのタイミングでは、早すぎて、ここで書き換えられてしまう。)
3030                if( editMarker != null ) {
3031                        final int[] clmNos = editMarker.getColumnNos();
3032                        if( clmNos != null ) {
3033                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
3034//                              for( int i=0; i<clmNos.length; i++ ) {
3035//                                      clmBulkSet[clmNos[i]] = false ; // 6.2.0.0 (2015/02/27) BulkSetしない
3036//                              }
3037                                for( final int clmNo : clmNos ) {
3038                                        clmBulkSet[clmNo] = false ;     // 6.2.0.0 (2015/02/27) BulkSetしない
3039                                }
3040                        }
3041                }
3042        }
3043
3044        /**
3045         * 引数のフォーマッターに、noDisplayカラムのロケーションをクリアします。
3046         *
3047         * フォーマッター系の noDisplay 処理になります。
3048         *
3049         * @og.rev 6.2.0.0 (2015/02/27) フォーマット系の noDisplay 対応
3050         * @og.rev 6.2.0.1 (2015/03/06) 非表示のマーカーに、Formatter#NO_DISPLAY を使用する。
3051         *
3052         * @param       format  フォーマッター
3053         */
3054        protected void setFormatNoDisplay( final TableFormatter format ) {
3055                final int size = format.getLocationSize();
3056                for( int cl=0; cl<size; cl++ ) {
3057                        final int loc = format.getLocation( cl );
3058                        if( loc >= 0 && !isColumnDisplay( loc ) ) {     // 6.2.0.1 (2015/03/06) 非表示のマーカー
3059                                format.setNoDisplay( cl );                              // 6.2.0.1 (2015/03/06) 非表示のマーカー
3060                        }
3061                }
3062        }
3063
3064        /**
3065         * このViewFormを作成するにあたり、区別するためのクラス属性をセットします。
3066         *
3067         * 通常は、viewForm より tableId を設定します。
3068         * SplitViewTag を使用する場合は、左右分割のため、同じtableId になるため、
3069         * 左右で異なるclassを設定してください。
3070         *
3071         * @og.rev 6.4.6.1 (2016/06/03) 新規追加
3072         *
3073         * @param clazz Viewのクラス属性
3074         */
3075        @Override       // ViewForm
3076        public void setViewClass( final String clazz ) {
3077                if( clazz != null ) {
3078                        this.viewClass = clazz;
3079                }
3080        }
3081
3082        /**
3083         * このViewFormを作成するにあたり、区別するためのクラス属性を取得します。
3084         *
3085         * 通常は、viewForm より tableId を設定します。
3086         * SplitViewTag を使用する場合は、左右分割のため、同じtableId になるため、
3087         * 左右で異なるclassを設定してください。
3088         *
3089         * @og.rev 6.4.6.1 (2016/06/03) 新規追加
3090         *
3091         * @return Viewのクラス属性
3092         */
3093        protected String getViewClass() {
3094                return viewClass;
3095        }
3096}