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.hayabusa.db; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.fukurou.util.LogWriter; 020import org.opengion.hayabusa.resource.ResourceFactory; 021import org.opengion.hayabusa.resource.ResourceManager; 022import org.opengion.fukurou.db.DBUtil; 023import org.opengion.fukurou.util.ApplicationInfo; 024 025import java.util.Map; 026import java.util.HashSet; 027import java.util.HashMap; 028 029/** 030 * データのコード情報を取り扱うクラスです。 031 * 032 * コードのキーとラベルの情報から、HTMLのメニューやリストを作成するための オプション 033 * タグを作成したり、与えられたキーをもとに、チェック済みのオプションタグを作成したり 034 * します。 035 * QUERYの第1カラムは、選択キーになります。第2カラムはラベルです。ここまでは必須です。 036 * 第3カラムが存在する場合は、短縮カラムとして認識されます。存在しない場合は、 037 * 短縮ラベルは使用しません。 038 * 039 * メニュー作成用に、SELECT文を与えます。 040 * SELECT 値,ラベル[,グループ][,クラス] FROM XXXX で指定され、値、ラベルまでは必須、 041 * グループは、optgroup に対して指定するラベルです。クラスは、そのオプションに 042 * 色づけなどを行う為の指定です。 043 * なお、グループ、クラス は、NULL(または、ゼロ文字列)の場合は、適用されません。) 044 * 045 * @og.group 選択データ制御 046 * 047 * @version 4.0 048 * @author Kazuhiko Hasegawa 049 * @since JDK5.0, 050 */ 051// public class Selection_DB implements Selection { 052public class Selection_DB extends Selection_NULL { 053 // 3.5.4.8 (2004/02/23) USE_MULTI_KEY_SELECT を定義しておきます。 054 private final boolean USE_MULTI_KEY_SELECT = HybsSystem.sysBool( "USE_MULTI_KEY_SELECT" ) ; 055 private final long DB_CACHE_TIME = (long)HybsSystem.sysInt( "DB_CACHE_TIME" ) ; 056 057 private final boolean isMultiSelect ; 058 private final boolean isShortLavel ; // 短縮ラベルを使用できるかどうか 059 private final long createTime ; // キャッシュの破棄タイミングを計るための作成時間 060 061 private final int[] ADRS ; 062 private final String CACHE ; 063 private final int LEN ; 064 private final int[] LADRS ; // 5.1.3.0 (2010/02/01) 065 private final String LCACHE ; // 5.1.3.0 (2010/02/01) 066 private final int LLEN ; // 5.1.3.0 (2010/02/01) 067 private final Map<String,Integer> map ; 068 069 private final String[] value ; // 値 070 private final String[] label ; // ラベル 071 private final String[] slabel ; // 短縮ラベル 072 073 private static final int VAL = 0; 074 private static final int LBL = 1; 075 private static final int SLBL = 2; 076 private static final int GRP = 3; 077 private static final int CLS = 4; 078 079 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 080 private static final ApplicationInfo appInfo; 081 static { 082 /** コネクションにアプリケーション情報を追記するかどうか指定 */ 083 boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 084 085 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 086 if( USE_DB_APPLICATION_INFO ) { 087 String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" ); 088 appInfo = new ApplicationInfo(); 089 // ユーザーID,IPアドレス,ホスト名 090 appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME ); 091 // 画面ID,操作,プログラムID 092 appInfo.setModuleInfo( "Selection_DB",null,null ); 093 } 094 else { 095 appInfo = null; 096 } 097 } 098 099 /** 100 * コンストラクター 101 * 102 * DB検索用のSQL文を与えて、初期化します。 103 * SQL文は、KEY,LNAME [,SNAME] で、第3項がなければ、LNAME を使用します。 104 * LNAME は、通常の値を返す場合に、SNAME は、一覧表示の値を返す場合に使用します。 105 * 特別に、KEY のみの場合は、lang に基づく ResourceManager からラベルを取得します。 106 * ただし、その場合は、オーナー(SYSTEM_ID)は選べません。 107 * 108 * @og.rev 3.5.4.2 (2003/12/15) コンストラクター 新規追加 109 * @og.rev 3.6.0.9 (2004/12/03) isMultiSelect の判定をラベル部のユニーク度で判定します。 110 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 111 * @og.rev 3.8.9.2 (2007/07/28) グループと、クラスを追加。Select文の第3、第4引数として指定。 112 * @og.rev 4.0.0.0 (2006/11/15) lang 属性を追加します。 113 * @og.rev 4.3.8.0 (2009/08/01) ツールチップ表示機能追加 114 * @og.rev 5.1.3.0 (2010/02/01) ラベル(短)がnullの場合でも、ラベル(短)で表示されてしまうバグを修正 115 * @og.rev 5.1.3.0 (2010/02/01) 一覧表示以外は、ツールチップ表示しない 116 * 117 * @param newQuery DB検索(SQL)文字列 118 * @param dbid データベース接続先ID 119 * @param lang リソースを使用する場合の言語 120 */ 121 public Selection_DB( final String newQuery,final String dbid,final String lang ) { 122 123 String[][] cols = DBUtil.dbExecute( newQuery,null,appInfo,dbid ); // 3.8.7.0 (2006/12/15) 124 int count = cols.length; 125 126 value = new String[count]; 127 label = new String[count]; 128 slabel = new String[count]; 129 ADRS = new int[count]; 130 map = new HashMap<String,Integer>(count); 131 132 int len = ( count > 0 ) ? cols[0].length : 0 ; 133 isShortLavel = len > SLBL ; // >= 3 と同意; 134 boolean isGrp = len > GRP ; // >= 4 と同意; 135 boolean isCls = len > CLS ; // >= 5 と同意; 136 137 boolean useLabelData = false ; 138 ResourceManager resource = null; 139 if( len == 1 ) { 140 useLabelData = true; 141 resource = ResourceFactory.newInstance( lang ); 142 } 143 144 // 3.6.0.9 (2004/12/03) 145 HashSet<String> set = new HashSet<String>(); 146 boolean flag = USE_MULTI_KEY_SELECT; // 判定処理を行う。false なら判定処理も行わない。 147 148 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_LARGE ); 149 String bkGroupKey = ""; 150 for( int i=0; i<count; i++ ) { 151 value[i] = cols[i][VAL]; 152 if( useLabelData ) { 153 label[i] = resource.getLabel( value[i] ); 154 } 155 else { 156 label[i] = cols[i][LBL]; 157 if( isShortLavel ) { slabel[i] = cols[i][SLBL]; } 158 } 159 map.put( value[i], Integer.valueOf( i ) ); 160 161 // 3.8.9.2 (2007/07/28) 162 if( isGrp ) { 163 String groupKey = cols[i][GRP]; 164 if( !groupKey.equals( bkGroupKey ) ) { // キーブレイク 165 if( ! "".equals( bkGroupKey ) ) { 166 buf.append( "</optgroup>" ); 167 } 168 if( ! "".equals( groupKey ) ) { 169 buf.append( "<optgroup label=\"" + groupKey + "\">" ); 170 } 171 bkGroupKey = groupKey; 172 } 173 } 174 175 buf.append( "<option value=\"" ).append( value[i] ).append( "\"" ); 176 ADRS[i] = buf.length() ; 177 if( isCls ) { 178 String classKey = cols[i][CLS]; 179 if( ! "".equals( classKey ) ) { 180 buf.append( " class=\"" ).append( classKey ).append( "\"" ); 181 } 182 } 183 // 4.3.8.0 (2009/08/01) slabel利用の場合はlabelをtitle属性にセット 184 //buf.append( ">" ).append( label[i] ).append( "</option>" ); 185 if( isShortLavel && slabel[i] != null && slabel[i].length() > 0 ){ // 5.1.3.0 (2010/02/01) 186 if( !label[i].equals( slabel[i] ) ){ // slabelとlabelが異なる場合のみ 187 buf.append( " title=\"" ).append( label[i] ).append( "\"" ); 188 } 189 buf.append( ">" ).append( slabel[i] ); 190 } 191 else{ 192 buf.append( ">" ).append( label[i] ); 193 } 194 buf.append( "</option>" ); 195 196 // 3.6.0.9 (2004/12/03) 197 if( flag && label[i].length() > 0 ) { 198 flag = set.add( label[i].substring(0,1) ); // 重複時は false 199 } 200 } 201 if( isGrp && ! "".equals( bkGroupKey ) ) { 202 buf.append( "</optgroup>" ); 203 } 204 205 CACHE = buf.toString(); 206 LEN = CACHE.length() + 30; 207 208 // 5.1.3.0 (2010/02/01) ツールチップ表示が適用されている場合のみ、ツールチップなしの状態のoptionをキャッシュする。 209 if( CACHE.indexOf( "title=\"" ) < 0 ) { 210 LADRS = null; 211 LCACHE = null; 212 LLEN = 0; 213 } 214 else { 215 LADRS = new int[count]; 216 StringBuilder lbuf = new StringBuilder( HybsSystem.BUFFER_LARGE ); 217 218 bkGroupKey = ""; 219 for( int i=0; i<count; i++ ) { 220 if( isGrp ) { 221 String groupKey = cols[i][GRP]; 222 if( !groupKey.equals( bkGroupKey ) ) { 223 if( ! "".equals( bkGroupKey ) ) { lbuf.append( "</optgroup>" ); } 224 if( ! "".equals( groupKey ) ) { lbuf.append( "<optgroup label=\"" + groupKey + "\">" ); } 225 bkGroupKey = groupKey; 226 } 227 } 228 lbuf.append( "<option value=\"" ).append( value[i] ).append( "\"" ); 229 LADRS[i] = lbuf.length() ; 230 if( isCls && ! "".equals( cols[i][CLS] ) ) { 231 lbuf.append( " class=\"" ).append( cols[i][CLS] ).append( "\"" ); 232 } 233 lbuf.append( ">" ).append( label[i] ).append( "</option>" ); 234 } 235 if( isGrp && ! "".equals( bkGroupKey ) ) { 236 lbuf.append( "</optgroup>" ); 237 } 238 LCACHE = lbuf.toString(); 239 LLEN = LCACHE.length() + 30; 240 } 241 242 isMultiSelect = USE_MULTI_KEY_SELECT && ! flag ; // flag の反転に注意 243 createTime = System.currentTimeMillis() ; 244 } 245 246 /** 247 * 初期値が選択済みの 選択肢(オプション)を返します。 248 * このオプションは、引数の値を初期値とするオプションタグを返します。 249 * このメソッドでは、ラベル(短)が設定されている場合でも、これを使用せずに必ずラベル(長)を使用します。 250 * 251 * @og.rev 3.6.0.6 (2004/10/22) シーケンスアクセス機能を指定する seqFlag を導入 252 * @og.rev 4.0.0.0 (2005/01/31) selectValue が、null/ゼロ文字列でない場合に、選択肢にない場合は、エラー 253 * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 継承するため、削除 254 * 255 * @param selectValue 選択されている値 256 * @param seqFlag シーケンスアクセス機能 [true:ON/false:OFF] 257 * 258 * @return オプションタグ 259 * @see #getOption( String, boolean, boolean ) 260 */ 261// public String getOption( final String selectValue,final boolean seqFlag ) { 262// return getOption( selectValue, seqFlag, false ); 263// } 264 265 /** 266 * 初期値が選択済みの 選択肢(オプション)を返します。 267 * このオプションは、引数の値を初期値とするオプションタグを返します。 268 * このメソッドでは、引数のuseShortLabelがtrueに指定された場合に、ラベル(短)をベースとした 269 * ツールチップ表示を行います。 270 * 271 * @og.rev 5.1.3.0 (2010/02/01) 追加 272 * 273 * @param selectValue 選択されている値 274 * @param seqFlag シーケンスアクセス機能 [true:ON/false:OFF] 275 * @param useShortLabel ラベル(短)をベースとしたオプション表示を行うかどうか。 276 * 277 * @return オプションタグ 278 * @see #getOption( String, boolean ) 279 */ 280 @Override 281 public String getOption( final String selectValue,final boolean seqFlag, final boolean useShortLabel ) { 282 int[] adrs = null; 283 String cache = null; 284 int len = 0; 285 if( !useShortLabel && LCACHE != null && LCACHE.length() > 0 ) { 286 adrs = LADRS; 287 cache = LCACHE; 288 len = LLEN; 289 } 290 else { 291 adrs = ADRS; 292 cache = CACHE; 293 len = LEN; 294 } 295 296 // マッチするアドレスを探す。 297 Integer sel = map.get( selectValue ); 298 299 if( sel == null ) { 300 // 4.0.0 (2005/01/31) 301 if( selectValue != null && selectValue.length() > 0 ) { 302 String errMsg = "DBコードに存在しない値が指定されました。" 303 + " value=[" + selectValue + "]" 304 + HybsSystem.CR ; 305 LogWriter.log( errMsg ); 306 } 307 return cache; 308 } 309 else { 310 int selected = sel.intValue(); 311 StringBuilder buf = new StringBuilder( len ); 312 // 3.6.0.6 (2004/10/22) シーケンスアクセス機能を指定する seqFlag を導入 313 if( seqFlag ) { 314 buf.append( "<option value=\"" ).append( value[selected] ).append( "\"" ); 315 } 316 else { 317 buf.append( cache.substring( 0,adrs[selected] ) ); 318 } 319 buf.append( " selected=\"selected\"" ); 320 buf.append( cache.substring( adrs[selected] ) ); 321 return buf.toString() ; 322 } 323 } 324 325 /** 326 * 初期値が選択済みの 選択肢(オプション)を返します。 327 * このオプションは、引数の値を初期値とするオプションタグを返します。 328 * ※ このクラスでは実装されていません。 329 * 330 * @og.rev 2.1.0.1 (2002/10/17) 選択リストを、正方向にしか選べないようにする sequenceFlag を導入する 331 * @og.rev 3.8.6.0 (2006/09/29) useLabel 属性 追加 332 * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 継承するため、削除 333 * 334 * @param name ラジオの name 335 * @param selectValue 選択されている値 336 * @param useLabel ラベル表示の有無 [true:有/false:無] 337 * 338 * @return オプションタグ 339 */ 340// public String getRadio( final String name,final String selectValue,final boolean useLabel ) { 341// String errMsg = "このクラスでは実装されていません。"; 342// throw new UnsupportedOperationException( errMsg ); 343// } 344 345 /** 346 * 初期値が選択済みの 選択肢(オプション)を返します。 347 * このオプションは、引数の値を初期値とするオプションタグを返します。 348 * ※ このクラスでは実装されていません。 349 * 350 * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 継承するため、削除 351 * 352 * @param selectValue 選択されている値 353 * 354 * @return オプションタグ 355 */ 356// public String getRadioLabel( final String selectValue ) { 357// String errMsg = "このクラスでは実装されていません。"; 358// throw new UnsupportedOperationException( errMsg ); 359// } 360 361 /** 362 * 選択肢(value)に対するラベルを返します。 363 * 選択肢(value)が、存在しなかった場合は、選択肢そのものを返します。 364 * getValueLabel( XX ) は、getValueLabel( XX,false ) と同じです。 365 * 366 * @og.rev 5.7.7.1 (2014/06/13) Selection_NULL を 継承するため、削除 367 * 368 * @param selectValue 選択肢の値 369 * 370 * @return 選択肢のラベル 371 * @see #getValueLabel( String,boolean ) 372 */ 373// public String getValueLabel( final String selectValue ) { 374// return getValueLabel( selectValue,false ); 375// } 376 377 /** 378 * 選択肢(value)に対するラベルを返します。 379 * 選択肢(value)が、存在しなかった場合は、選択肢そのものを返します。 380 * このメソッドでは、短縮ラベルを返すかどうかを指定するフラグを指定します。 381 * getValueLabel( XX,false ) は、getValueLabel( XX ) と同じです。 382 * 383 * @og.rev 4.0.0.0 (2005/11/30) を追加 384 * @og.rev 5.3.5.0 (2011/05/01) 名称(短)表示時に名称(長)をツールチップで表示する。 385 * 386 * @param selectValue 選択肢の値 387 * @param flag 短縮ラベルを使用する [true:使用する/false:しない] 388 * 389 * @return 選択肢のラベル 390 * @see #getValueLabel( String ) 391 */ 392 @Override 393 public String getValueLabel( final String selectValue,final boolean flag ) { 394 // マッチするアドレスを探す。 395 Integer sel = map.get( selectValue ); 396 397 if( sel == null ) { 398 return selectValue; 399 } 400 else { 401 if( isShortLavel && flag ) { 402 return "<span title=\""+label[sel.intValue()]+"\">"+slabel[sel.intValue()]+"</span>"; 403 } 404 else { 405 return label[sel.intValue()] ; 406 } 407 } 408 } 409 410 /** 411 * マルチ・キーセレクトを使用するかどうかを返します。 412 * true:使用する。false:使用しない です。 413 * ただし、実際に使用するかどうかは、HTML出力時に決めることが出来ます。 414 * ここでは、USE_MULTI_KEY_SELECT が true で、USE_SIZE(=20)以上の場合に 415 * true を返します。 416 * 417 * @og.rev 3.5.5.7 (2004/05/10) 新規作成 418 * 419 * @return 選択リストで、マルチ・キーセレクトを使用するかどうか(true:使用する) 420 */ 421 @Override 422 public boolean useMultiSelect() { 423 return isMultiSelect; 424 } 425 426 /** 427 * オブジェクトのキャッシュが時間切れかどうかを返します。 428 * キャッシュが時間切れ(無効)であれば、true を、有効であれば、 429 * false を返します。 430 * 431 * @og.rev 4.0.0.0 (2005/01/31) 新規作成 432 * 433 * @return キャッシュが時間切れなら true 434 */ 435 @Override 436 public boolean isTimeOver() { 437 return ( System.currentTimeMillis() - createTime ) > DB_CACHE_TIME ; 438 } 439}