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     */
016    package org.opengion.hayabusa.db;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.fukurou.util.LogWriter;
020    import org.opengion.hayabusa.resource.ResourceFactory;
021    import org.opengion.hayabusa.resource.ResourceManager;
022    import org.opengion.fukurou.db.DBUtil;
023    import org.opengion.fukurou.util.ApplicationInfo;
024    
025    import java.util.Map;
026    import java.util.HashSet;
027    import java.util.HashMap;
028    
029    /**
030     * ãƒ??タのコード情報を取り扱ã�?‚¯ラスですã?
031     *
032     * コードã?キーとラベルのæƒ??から、HTMLのメニューã‚?ƒªストを作æ?するための オプション
033     * タグを作æ?したりã?与えられたキーをもとに、チェãƒ?‚¯済みのオプションタグを作æ?したã‚?
034     * しますã?
035     * QUERYの第?‘カラãƒ??ã€?�¸択キーになりますã?第?’カラãƒ??ラベルですã?ここまではå¿??ですã?
036     * 第?“カラãƒ?�Œ存在する場合ã?、短縮カラãƒ?�¨して認識されますã?存在しなã�??合ã?ã€?
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 {
052            // 3.5.4.8 (2004/02/23) USE_MULTI_KEY_SELECT を定義しておきますã?
053            private final boolean USE_MULTI_KEY_SELECT      = HybsSystem.sysBool( "USE_MULTI_KEY_SELECT" ) ;
054            private final long        DB_CACHE_TIME                 = (long)HybsSystem.sysInt( "DB_CACHE_TIME" ) ;
055    
056            private final boolean   isMultiSelect ;
057            private final boolean   isShortLavel ;          // 短縮ラベルを使用できるかどã�?�‹
058            private final long              createTime ;            // キャãƒ?‚·ュの破æ£?‚¿イミングを計るための作æ?時間
059    
060            private final int[]             ADRS  ;
061            private final String    CACHE ;
062            private final int               LEN      ;
063            private final int[]             LADRS  ; // 5.1.3.0 (2010/02/01)
064            private final String    LCACHE ; // 5.1.3.0 (2010/02/01)
065            private final int               LLEN   ; // 5.1.3.0 (2010/02/01)
066            private final Map<String,Integer> map  ;
067    
068            private final String[]  value ;         // 値
069            private final String[]  label ;         // ラベル
070            private final String[]  slabel ;        // 短縮ラベル
071    
072            private static final int VAL  = 0;
073            private static final int LBL  = 1;
074            private static final int SLBL = 2;
075            private static final int GRP  = 3;
076            private static final int CLS  = 4;
077    
078            // 3.8.7.0 (2006/12/15) アクセスログ取得ã?為,ApplicationInfoオブジェクトを設å®?
079            private static final ApplicationInfo appInfo;
080            static {
081                    /** コネクションにアプリケーションæƒ??を追記するかどã�?�‹æŒ?®?*/
082                    boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
083    
084                    // 3.8.7.0 (2006/12/15) アクセスログ取得ã?為,ApplicationInfoオブジェクトを設å®?
085                    if( USE_DB_APPLICATION_INFO ) {
086                            String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" );
087                            appInfo = new ApplicationInfo();
088                            // ユーザーID,IPアドレス,ホスト名
089                            appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
090                            // 画面ID,操ä½?プログラãƒ?D
091                            appInfo.setModuleInfo( "Selection_DB",null,null );
092                    }
093                    else {
094                            appInfo = null;
095                    }
096            }
097    
098            /**
099             * コンストラクター
100             *
101             * ?¤?¢検索用の?³?±?¬æ–?‚’与えて、å?期化しますã?
102             * SQLæ–??、KEY,LNAME [,SNAME] で、第?“é?がなければ、LNAME を使用しますã?
103             * LNAME はã€??常の値を返す場合に、SNAME は、ä¸?¦§表示の値を返す場合に使用しますã?
104             * 特別に、KEY のみの場合ã?、lang に基づã�?ResourceManager から?—ベルを取得しますã?
105             * ただしã?そã?場合ã?、オーナã?(SYSTEM_ID)は選べませんã€?
106             *
107             * @og.rev 3.5.4.2 (2003/12/15) コンストラクター 新規追åŠ?
108             * @og.rev 3.6.0.9 (2004/12/03) isMultiSelect の判定をラベル部のユニã?ク度で判定しますã?
109             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得ã?為,ApplicationInfoオブジェクトを設å®?
110             * @og.rev 3.8.9.2 (2007/07/28) グループと、クラスを追åŠ??Selectæ–??第?“ã?第?”引数としてæŒ?®šã?
111             * @og.rev 4.0.0.0 (2006/11/15) lang 属æ?を追åŠ?�—ますã?
112             * @og.rev 4.3.8.0 (2009/08/01) ãƒ??ルチップ表示機è?追åŠ?
113             * @og.rev 5.1.3.0 (2010/02/01) ラベル(短)がnullの場合でもã?ラベル(短)で表示されてしまã�?ƒ�グを修正
114             * @og.rev 5.1.3.0 (2010/02/01) ä¸?¦§表示以外ã?、ツールチップ表示しなã�?
115             *
116             * @param newQuery      DB検索(SQL)æ–?­—å?
117             * @param dbid          ãƒ??タベã?ス接続å?ID
118             * @param lang          リソースを使用する場合ã?è¨?ª?
119             */
120            public Selection_DB( final String newQuery,final String dbid,final String lang ) {
121    
122                    String[][] cols = DBUtil.dbExecute( newQuery,null,appInfo,dbid );       // 3.8.7.0 (2006/12/15)
123                    int count = cols.length;
124    
125                    value   = new String[count];
126                    label   = new String[count];
127                    slabel  = new String[count];
128                    ADRS    = new int[count];
129                    map             = new HashMap<String,Integer>(count);
130    
131                    int len = ( count > 0 ) ? cols[0].length : 0 ;
132    //              isShortLavel = ( len >= 3 ) ? true : false ;
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 ){
186                            if( isShortLavel && slabel[i] != null && slabel[i].length() > 0 ){ // 5.1.3.0 (2010/02/01)
187                                    if( !label[i].equals( slabel[i] ) ){ // slabelとlabelが異なるå?合ã?み
188                                            buf.append( " title=\"" ).append( label[i] ).append( "\"" );
189                                    }
190                                    buf.append( ">" ).append( slabel[i] );
191                            }
192                            else{
193                                    buf.append( ">" ).append( label[i] );
194                            }
195                            buf.append( "</option>" );
196    
197                            // 3.6.0.9 (2004/12/03)
198                            if( flag && label[i].length() > 0 ) {
199                                    flag = set.add( label[i].substring(0,1) );      // 重è¤?™‚は false
200                            }
201                    }
202                    if( isGrp && ! "".equals( bkGroupKey ) ) {
203                            buf.append( "</optgroup>" );
204                    }
205    
206                    CACHE = buf.toString();
207                    LEN   = CACHE.length() + 30;
208    
209                    // 5.1.3.0 (2010/02/01) ãƒ??ルチップ表示が適用されてã�?‚‹場合ã?み、ツールチップなしã?状態ã?optionをキャãƒ?‚·ュするã€?
210                    if( CACHE.indexOf( "title=\"" ) < 0 ) {
211                            LADRS  = null;
212                            LCACHE = null;
213                            LLEN   = 0;
214                    }
215                    else {
216                            LADRS  = new int[count];
217                            StringBuilder lbuf = new StringBuilder( HybsSystem.BUFFER_LARGE );
218    
219                            bkGroupKey = "";
220                            for( int i=0; i<count; i++ ) {
221                                    if( isGrp ) {
222                                            String groupKey = cols[i][GRP];
223                                            if( !groupKey.equals( bkGroupKey ) ) {
224                                                    if( ! "".equals( bkGroupKey ) ) { lbuf.append( "</optgroup>" ); }
225                                                    if( ! "".equals( groupKey ) )   { lbuf.append( "<optgroup label=\"" + groupKey + "\">" ); }
226                                                    bkGroupKey = groupKey;
227                                            }
228                                    }
229                                    lbuf.append( "<option value=\"" ).append( value[i] ).append( "\"" );
230                                    LADRS[i] = lbuf.length() ;
231                                    if( isCls && ! "".equals( cols[i][CLS] ) ) {
232                                            lbuf.append( " class=\"" ).append( cols[i][CLS] ).append( "\"" );
233                                    }
234                                    lbuf.append( ">" ).append( label[i] ).append( "</option>" );
235                            }
236                            if( isGrp && ! "".equals( bkGroupKey ) ) {
237                                    lbuf.append( "</optgroup>" );
238                            }
239                            LCACHE = lbuf.toString();
240                            LLEN   = LCACHE.length() + 30;
241                    }
242    
243                    isMultiSelect = ( USE_MULTI_KEY_SELECT && ! flag ) ;    // flag の反転に注æ„?
244                    createTime = System.currentTimeMillis() ;
245            }
246    
247            /**
248             * 初期値が選択済みの 選択肢(オプション)を返しますã?
249             * こã?オプションは、引数の値をå?期å?とするオプションタグを返しますã?
250             * こã?メソãƒ?ƒ‰では、ラベル(短)が設定されてã�?‚‹場合でもã?これを使用せずにå¿?�šラベル(長)を使用しますã?
251             *
252             * @og.rev 3.6.0.6 (2004/10/22) シーケンスアクセス機è?を指定すã‚?seqFlag を導å?
253             * @og.rev 4.0.0.0 (2005/01/31) selectValue がã?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            public String getOption( final String selectValue,final boolean seqFlag, final boolean useShortLabel ) {
281                    int[] adrs = null;
282                    String cache = null;
283                    int len = 0;
284                    if( !useShortLabel && LCACHE != null && LCACHE.length() > 0 ) {
285                            adrs = LADRS;
286                            cache = LCACHE;
287                            len = LLEN;
288                    }
289                    else {
290                            adrs = ADRS;
291                            cache = CACHE;
292                            len = LEN;
293                    }
294    
295                    // マッチするアドレスを探すã?
296                    Integer sel = map.get( selectValue );
297    
298                    if( sel == null ) {
299                            // 4.0.0 (2005/01/31)
300                            if( selectValue != null && selectValue.length() > 0 ) {
301                                    String errMsg = "DBコードに存在しなã�??が指定されましたã€?
302                                                            + " value=[" + selectValue + "]"
303                                                            + HybsSystem.CR ;
304                                    LogWriter.log( errMsg );
305                            }
306                            return cache;
307                    }
308                    else {
309                            int selected = sel.intValue();
310                            StringBuilder buf = new StringBuilder( len );
311                            // 3.6.0.6 (2004/10/22) シーケンスアクセス機è?を指定すã‚?seqFlag を導å?
312                            if( seqFlag ) {
313                                    buf.append( "<option value=\"" ).append( value[selected] ).append( "\"" );
314                            }
315                            else {
316                                    buf.append( cache.substring( 0,adrs[selected] ) );
317                            }
318                            buf.append( " selected=\"selected\"" );
319                            buf.append( cache.substring( adrs[selected] ) );
320                            return buf.toString() ;
321                    }
322            }
323    
324            /**
325             * 初期値が選択済みの 選択肢(オプション)を返しますã?
326             * こã?オプションは、引数の値をå?期å?とするオプションタグを返しますã?
327             * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
328             *
329             * @og.rev 2.1.0.1 (2002/10/17) 選択リストを、正方向にしか選べなã�?‚ˆã�?�«する sequenceFlag を導å?する
330             * @og.rev 3.8.6.0 (2006/09/29) useLabel 属æ? 追åŠ?
331             *
332             * @param   name         ラジオの name
333             * @param   selectValue  選択されてã�?‚‹値
334             * @param   useLabel     ラベル表示の有無 [true:æœ?false:無]
335             *
336             * @return  オプションタグ
337             */
338            public String getRadio( final String name,final String selectValue,final boolean useLabel ) {
339                    String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
340                    throw new UnsupportedOperationException( errMsg );
341            }
342    
343            /**
344             * 初期値が選択済みの 選択肢(オプション)を返しますã?
345             * こã?オプションは、引数の値をå?期å?とするオプションタグを返しますã?
346             * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
347             *
348             * @param   selectValue  選択されてã�?‚‹値
349             *
350             * @return  オプションタグ
351             */
352            public String getRadioLabel( final String selectValue ) {
353                    String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
354                    throw new UnsupportedOperationException( errMsg );
355            }
356    
357            /**
358             * 選択肢(value)に対するラベルを返しますã?
359             * 選択肢(value)がã?存在しなかったå?合ã?ã€?�¸択肢そã?もã?を返しますã?
360             * getValueLabel( XX ) は、getValueLabel( XX,false ) と同じですã?
361             *
362             * @param   selectValue 選択肢の値
363             *
364             * @return  選択肢のラベル
365             * @see     #getValueLabel( String,boolean )
366             */
367            public String getValueLabel( final String selectValue ) {
368                    return getValueLabel( selectValue,false );
369            }
370    
371            /**
372             * 選択肢(value)に対するラベルを返しますã?
373             * 選択肢(value)がã?存在しなかったå?合ã?ã€?�¸択肢そã?もã?を返しますã?
374             * こã?メソãƒ?ƒ‰では、短縮ラベルを返すかどã�?�‹を指定するフラグを指定しますã?
375             * getValueLabel( XX,false ) は、getValueLabel( XX ) と同じですã?
376             *
377             * @og.rev 4.0.0.0 (2005/11/30) を追åŠ?
378             * @og.rev 5.3.5.0 (2011/05/01) 名称(短)表示時に名称(長)をツールチップで表示するã€?
379             *
380             * @param       selectValue     選択肢の値
381             * @param       flag    短縮ラベルを使用する [true:使用する/false:しない]
382             *
383             * @return  選択肢のラベル
384             * @see     #getValueLabel( String )
385             */
386            public String getValueLabel( final String selectValue,final boolean flag ) {
387                    // マッチするアドレスを探すã?
388                    Integer sel = map.get( selectValue );
389    
390                    if( sel == null ) {
391                            return selectValue;
392                    }
393                    else {
394                            if( isShortLavel && flag ) {
395    //                              return slabel[sel.intValue()];
396                                    return "<span title=\""+label[sel.intValue()]+"\">"+slabel[sel.intValue()]+"</span>";
397                            }
398                            else {
399                                    return label[sel.intValue()] ;
400                            }
401                    }
402            }
403    
404            /**
405             * マルチã?キーセレクトを使用するかどã�?�‹を返しますã?
406             * true?š使用する。false:使用しなã�?ですã?
407             * ただしã?実際に使用するかどã�?�‹は、HTML出力時に決めることがå?来ますã?
408             * ここでは、USE_MULTI_KEY_SELECT ã�?true で、USE_SIZE(=20)以上ã?場合に
409             * true を返しますã?
410             *
411             * @og.rev 3.5.5.7 (2004/05/10) 新規作æ?
412             *
413             * @return  選択リストで、ã?ルチã?キーセレクトを使用するかどã�?�‹(true:使用する)
414             */
415            public boolean useMultiSelect() {
416                    return isMultiSelect;
417            }
418    
419            /**
420             * オブジェクトã?キャãƒ?‚·ュが時間å?れかどã�?�‹を返しますã?
421             * キャãƒ?‚·ュが時間å?ã‚?無効)であれば、true をã?有効であればã€?
422             * false を返しますã?
423             *
424             * @og.rev 4.0.0.0 (2005/01/31) 新規作æ?
425             *
426             * @return  キャãƒ?‚·ュが時間å?れなã‚?true
427             */
428            public boolean isTimeOver() {
429                    return ( System.currentTimeMillis() - createTime > DB_CACHE_TIME ) ;
430            }
431    }