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