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