001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.plugin.view; 017 018import org.opengion.fukurou.util.StringUtil; 019import org.opengion.fukurou.util.Attributes; 020 021import org.opengion.hayabusa.db.DBColumn; 022import org.opengion.hayabusa.db.DBColumnConfig; 023import org.opengion.hayabusa.db.DBTableModel; 024import org.opengion.hayabusa.resource.ResourceFactory; 025import org.opengion.hayabusa.resource.ResourceManager; 026import org.opengion.hayabusa.resource.LabelData; 027import org.opengion.hayabusa.common.HybsSystemException; 028 029import java.time.LocalDateTime; // 7.4.2.1 (2021/05/21) 030import java.time.format.DateTimeFormatter; // 7.4.2.1 (2021/05/21) 031 032/** 033 * 指定の行-列と、動的カラムのテーブルを作成するクラスです。 034 * 035 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。 036 * 各HTMLのタグに必要な setter/getterメソッドのみ,追加定義しています。 037 * 行単位の繰り返し色は使いません。 038 * 039 * RENDERER,EDITOR,DBTYPE を使用する代わりに、簡易的な DATA_TYPE で決定します。 040 * 041 * GG10 履歴テーブル (書き込むテーブル) 042 * トークン(TOKEN) 必須キー(トークン) 043 * 更新カウンタ(UPCNT) ← 未使用(同一トークンでの最大値が有効:逆順検索なので、最初に見つかった値を採用) 044 * 値データ(VAL) 必須キー(値の設定) 045 * 単位(TANI) フィールドの後ろに追記(連続の場合は、一番最後のみ) 046 * 判定結果(JUDG) 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格 047 * 判定理由(RIYU) 上限、下限で判定した結果が入っている。titleに入れてポップアップさせる 048 * 049 * GG01 トークンマスタ (GG02がnullの時) 050 * トークン名称(TKN_NM) ← 未使用(GG02 のトークン名称が未設定の場合…SQL文で処理済み) 051 * 表示桁数(VIEW_LEN) テキストフィールドの長さセット 052 * データ型(DATA_TYPE) EDITORを決定 053 * トークングループ(TKN_GRP) (未使用=GG03のSEL_KEY の条件に使用している) 054 * 055 * GG03 選択マスタ (GG01 トークングループの名称とマーカー) 056 * 選択名称(SEL_NM) トークングループ名で、fieldset のキーブレイクに使用 057 * マーカー(MARKER) fieldset のstyle属性として使用 058 * 059 * GG02 雛形設定マスタ 060 * トークン名称(TKN_NM) (名称優先) 061 * タブ名称(TAB_NM) ← 未使用 062 * タグループ配置(GRP_POS) ← 未使用(fieldset を配置する場合に使う予定) 063 * 初期値(DEF_VAL) 値の設定 する場合の初期値に使用 064 * 行番号(ROWNO) トークンの並び順を指定 065 * 列番号(COLNO) ← 未使用(トークンの並び順のサブ) 066 * 行数(ROWSPAN) tableのカラムを複数縦につなげる場合 067 * 列数(COLSPAN) tableのカラムを複数横につなげる場合 068 * 登録方法(CDREC) 0:未決 1:不要 2:任意 4:保留 6:必須 069 * 表示方法(CDDISP) 1:ラベルカラム 2:カラム単発 3:カラム連続 4:表示のみ 070 * 異常下限(E_MIN) 異常値の下限判定をフィールドの横に記述 071 * 警告下限(W_MIN) 警告値の下限判定をフィールドの横に記述 072 * 警告上限(W_MAX) 警告値の上限判定をフィールドの横に記述 073 * 異常上限(E_MAX) 異常値の上限判定をフィールドの横に記述 074 * オプション属性(OPT_ATTR) トークンのフォームの属性に追記する 075 * 076 * @og.group 画面表示 077 * 078 * @version 7.3 079 * @author Kazuhiko Hasegawa 080 * @since JDK11.0, 081 */ 082public class ViewForm_HTMLTokenTable extends ViewForm_HTMLTable { 083 /** このプログラムのVERSION文字列を設定します。 {@value} */ 084 private static final String VERSION = "7.4.2.3 (2021/06/09)" ; 085 086 private static final String INS_VAL = "$$$$"; // 表示方法(CDDISP)が3:カラム連続 の場合の挿入位置を示すマーカー 087 088 private static final DateTimeFormatter YMD = DateTimeFormatter.ofPattern( "yyyyMMdd" ); 089 private static final DateTimeFormatter HM = DateTimeFormatter.ofPattern( "HHmm" ); 090 private static final DateTimeFormatter YMDHMS = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss" ); 091 092 // Rendereを使う データ型(DATA_TYPE) の指定 093 // TP_IFRAME,TP_IMAGE,TP_LINE,TP_SIGNALは、Rendereを使う。contains で判定しているので、部分一致に注意 094 private static final String RENDERE_TYPE = "TP_IFRAME,TP_IMAGE,TP_LINE,TP_SIGNAL" ; 095 096 private int noToken = -1; 097// private int noUpcnt = -1; 098 private int noVal = -1; 099 private int noTani = -1; 100 private int noJudg = -1; 101 private int noRiyu = -1; 102 103 private int noViewlen = -1; 104 private int noType = -1; 105 106 private int noSelnm = -1; 107 private int noMarker = -1; 108 109 private int noName = -1; 110 private int noDefval = -1; 111 private int noRowno = -1; 112// private int noColno = -1; 113 private int noRowspan = -1; 114 private int noColspan = -1; 115 116 private int noCdrec = -1; 117 private int noCddisp = -1; 118 private int noEmin = -1; 119 private int noWmin = -1; 120 private int noWmax = -1; 121 private int noEmax = -1; 122 private int noOptAttr = -1; 123 124 private DBTableModel table ; 125 126 /** 127 * デフォルトコンストラクター 128 * 129 * @og.rev 7.3.2.1 (2021/03/25) 動的カラムのテーブルを作成する 130 */ 131 public ViewForm_HTMLTokenTable() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 132 133 /** 134 * 初期化します。 135 * ここでは、内部で使用されているキャッシュをクリアし、 136 * 新しいモデル(DBTableModel)と言語(lang) を元に内部データを再構築します。 137 * ただし、設定情報は、以前の状態がそのままキープされています。 138 * 139 * @og.rev 7.3.2.1 (2021/03/25) 動的カラムのテーブルを作成する 140 * 141 * @param table DBTableModelオブジェクト 142 */ 143 @Override 144 public void init( final DBTableModel table ) { 145 super.init( table ); 146 this.table = table; 147 148 noToken = table.getColumnNo( "TOKEN" ); // トークン 149 // noUpcnt = table.getColumnNo( "UPCNT" ); // 更新カウンタ 150 noVal = table.getColumnNo( "VAL" ); // 値 151 noTani = table.getColumnNo( "TANI" , false ); // 152 noJudg = table.getColumnNo( "JUDG" , false ); // 153 noRiyu = table.getColumnNo( "RIYU" , false ); // 154 noViewlen = table.getColumnNo( "VIEW_LEN" , false ); // 155 noType = table.getColumnNo( "DATA_TYPE", false ); // 156 noSelnm = table.getColumnNo( "SEL_NM" , false ); // 157 noMarker = table.getColumnNo( "MARKER" , false ); // 158 noName = table.getColumnNo( "TKN_NM" , false ); // 159 noDefval = table.getColumnNo( "DEF_VAL" , false ); // 160 noRowno = table.getColumnNo( "ROWNO" , false ); // 161 // noColno = table.getColumnNo( "COLNO" , false ); // 162 noRowspan = table.getColumnNo( "ROWSPAN" , false ); // 163 noColspan = table.getColumnNo( "COLSPAN" , false ); // 164 noCdrec = table.getColumnNo( "CDREC" , false ); // 165 noCddisp = table.getColumnNo( "CDDISP" , false ); // 166 noEmin = table.getColumnNo( "E_MIN" , false ); // 167 noWmin = table.getColumnNo( "W_MIN" , false ); // 168 noWmax = table.getColumnNo( "W_MAX" , false ); // 169 noEmax = table.getColumnNo( "E_MAX" , false ); // 170 noOptAttr = table.getColumnNo( "OPT_ATTR" , false ); // 171 } 172 173 /** 174 * DBTableModel から HTML文字列を作成して返します。 175 * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。 176 * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。 177 * 178 * @og.rev 7.3.2.1 (2021/03/25) 動的カラムのテーブルを作成する 179 * @og.rev 7.4.2.1 (2021/05/21) TP_RADIO追加,4:表示のみは、値をRendererで出す。 180 * @og.rev 7.4.2.3 (2021/06/09) 数値フォーマット(カンマ無し、桁数指定)を設定、addNoValue制御を追加 181 * 182 * @param startNo 表示開始位置 183 * @param pageSize 表示件数 184 * 185 * @return DBTableModelから作成された HTML文字列 186 * @og.rtnNotNull 187 */ 188 @Override 189 public String create( final int startNo, final int pageSize ) { 190 if( getRowCount() == 0 ) { return ""; } // 暫定処置 191 192 final int lastNo = getLastNo( startNo, pageSize ); 193 194 final StringBuilder tagOut = new StringBuilder( BUFFER_LARGE ); // 最終的に出力するタグの文字列バッファ 195// .append( getCountForm( startNo,pageSize ) ) 196// .append( getHeader() ); 197 198 final ResourceManager resource = ResourceFactory.newInstance( "ja" ) ; 199 200 int lastRow = -1; 201// int bgClrCnt = 0; 202 203 String bkSelNm = ""; // 最後にセットされた SEL_NM (キーブレイク用) 204 String bkToken = ""; // 更新カウンタの最大値(逆順検索しているので、最初に見つかったトークン)のみ採用する。 205 206 final int clmCnt = getColumnCount(); 207 for( int row=startNo; row<lastNo; row++ ) { 208 final int rowno = rowData( row,noRowno,row-startNo ); // DBに指定した列の番号 209 210 final String token = table.getValue( row,noToken ); 211 // final String upcnt = table.getValue( row,noUpcnt ); // 更新カウンタは、同一トークン内で、一番最初に現れたレコードのみ使用する。 212 if( bkToken.equals( token ) ) { continue; } // 同一トークンなら、過去データなので取り直し 213 bkToken = token; 214 215 final String selNm = rowData( row,noSelnm ,"" ); // 選択名称(SEL_NM) 216// if( lastRow != rowno || !bkSelNm.equals( selNm ) ) { 217 if( lastRow != rowno ) { // 行のブレイク 218 if( lastRow >= 0 ) { // 最初のループだけは、実行しない。 219 if( !bkSelNm.equals( selNm ) && !bkSelNm.isEmpty() ) { 220 tagOut.append( "</tr></tbody></table></fieldset>" ); 221 } 222 else { 223 tagOut.append(" </tr>").append( CR ); 224 } 225 } 226 227 // ※ 繰り返し色:getBgColorCycleClass( bgClrCnt++,row ) は使いません。 228 if( !bkSelNm.equals( selNm ) && !selNm.isEmpty() ) { 229 final String style = rowData( row,noMarker," style=\"", "\"" ); // マーカー(MARKER) は、style属性に追加する。 230 tagOut.append( "<fieldset" ).append( style ).append( "><legend>" ).append( selNm ).append( "</legend>" ) 231 .append("<table><tbody><tr>").append( CR ); // 繰り返し色背景色は使わない 232// .append("<table><tbody><tr").append( getBgColorCycleClass( bgClrCnt++,row ) ).append('>').append( CR ); 233 } 234 else if( lastRow < 0 ) { // 最初の行で、fieldset のラベルが 未指定の場合、<table> が必要。 235 tagOut.append("<table><tbody><tr>").append( CR ); // 繰り返し色背景色は使わない 236// tagOut.append("<table><tbody><tr").append( getBgColorCycleClass( bgClrCnt++,row ) ).append('>').append( CR ); 237 } 238 else { 239 tagOut.append("<tr>").append( CR ); // 繰り返し色背景色は使わない 240// tagOut.append("<tr").append( getBgColorCycleClass( bgClrCnt++,row ) ).append('>').append( CR ); 241 } 242 bkSelNm = selNm; 243 lastRow = rowno; 244 } 245 246 final String lbl = rowData( row,noName,token ); // 表示するラベル(無ければトークンそのもの) 247 final String dbType= rowData( row,noType,"TP_TEXT" ); // DBタイプ。未指定時は、TP_TEXT:テキスト 248 249 final DBColumn clm = resource.makeDBColumn( dbType,lbl ); 250 final DBColumnConfig config = clm.getConfig(); 251 config.setName( "VAL" ); // 登録するカラムの名前は、VAL になる。 252 253 final String defVal = timeVal( dbType,rowData( row,noDefval,"" ) ); // 初期値 7.4.2.1 (2021/05/21) 254 final String val = rowData( row,noVal,defVal ); 255 256 final String cdrec = rowData( row,noCdrec ,"0" ); // 0:未決 1:不要 2:任意 4:保留 6:必須 257 final String judg = rowData( row,noJudg ,"0" ); // 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格 258 259 final Attributes editAttri = config.getEditorAttributes(); // 内部オブジェクトを取得している。 260// final String optAttr = changeOptAttr( editAttri, rowData( row,noOptAttr,"" ) ); // オプション属性(OPT_ATTR) 261 final String optAttr = changeOptAttr( config, editAttri, rowData( row,noOptAttr,"" ) ); // 7.4.2.3 (2021/06/09) オプション属性(OPT_ATTR) 262 263 final boolean isEmp = val.isEmpty() // 本当にempty 264 || ( "TP_CHECK".equals( dbType ) && "0".equals(val) ); // TP_CHECK が '0' は、未設定と同じ 265 266 if( isEmp ) { // val が未設定の場合は、cdrec をそのままセットする。 267 editAttri.add( "class" , "judg" + cdrec ); // 注意:キーは、judg 268 } 269 else { // val が設定済みの場合は、judg をセットする。 270 editAttri.add( "class" , "judg" + judg ); 271 } 272 273 // 日付フォーマットが日本風じゃないので、取りやめ 274 // // dbType が、TP_YMD,TP_HMS,TP_YMDH の場合は、日付、時刻のみ可能とする。 275 // if( "TP_YMD".equals( dbType ) ) { 276 // editAttri.set( "type" , "date" ); // type="date" で日付 277 // } 278 // else if( "TP_HMS".equals( dbType ) ) { 279 // editAttri.set( "type" , "time" ); // type="time" だけだと、秒が入らない。 280 // editAttri.set( "step" , "1" ); // 秒 を有効にするには、step="1" にする。 281 // } 282 283 // dbType が、TP_INT の場合は、数値のみ可能とする。 284 if( "TP_INT".equals( dbType ) ) { 285 editAttri.set( "type" , "number" ); // type="number" だけだと、整数しか入らない。 286 // Editor_NUMBER は、フォーマット指定できない。TableFilter_JUDG で書き戻しして、カンマを削除している。 287 } 288 else if( "TP_REAL".equals( dbType ) ) { 289 editAttri.set( "type" , "number" ); // type="number" だけだと、整数しか入らない。 290 editAttri.set( "step" , "0.01" ); // とりあえず、無条件に、0.01 刻みにする。 291 config.setEditorParam( "#0.00" ); // 7.4.2.3 (2021/06/09) 数値フォーマット(カンマ無し、桁数指定)を設定 292 } 293 294 // if( noViewlen >= 0 ) { config.setFieldSize( table.getValue( row,noViewlen ) ); } // フィールドの表示桁数 295 final String viewLen = rowData( row,noViewlen,"" ); // フィールドの文字桁数 296 if( !viewLen.isEmpty() ) { 297 config.setMaxlength( viewLen ); 298 299 // dbType が、TP_REAL の場合は、表示桁数 に合わせて、step を再設定する。 300 if( "TP_REAL".equals( dbType ) ) { 301 if( viewLen.contains( ".1" ) ) { 302 editAttri.set( "step" , "0.1" ); 303 // config.setEditorParam( "#0.0" ); // 7.4.2.3 (2021/06/09) 数値フォーマット(カンマ無し、桁数指定)を設定 304 } 305 else if( viewLen.contains( ".2" ) ) { 306 editAttri.set( "step" , "0.01" ); 307 // config.setEditorParam( "#0.00" ); // 7.4.2.3 (2021/06/09) 数値フォーマット(カンマ無し、桁数指定)を設定 308 } 309 else if( viewLen.contains( ".3" ) ) { 310 editAttri.set( "step" , "0.001" ); 311 // config.setEditorParam( "#0.000" ); // 7.4.2.3 (2021/06/09) 数値フォーマット(カンマ無し、桁数指定)を設定 312 } 313 else { 314 editAttri.set( "step" , "any" ); 315 } 316 } 317 } 318 319 final String cddisp = rowData( row,noCddisp,"1" ); // 1:ラベルカラム 2:カラム単発 3:カラム連続 4:表示のみ 320 321 // 表示方法(CDDISP)=3:カラム連続 かつ ラベルの末尾が数字の場合は、①~の番号を placeholder にセットする。 322 if( "3".equals( cddisp ) && !optAttr.contains( "placeholder" ) ) { // オプション属性 に plaseholder が未設定の場合のみ 323 int idx = lbl.length()-1; 324 while( idx >= 0 ) { 325 final char ch = lbl.charAt( idx ); 326 if( '0' <= ch && ch <= '9' ) { idx--; } // 末尾から数字の間、処理を継続 327 else { break; } // 数字でなくなった時点で処理終了 328 } 329 if( idx >= 0 && idx < lbl.length()-1 ) { // 末尾に何らかの数値があった場合 330 final char plc = (char)('①' + ( Integer.parseInt(lbl.substring( idx+1 ))-1 ) ); 331 editAttri.set( "placeholder" , String.valueOf( plc ) ); 332 } 333 } 334 335// // 理由 があれば、title に入れて popup させる 336// final String riyu= rowData( row,noRiyu,"" ); 337// if( ! riyu.isEmpty() ) { 338// editAttri.set( "title" , riyu ); 339// } 340 341 // 登録方法(CDREC) が、1:不要 か、書き込み禁止(isWritable( row )がfalse) の場合は、disabled をセットする。 342 if( "1".equals( cdrec ) || !isWritable( row ) ) { 343 editAttri.set( "disabled" , "disabled" ); // 1:不要 は、disabled をセットする。 344 } 345 346 // config.setEditorAttributes( editAttri ); // 内部オブジェクトを追加しているので、再設定不要。追加する場合に使用する。 347 348 if( "TP_FILE".equals( dbType ) ) { // ファイル添付は、値をアップロードするフォルダとする。 349 config.setEditorParam( "UPLOAD_DIR=" + val ); // jsp 以下のフォルダになります。 350 } 351 352 // RENDERE_TYPE="TP_IFRAME,TP_IMAGE,TP_LINE,TP_SIGNAL" は、Rendereを使う。 353 // 表示方法(CDDISP) 4:表示のみ の場合も、Rendereを使う。 354 // final String valBuf ; 355 String valBuf ; 356// if( "TP_IFRAME".equals( dbType ) || "TP_IMAGE".equals( dbType ) || "TP_LINE".equals( dbType ) || "TP_SIGNAL".equals( dbType ) || "4".equals( cddisp ) ) { 357 if( RENDERE_TYPE.contains( dbType ) || "4".equals( cddisp ) ) { 358 if( !optAttr.isEmpty() ) { 359 // final Attributes rendAttri = config.getRendererAttributes(); // 内部オブジェクトを取得している。 360 // rendAttri.add( "optionAttributes" , optAttr ); 361 config.setRendererParam( optAttr ); 362 } 363 valBuf = new DBColumn( config ).getRendererValue( row,val ); // 表示欄(Renderer) 364 } 365 else { 366 if( !optAttr.isEmpty() ) { 367 editAttri.add( "optionAttributes" , optAttr ); 368 // config.setEditorParam( optAttr ); 369 } 370 371 // dbType が、TP_MENU かTP_RADIO の場合は、DBMENUの引数($2)に、トークンを渡す。(GG03を検索する) 372 String tempVal = val; 373 if( "TP_MENU".equals( dbType ) || "TP_RADIO".equals( dbType ) ) { 374 config.setAddNoValue( true ); // プルダウンメニューは、空欄を選択できるようにしておく 375 tempVal = val + ":" + token; // DBMENUの引数($2) 376 } 377 378 valBuf = new DBColumn( config ).getEditorValue( row,tempVal ); // 入力欄(Editor) 379 } 380 381 // 理由 があれば、valBuf の直後にそのまま入れる。 382 final String riyu= rowData( row,noRiyu,"" ); 383 if( ! riyu.isEmpty() ) { 384 valBuf = valBuf + riyu ; 385 } 386 387 final int colspan = rowData( row,noColspan,1 ); 388 final int rowspan = rowData( row,noRowspan,1 ); 389 390 // 表示方法(CDDISP) 1:ラベルカラム 2:カラム単発 3:カラム連続 4:表示のみ で、 391 // 3:カラム連続 の場合のみ、</td> の直前に INSERT する。 392 393 // ラベル項目の表示 394 if( "1".equals( cddisp ) ) { // CDDISP=1:ラベルカラム の場合、ラベル表示される(colspanなし) 395 if( 1 == rowspan ) { 396 tagOut.append( "<td class='label'>" ); 397 } 398 else { 399 tagOut.append( "<td class='label' rowspan=\"" ).append( rowspan ).append( "\">" ); 400 } 401 tagOut.append(lbl).append( "</td>" ); 402 } 403 404 if( "1".equals( cddisp ) || "2".equals( cddisp ) ) { // CDDISP=1:ラベルカラム or 2:カラム単発 の場合 td が必要。 405 tagOut.append( "<td" ); 406 // colspan を反映させるのは、フィールド部のみ 407 if( 1 != colspan ) { 408 tagOut.append( " colspan=\"" ).append( colspan ).append( '"' ); // ラベルと本体があるが自分で調整する。 409 } 410 411 // rowspan を反映させるのは、フィールド部のみ 412 if( 1 != rowspan ) { 413 tagOut.append( " rowspan=\"" ).append( rowspan ).append( '"' ); 414 } 415 tagOut.append( '>' ).append( valBuf ).append( INS_VAL ); // INS_VAL は、CDDISP=3:カラム連続 の場合の挿入位置 416 taniErrWarn( row,tagOut ); 417 } 418 419 // 4:表示のみ の場合は、td を出す。 420 if( "4".equals( cddisp ) ) { // CDDISP=4:表示のみ の場合 td が必要。 421 tagOut.append( "<td" ); 422 // colspan を反映させる 423 if( 1 != colspan ) { 424 tagOut.append( " colspan=\"" ).append( colspan ).append( '"' ); // colspan をそのまま出す。自分で調整する。 425 } 426 427 // rowspan を反映させるのは、フィールド部のみ 428 if( 1 != rowspan ) { 429 tagOut.append( " rowspan=\"" ).append( rowspan ).append( '"' ); 430 } 431 tagOut.append( '>' ).append( valBuf ).append( "</td>" ); // valBuf を使うが、先にRenderer の値を設定している。 432 } 433 434 if( "3".equals( cddisp ) ) { // CDDISP=3:カラム連続 の場合は、INS_VALの直前に挿入する。 435 final int lstIdx = tagOut.lastIndexOf( INS_VAL ) ; 436 if( lstIdx >= 0 ) { 437 tagOut.insert( lstIdx,valBuf ); 438 } 439 else { // ありえないはずだが、挿入位置が見つからない場合は、td で囲う。 440 tagOut.append( "<td>" ).append( valBuf ).append( INS_VAL ).append( "</td>" ); 441 } 442 } 443 } 444 445 tagOut.append(" </tr></tbody></table>").append( CR ); 446 if( !bkSelNm.isEmpty() ) { tagOut.append( "</fieldset>" ); } 447 tagOut.append( getScrollBarEndDiv() ); 448 449 return tagOut.toString().replace( INS_VAL , "" ); // 最後に文字列に変換後、INS_VAL は、すべて空文字列に置き換えます。 450 } 451 452 /** 453 * 値出力の終端処理をまとめて行います。 454 * 455 * 全体出力の tagOut に、値フィールドの valBuf と、 tani を連結し、 456 * DBTableModelから、異常下限,警告下限,警告上限,異常上限を、div で固めます。 457 * valBuf は、初期化されます。 458 * 459 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加 460 * 461 * @param row 行 462 * @param tagOut 全体出力のStringBuilder 463 * @param valBuf 値フィールドのStringBuilder(このメソッド内でクリアする) 464 * @param tani 単位 465 */ 466// private void valBufOut( final int row,final StringBuilder tagOut,final StringBuilder valBuf,final String tani ) { 467 private void taniErrWarn( final int row,final StringBuilder tagOut ) { 468 final String tani = rowData( row,noTani,"(",")" ); // 単位表示(カラムの最後に出す) 469 tagOut.append( tani ); 470 471 final String wmin = rowData( row,noWmin,"" ); // 警告下限(W_MIN) 472 final String wmax = rowData( row,noWmax,"" ); // 警告上限(W_MAX) 473 final String emin = rowData( row,noEmin,"" ); // 異常下限(E_MIN) 474 final String emax = rowData( row,noEmax,"" ); // 異常上限(E_MAX) 475 476 if( wmin.isEmpty() && wmax.isEmpty() && emin.isEmpty() && emax.isEmpty() ) { 477 tagOut.append( "</td>" ); 478 } 479 else { 480 tagOut.append( "<div class='small' title='上段:警告 下段:異常'>" ); 481 482 if( !wmin.isEmpty() || !wmax.isEmpty() ) { // 警告下限(W_MIN) 警告上限(W_MAX) 483 final String max = "%" + Math.max( wmin.length() , wmax.length() ) + "s"; // 最大桁数を求める。 484 tagOut.append( String.format( max + "~" + max ,wmin,wmax ) ); 485 } 486 tagOut.append( "</br>" ); 487 488 if( !emin.isEmpty() || !emax.isEmpty() ) { // 異常下限(E_MIN) 異常上限(E_MAX) 489 final String max = "%" + Math.max( emin.length() , emax.length() ) + "s"; // 最大桁数を求める。 490 tagOut.append( String.format( max + " ~ " + max ,emin,emax ) ); // 異常の範囲の方が広いので、間を少し開けている。 491 } 492 tagOut.append( "</div></td>" ); 493 } 494 } 495 496 /** 497 * DBTableModelから、指定行-列のデータを取得します。 498 * 499 * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。 500 * 501 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加 502 * 503 * @param row 行 504 * @param col 列 505 * @param defVal 初期値(文字列) 506 * 507 * @return 指定行-列のデータ(文字列) 508 */ 509 private String rowData( final int row , final int col , final String defVal ) { 510 String rtn = defVal ; 511 if( col >= 0 ) { 512 final String str = table.getValue( row,col ); 513 if( str != null && !str.isEmpty()) { 514 rtn = str ; 515 } 516 } 517 return rtn ; 518 } 519 520 /** 521 * DBTableModelから、指定行-列のデータを取得し、前後に文字列を追加します。 522 * 523 * 列番号がマイナスの場合は、カラムが存在していないため、長さゼロの文字列を返します。 524 * 取得したデータが、長さゼロの文字列でない場合は、前後に指定の文字列を追加して返します。 525 * 526 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加 527 * 528 * @param row 行 529 * @param col 列 530 * @param prefix 前に付ける文字列 531 * @param suffix 後ろに付ける文字列 532 * 533 * @return 指定行-列のデータ(文字列) 534 */ 535 private String rowData( final int row , final int col , final String prefix , final String suffix ) { 536 String rtn = "" ; 537 if( col >= 0 ) { 538 final String str = table.getValue( row,col ); 539 if( str != null && !str.isEmpty()) { 540 rtn = prefix + str + suffix ; 541 } 542 } 543 return rtn ; 544 } 545 546 /** 547 * DBTableModelから、指定行-列のデータを取得します。 548 * 549 * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。 550 * 551 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加 552 * 553 * @param row 行 554 * @param col 列 555 * @param defVal 初期値(数値) 556 * 557 * @return 指定行-列のデータ(数値) 558 */ 559 private int rowData( final int row , final int col , final int defVal ) { 560 final String val = col < 0 ? null : table.getValue( row,col ) ; 561 562 try { 563 return val == null || val.isEmpty() ? defVal : Integer.parseInt( val ); 564 } 565 catch( final NumberFormatException ex ) { 566 final String errMsg = "数値項目に数値以外の文字が含まれています。行=" + row + " , 列=" + col + " , 値=" + val ; 567 throw new HybsSystemException( errMsg,ex ); 568 } 569 } 570 571 /** 572 * DBタイプ TP_YMD、TP_HMS、TP_YMDH の初期値に現在時刻を求めます。 573 * 574 * DBタイプが、上記以外か、val が NOW 以外の場合は、val をそのまま返します。 575 * 576 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加 577 * 578 * @param dbType DBタイプ TP_YMD、TP_HMS、TP_YMDH 以外は、引数のval をそのまま返します。 579 * @param val 変換する文字列 NOW 以外の場合は、引数のval をそのまま返します。 580 * 581 * @return 日時タイプの初期値を求めます 582 */ 583 private String timeVal( final String dbType , final String val ) { 584 String rtn = val; 585 if( "NOW".equalsIgnoreCase( val ) ) { 586 final LocalDateTime now = LocalDateTime.now(); 587 588 if( "TP_YMD".equals(dbType) ) { 589 rtn = now.format( YMD ); 590 } 591 else if( "TP_HMS".equals(dbType) ) { 592 rtn = now.format( HM ); 593 } 594 else if( "TP_YMDH".equals(dbType) ) { 595 rtn = now.format( YMDHMS ); 596 } 597 } 598 599 return rtn ; 600 } 601 602 /** 603 * オプション属性の特殊記号を変換します。 604 * 605 * シングルクオートは必要です。『=』から後ろ全てをそのまま 適用します。 606 * 607 * 【これらの設定は、Attributesオブジェクトに設定します】 608 * P='AAA' → placeholder='AAA' 609 * T='ツールチップ' → title='ツールチップ' 610 * C='HALF' → class='HALF' 611 * S='XX:BB;YY:CC;' → style='XX:BB;YY:CC;' 612 * 613 * 【これらは変換して属性に設定します】 614 * W='120px' → width='120px' 615 * H='300px' → height='300px' 616 * D='GRP1' → dis='GRP1' DIS で指定したグループを disabled するときのキー 617 * 618 * 【DISはonchangeで書き込み不可制御を行います】 619 * DIS(・・・・) → onchange=disabl(this.・・・・) 620 * 以下、変換は同一です。 621 * DIS(value=='123','GRP1') → onchange=disabl(this.value=='123','GRP1') textfieldなど 622 * DIS(checked,'GRP1') → onchange=disabl(this.checked,'GRP1') チェックボックス 623 * DIS(selectedIndex==2,'GRP1') → onchange=disabl(selectedIndex==2,'GRP1') プウルダウンメニュー(インデックス判定) 624 * DIS(options[selectedIndex].value=='テスト2','GRP1') → onchange=disabl(options[selectedIndex].value=='テスト2','GRP1') プウルダウンメニュー(値判定) 625 * 626 * 【ANVは、addNoValue制御の略で、メニューに空オプションを追加できます】 627 * ANV='true' → DBColumnConfig#setAddNoValue(true) を設定します。 628 * 【AKLは、addKeyLabel制御の略で、trueでキー:ラベル形式、falseでラベルのみ、null(未指定)はリソースに準拠します】 629 * AKL='true' → DBColumnConfig#setAddKeyLabel("true") を設定します。 630 * 631 * 【それ以外は、変換なしで設定します】 632 * readonly → readonly (例) 633 * 634 * @og.rev 7.3.1.1 (2021/02/25) オプション属性の特殊記号を変換 635 * @og.rev 7.4.2.3 (2021/06/09) addNoValue制御、addKeyLabel制御を追加 636 * 637 * @param attri Attributesオブジェクト 638 * @param val 変換するオプション属性 639 * 640 * @return 変換後のオプション属性 641 */ 642// private String changeOptAttr( final Attributes attri,final String val ) { 643 private String changeOptAttr( final DBColumnConfig config , final Attributes attri,final String val ) { 644 if( val.isEmpty() ) { return val; } // 確率的に、空文字はそのまま返します。 645 646 final StringBuilder buf = new StringBuilder( val ); // 最終的に出力するタグの文字列バッファ 647 648 int st = 0; 649 int ed = 0; 650 651 st = buf.indexOf( "P=" ); 652 if( st >= 0 ) { 653 ed = Math.max( buf.indexOf( "'" , st+3 ),buf.indexOf( "\"" , st+3 ) ); // シングルか、ダブルか 654 attri.set( "placeholder" , buf.substring( st+3,ed ) ); // P= の後ろ+1から、最後のコーテーション(含まず)まで 655 buf.delete( st,ed+1 ); 656 } 657 658 st = buf.indexOf( "T=" ); 659 if( st >= 0 ) { 660 ed = Math.max( buf.indexOf( "'" , st+3 ),buf.indexOf( "\"" , st+3 ) ); 661 attri.set( "title" , buf.substring( st+3,ed ) ); // T= の後ろ+1から、最後のコーテーション(含まず)まで 662 buf.delete( st,ed+1 ); 663 } 664 665 st = buf.indexOf( "C=" ); 666 if( st >= 0 ) { 667 ed = Math.max( buf.indexOf( "'" , st+3 ),buf.indexOf( "\"" , st+3 ) ); 668 attri.add( "class" , buf.substring( st+3,ed ) ); // T= の後ろ+1から、最後のコーテーション(含まず)まで 669 buf.delete( st,ed+1 ); 670 } 671 672 st = buf.indexOf( "S=" ); 673 if( st >= 0 ) { 674 ed = Math.max( buf.indexOf( "'" , st+3 ),buf.indexOf( "\"" , st+3 ) ); 675 attri.add( "style" , buf.substring( st+3,ed ) ); // T= の後ろ+1から、最後のコーテーション(含まず)まで 676 buf.delete( st,ed+1 ); 677 } 678 679 // 7.4.2.3 (2021/06/09) addNoValue制御、addKeyLabel制御を追加 680 st = buf.indexOf( "ANV=" ); 681 if( st >= 0 ) { 682 ed = Math.max( buf.indexOf( "'" , st+5 ),buf.indexOf( "\"" , st+5 ) ); 683 config.setAddNoValue( Boolean.parseBoolean( buf.substring( st+5,ed ) ) ); 684 buf.delete( st,ed+1 ); 685 } 686 687 // 7.4.2.3 (2021/06/09) addNoValue制御、addKeyLabel制御を追加 688 st = buf.indexOf( "AKL=" ); 689 if( st >= 0 ) { 690 ed = Math.max( buf.indexOf( "'" , st+5 ),buf.indexOf( "\"" , st+5 ) ); 691 config.setAddKeyLabel( buf.substring( st+5,ed ) ); // 空文字列は、処理不定 692 buf.delete( st,ed+1 ); 693 } 694 695 return buf.toString() 696 .replace( "W=" , "width=" ) 697 .replace( "H=" , "height=" ) 698 .replace( "D=" , "dis=" ) 699 .replace( "DIS(" , "onchange=disabl(this." ) ; 700 } 701 702 /** 703 * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。 704 * 705 * @og.rev 3.5.2.0 (2003/10/20) ヘッダーそのもののキャッシュはしない。 706 * 707 * @return テーブルのヘッダータグ文字列 708 * @og.rtnNotNull 709 */ 710// protected String getHeader() { 711// // ヘッダーは不要なので、オーバーライドしておく。 712// return "" ; 713// } 714}