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.column; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.AbstractEditor; 021import org.opengion.hayabusa.db.CellEditor; 022import org.opengion.hayabusa.db.DBColumn; 023import org.opengion.hayabusa.db.SelectionCellEditor; // 6.2.2.0 (2015/03/27) 024import org.opengion.hayabusa.db.Selection; 025import org.opengion.hayabusa.db.SelectionFactory; 026import org.opengion.fukurou.util.StringFormat; 027import org.opengion.fukurou.util.XHTMLTag; 028import org.opengion.fukurou.util.TagBuffer; 029import org.opengion.fukurou.util.StringUtil; // 8.5.4.2 (2024/01/12) import static … を個別に記述 030 031// import static org.opengion.fukurou.util.StringUtil.isNull; // 6.1.1.0 (2015/01/17) 032 033/** 034 * カラムの編集パラメーターのSQL文の実行結果より、datalistを作成して 035 * 入力候補となるデータリストを定義する編集用エディタークラスです。 036 * datalist は、HTML5 から採用されたタグです。 037 * 038 * 編集パラメータには、datalistを作成するための、SQL文を記述します。 039 * このSQL文は、select KEY,LABEL from xx ・・・ という構文で、KEY部分とLABEL部分が 040 * 選択されます。 041 * datalist 自身が、HTML5からの新機能なので、現時点では、これ以上の機能はありません。 042 * 将来的に、DBMENU などと同様に、第三カラム以降を利用可能になると思いますので、 043 * 今は使わないでください。(将来の機能追加時に互換性問題を引き起こすかもしれませんので) 044 * 045 * 入力フィールドとdatalistタグとの関係付は、カラムIDに、"カラムID.sel" で結びつけます。 046 * 047 * ただし、値なしのOptionを含めても(addNoValue="true")、HTML5の仕様上、 048 * 値なしのOptionは表示されません。 049 * 050 * <input name="カラムID" list="カラムID.sel" /> 051 * <del><div style="display:none;"></del> 052 * <datalist id="カラムID.sel"> 053 * <option value="KEY1">LABEL1</option> 054 * <option value="KEY2">LABEL2</option> 055 * <option value="KEY3">LABEL3</option> 056 * </datalist> 057 * <del></div></del> 058 * 059 * 7.0.1.4 (2018/11/26) autocomplete="off" を初期設定します。 060 * 061 * <del>divタグは、HTML5 非対応ブラウザを使用した場合、datalist の option がそのまま 062 * テキストとして見えてしまうのを避けるためです。</del> 063 * 064 * 一覧表出力時の getValue( int ,String ) 処理では、Selection オブジェクトの 065 * キャッシュ機能を利用して、同一Selection オブジェクトの間は、datalist は、 066 * 1度しか、出力しない様に制御しています。これにより、共有のdatalist を使用する為、 067 * HTMLの出力データ量を抑えることが可能になります。 068 * (キャッシュを利用しないと100行出力すると100個のdatalistを出力する事になります。) 069 * <del>(同様の機能を持つ INDBMENU では、行ごとにプルダウンデータを作成しています。)</del> 070 * ただし、行単位にSQLの条件を変える機能(AAA:BBB:CCC:DDD引数)が指定された場合は、 071 * 行ごとに出力します。 072 * 073 * 各カラムの値(value値)に、AAA:BBB:CCC:DDD という値を設定できます。これは、 074 * $1,$2,$3,$4 に割り当てなおして、QUERYを実行します。また、$1 は、本来の値として、 075 * メニューの初期値設定等に使用します。上記の例では、AAA が値で、それ以降は、 076 * 引数になります。 077 * 又、$Cには自分自身のカラム名を割り当てます。 078 * この機能を使用すれば、動的メニューを行ごとに条件を変えて作成することが 079 * 可能になります。 080 * 例:select KEY,LABEL from xx where KUBUN='$2' and CDK='$3' 081 * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない 082 * 変数は、""(ゼロ文字列)として、扱われます。 083 * 084 * カラムの表示に必要な属性は、DBColumn オブジェクト より取り出します。 085 * このクラスは、DBColumn オブジェクト毎に1つ作成されます。 086 * 087 * @og.rev 5.7.4.3 (2014/03/28) 新規作成 088 * @og.rev 6.2.2.0 (2015/03/27) SelectionCellEditor I/Fを追加 089 * @og.rev 8.5.2.0 (2023/07/14) 一部の機能廃止による修正(問合・トラブル 0200010980) 090 * @og.group データ編集(HTML5) 091 * 092 * @version 4.0 093 * @author Kazuhiko Hasegawa 094 * @since JDK5.0, 095 */ 096// 8.5.5.1 (2024/02/29) spotbugs CT_CONSTRUCTOR_THROW(コンストラクタで、Excweptionを出さない) class を final にすれば、警告は消える。 097// public class Editor_DATALIST extends AbstractEditor implements SelectionCellEditor { 098public final class Editor_DATALIST extends AbstractEditor implements SelectionCellEditor { 099 /** このプログラムのVERSION文字列を設定します。 {@value} */ 100 private static final String VERSION = "8.5.2.0 (2023/07/14)" ; 101 102 /** 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。 */ 103 private static final String DIV1 = "<div style=\"display:none;\">" ; 104 private static final String DIV2 = "</div>" ; 105 private static final String AUTO = "autocomplete" ; // 7.0.1.4 (2018/11/26) 106 private static final String OFF = "off" ; // 7.0.1.4 (2018/11/26) 107 108 private final String query ; 109 private final String dbid ; 110 private final String lang ; 111 /** 6.2.0.0 (2015/02/27) SLABEL 対応 */ 112 private final String useSLabel; 113 /** 6.2.0.0 (2015/02/27) キー:ラベル形式 */ 114 private final String addKeyLabel; 115 /** データのコード情報 */ 116 private final Selection selection; // 8.5.2.0 (2023/07/14) Add 117 /** シーケンスフラグ */ 118 private final boolean seqFlag; // 8.5.2.0 (2023/07/14) Add 119 120 /** 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能 */ 121 private Selection bkSel ; 122 123 /** 124 * デフォルトコンストラクター。 125 * このコンストラクターで、基本オブジェクトを作成します。 126 * 127 * @og.rev 6.2.0.0 (2015/02/27) SLABEL 対応 128 * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。 129 * @og.rev 8.5.2.0 (2023/07/14) 一部の機能廃止による修正(問合・トラブル 0200010980) 130 */ 131 public Editor_DATALIST() { 132 super(); // 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 133 query = null; 134 dbid = null; 135 lang = null; 136 useSLabel = "auto"; // 6.2.0.0 (2015/02/27) SLABEL 対応 137 addKeyLabel = null; // 6.2.0.0 (2015/02/27) キー:ラベル形式 138 selection = null; // 8.5.2.0 (2023/07/14) Add 139 seqFlag = false; // 8.5.2.0 (2023/07/14) Add 140 } 141 142 /** 143 * DBColumnオブジェクトを指定したprivateコンストラクター。 144 * 145 * @og.rev 6.2.0.0 (2015/02/27) SLABEL 対応 146 * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。 147 * @og.rev 7.0.1.4 (2018/11/26) autocomplete="off" を初期設定します。 148 * @og.rev 8.5.2.0 (2023/07/14) 一部の機能廃止による修正(問合・トラブル 0200010980) 149 * 150 * @param clm DBColumnオブジェクト 151 */ 152 private Editor_DATALIST( final DBColumn clm ) { 153 super( clm ); 154 // 7.0.1.4 (2018/11/26) autocomplete="off" を初期設定します。 155 // 8.5.4.2 (2024/01/12) import static … を個別に記述 156 if( StringUtil.isNull( attributes.get( AUTO ) ) ) { attributes.set( AUTO,OFF ); } 157 158 tagBuffer.add( XHTMLTag.inputAttri( attributes ) ); 159 160 query = clm.getEditorParam(); 161 dbid = clm.getDbid(); 162 lang = clm.getLang(); // 4.0.0.0 (2006/11/15) 163 useSLabel = clm.getUseSLabel(); // 6.2.0.0 (2015/02/27) SLABEL 対応 164 addKeyLabel = clm.getAddKeyLabel(); // 6.2.0.0 (2015/02/27) キー:ラベル形式 165 seqFlag = "SEQ".equals( query ); // 8.5.2.0 (2023/07/14) Add 166 167 // 編集パラメータが未指定の場合は、データのコード情報を取得 8.5.2.0 (2023/07/14) Add 168 if( query == null || query.isEmpty() || seqFlag ) { 169 selection = SelectionFactory.newSelection( "MENU",clm.getCodeData(),addKeyLabel ); 170 } 171 else { 172 selection = null; 173 } 174 175 // 3.5.5.9 (2004/06/07) 176// if( query == null || query.isEmpty() ) { 177 // 編集パラメータ 又は データのコード が未指定の場合 8.5.2.0 (2023/07/14) Modify 178 if( ( query == null || query.isEmpty() ) && selection == null ) { 179 final String errMsg = "DATALIST Editor では、編集パラメータは必須です。" 180 + " name=[" + name + "]" + CR ; 181 throw new HybsSystemException( errMsg ); 182 } 183 } 184 185 /** 186 * 各オブジェクトから自分のインスタンスを返します。 187 * 自分自身をキャッシュするのか、新たに作成するのかは、各サブクラスの実装に 188 * まかされます。 189 * 190 * @param clm DBColumnオブジェクト 191 * @return CellEditorオブジェクト 192 * @og.rtnNotNull 193 */ 194 public CellEditor newInstance( final DBColumn clm ) { 195 return new Editor_DATALIST( clm ); 196 } 197 198 /** 199 * データの編集用文字列を返します。 200 * 201 * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、 202 * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に 203 * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。 204 * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない 205 * 変数は、""(ゼロ文字列)として、扱われます。 206 * 又、$Cには自分自身のカラム名を割り当てます。 207 * 208 * @og.rev 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。 209 * @og.rev 5.7.6.2 (2014/05/16) list属性とid属性の結びつきを、name+".sel" に変更 210 * @og.rev 6.2.0.0 (2015/02/27) SLABEL 対応 211 * @og.rev 6.4.5.3 (2016/05/13) value は、コロン区切りの先頭だけ分離する。 212 * @og.rev 8.5.2.0 (2023/07/14) 一部の機能廃止による修正(問合・トラブル 0200010980) 213 * 214 * @param value 入力値 215 * @return データの編集用文字列 216 * @og.rtnNotNull 217 */ 218 @Override 219 public String getValue( final String value ) { 220 final String newValue = StringFormat.getValue( value ); // 6.4.5.3 (2016/05/13) コロン区切りの先頭だけ 221 222 // input タグの作成 223 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 224 final String intag = new TagBuffer( "input" ) 225 .add( "name" , name ) // 4.3.6.0 (2009/04/01) 226 // 8.5.4.2 (2024/01/12) import static … を個別に記述 227 .add( "id" , name , StringUtil.isNull( attributes.get( "id" ) ) ) // 4.3.7.2 (2009/06/15) 228 .add( "list" , name + ".sel" ) // datalistタグとの関係付けるためのキーワード 229 .add( "value" , newValue ) // 6.4.5.3 (2016/05/13) 230 .add( "size" , size1 ) 231 .add( tagBuffer.makeTag() ) 232 .makeTag(); 233 234 final boolean useSlbl = "true".equalsIgnoreCase( useSLabel ); // 6.2.0.0 (2015/02/27) 235 236 // datalist タグの作成 237 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 238// final String dltag = getOption( 239// new TagBuffer( "datalist" ) 240// .add( "id" , name + ".sel" ) // inputタグとの関係付けるためのキーワード 241// , value 242// , false // キャッシュは使用しない。(つまり、null は返らない) 243// , useSlbl // 6.2.0.0 (2015/02/27) SLABEL 対応 244// ).makeTag() ; 245 246 // 8.5.2.0 (2023/07/14) Modify 247 final String dltag; 248 // データのコード情報からdatalist作成 249 if( selection != null ) { 250 dltag = new TagBuffer( "datalist" ) 251 .add( "id" , name + ".sel" ) // inputタグとの関係付けるためのキーワード 252 .addBody( selection.getOption( value,seqFlag,useSlbl ) ) 253 .makeTag(); 254 } 255 // 編集パラメータからdatalist作成 256 else { 257 dltag = getOption( 258 new TagBuffer( "datalist" ) 259 .add( "id" , name + ".sel" ) // inputタグとの関係付けるためのキーワード 260 , value 261 , false // キャッシュは使用しない。(つまり、null は返らない) 262 , useSlbl // 6.2.0.0 (2015/02/27) SLABEL 対応 263 ).makeTag() ; 264 } 265 266 // DIV1 の display:none は、datalist の optionのBODY部が、HTML5 以外では表示されてしまうのを防ぐため。 267 return intag + CR + DIV1 + dltag + DIV2 + CR; 268 } 269 270 /** 271 * name属性を変えた、データ表示/編集用のHTML文字列を作成します。 272 * テーブル上の name に 行番号を付加して、名前_行番号 で登録するキーを作成し、 273 * リクエスト情報を1つ毎のフィールドで処理できます。 274 * 275 * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、 276 * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に 277 * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。 278 * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない 279 * 変数は、""(ゼロ文字列)として、扱われます。 280 * 又、$Cには自分自身のカラム名を割り当てます。 281 * 282 * @og.rev 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。 283 * @og.rev 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能 284 * @og.rev 5.7.6.2 (2014/05/16) list属性とid属性の結びつきを、name+".sel" に変更 285 * @og.rev 6.2.0.0 (2015/02/27) SLABEL 対応 286 * @og.rev 6.4.5.3 (2016/05/13) value は、コロン区切りの先頭だけ分離する。 287 * @og.rev 8.5.2.0 (2023/07/14) 一部の機能廃止による修正(問合・トラブル 0200010980) 288 * 289 * @param row 行番号 290 * @param value 入力値 291 * @return データ表示/編集用の文字列 292 * @og.rtnNotNull 293 */ 294 @Override 295 public String getValue( final int row,final String value ) { 296 final String name2 = name + HybsSystem.JOINT_STRING + row ; 297 298 // 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能 (true:使用可能) 299 final boolean useSelCache = value != null && value.indexOf( ':' ) < 0 ; 300 301 final String listId = useSelCache ? name : name2; // キャッシュを使用する場合は、共通の name を使う。 302 303 final String newValue = StringFormat.getValue( value ); // 6.4.5.3 (2016/05/13) コロン区切りの先頭だけ 304 305 // input タグの作成 306 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 307 final String intag = new TagBuffer( "input" ) 308 .add( "name" , name2 ) // 4.3.6.0 (2009/04/01) 309 // 8.5.4.2 (2024/01/12) import static … を個別に記述 310 .add( "id" , name2 , StringUtil.isNull( attributes.get( "id" ) ) ) // 4.3.7.2 (2009/06/15) 311 .add( "list" , listId + ".sel" ) // datalistタグとの関係付けるためのキーワード 312 .add( "value" , newValue ) // 6.4.5.3 (2016/05/13) 313 .add( "size" , size2 ) 314 .add( tagBuffer.makeTag() ) 315 .makeTag( row,newValue ); // 6.4.5.3 (2016/05/13) 316 317 final boolean useSlbl = "auto".equalsIgnoreCase( useSLabel ) || "true".equalsIgnoreCase( useSLabel ); // 6.2.0.0 (2015/02/27) 318 319 // datalist タグの作成 320 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 321// final TagBuffer dltag = getOption( 322// new TagBuffer( "datalist" ) 323// .add( "id" , listId + ".sel" ) // inputタグとの関係付けるためのキーワード 324// , value 325// , useSelCache 326// , useSlbl // 6.2.0.0 (2015/02/27) SLABEL 対応 327// ); 328 329 // 8.5.2.0 (2023/07/14) Modify 330 final TagBuffer dltag; 331 // データのコード情報からdatalist作成 332 if( selection != null ) { 333 dltag = new TagBuffer( "datalist" ) 334 .add( "id" , name + ".sel" ) // datalistタグとの関係付けるためのキーワード 335 .addBody( selection.getOption( value,seqFlag,useSlbl ) ); 336 } 337 // 編集パラメータからdatalist作成 338 else { 339 dltag = getOption( 340 new TagBuffer( "datalist" ) 341 .add( "id" , listId + ".sel" ) // datalistタグとの関係付けるためのキーワード 342 , value 343 , useSelCache 344 , useSlbl // 6.2.0.0 (2015/02/27) SLABEL 対応 345 ); 346 347 } 348 349 // キャッシュが効くと、getOption の戻り値は、null になる。 350 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 351 // 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 352 // 反転注意 353 return dltag == null 354 ? (intag + CR) 355 : (intag + CR + DIV1 + dltag.makeTag( row,newValue ) + DIV2 + CR) ; // 6.4.5.3 (2016/05/13) 356 } 357 358 /** 359 * 初期値が選択済みの 選択肢(オプション)をTagBuffer に反映します。 360 * このオプションは、引数の値を初期値とするオプションタグ作成し、TagBuffer 361 * に値を設定して返します。 362 * 363 * 第3引数は、Selection オブジェクトのキャッシュ機能を使用するかどうか指定します。 364 * true で、使用する事を前提に、チェックを行います。 365 * DBMENU など、他のメソッドでは、ラベル(短)の使用有無として使用しているため、異なります。 366 * 367 * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、 368 * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に 369 * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。 370 * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない 371 * 変数は、""(ゼロ文字列)として、扱われます。 372 * 又、$Cには自分自身のカラム名を割り当てます。 373 * 374 * @og.rev 6.2.0.0 (2015/02/27) SLABEL 対応 375 * @og.rev 6.2.0.0 (2015/02/27) キー:ラベル形式で表示するかどうかを、指定できるようにします。 376 * 377 * @param buf タグ文字列のバッファー 378 * @param value 選択されている値 379 * @param useSelCache Selection オブジェクトのキャッシュ機能を使用するかどうか。 380 * @param useSlbl ラベル(短)をベースとしたオプション表示を行うかどうか。 381 * @return オプションタグ 382 */ 383 private TagBuffer getOption( final TagBuffer buf,final String value,final boolean useSelCache,final boolean useSlbl ) { 384 385 final StringFormat format = new StringFormat( query, value, name ); 386 final String newQuery = format.format(); 387 388 // 6.2.0.0 (2015/02/27) キー:ラベル形式 389 final Selection selection = SelectionFactory.newDBSelection( newQuery, dbid, lang, addKeyLabel ); 390 391 if( useSelCache ) { 392 if( selection == bkSel ) { return null; } // SelectionFactory で生成したキャッシュの確認なので、== で判定しておきます。 393 bkSel = selection ; 394 } 395 396 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 397 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point. 398 final String newValue = format.getValue(); 399 return buf.addBody( selection.getOption( newValue, false, useSlbl ) ); // 6.2.0.0 (2015/02/27) SLABEL 対応 400 } 401}