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