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 java.util.LinkedHashMap;
019import java.util.Map;
020import java.util.Collections;                                                                                   // 6.4.3.1 (2016/02/12)
021
022import org.opengion.fukurou.db.DBUtil;
023import org.opengion.fukurou.db.ApplicationInfo;
024import org.opengion.hayabusa.common.HybsSystem;
025import org.opengion.hayabusa.resource.ResourceFactory;
026import org.opengion.hayabusa.resource.ResourceManager;
027import static org.opengion.fukurou.system.HybsConst.BUFFER_LARGE;               // 6.1.0.0 (2014/12/26) refactoring
028
029/**
030 * データのコード情報を取り扱うクラスです。
031 *
032 * コードのキーとラベルの情報から、HTMLのメニューやリストを作成するための オプション
033 * タグを作成したり、与えられたキーをもとに、チェック済みのオプションタグを作成したり
034 * します。
035 * QUERYのそれぞれのカラムは、以下の意味を持ちます。
036 *  第1カラム(必須) : ラジオボタンのキー(値)
037 *  第2カラム       : ラベル(指定されない場合は、ラベルリソースの短縮ラベルを使用します)
038 *  第3カラム       : クラス そのオプションに色づけなどを行う為の指定します。
039 *                     NULL(または、ゼロ文字列)の場合は、適用されません。
040 *  第4カラム       : この値は'false'又は'0'である場合にそのラジオボタンを選択不可にします。
041 *                     NULL(または、ゼロ文字列)の場合は、選択可能になります。
042 *
043 * @og.group 選択データ制御
044 *
045 * @version  4.0
046 * @author   Hiroki Nakamura
047 * @since    JDK5.0,
048 */
049public class Selection_DBRADIO extends Selection_NULL {
050        private final long              DB_CACHE_TIME                   = (long)HybsSystem.sysInt( "DB_CACHE_TIME" ) ;
051
052        private final boolean   isClass ;                       // クエリでクラス属性が指定されているかどうか
053        private final boolean   isDisable ;                     // クエリで選択不可属性が指定されているかどうか
054        private final long              createTime ;            // キャッシュの破棄タイミングを計るための作成時間
055
056        /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
057        private final Map<String,Integer>       adrsMap  ;              // 6.4.3.1 (2016/02/12) ついでに変数名も変えておきます。
058
059        private final String[]  label   ;               // ラベル
060        private final String[]  cls     ;               // クラス
061        private final String[]  disabled ;              // ラジオ単位のdisable
062
063        private static final int VAL            = 0;
064        private static final int LBL            = 1;
065        private static final int CLS            = 2;
066        private static final int DISABLED       = 3;
067
068        private static final ApplicationInfo APP_INFO;                                                                          // 6.4.1.1 (2016/01/16) appInfo → APP_INFO refactoring
069        static {
070                /** コネクションにアプリケーション情報を追記するかどうか指定 */
071                final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
072
073                // 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
074                if( USE_DB_APPLICATION_INFO ) {
075                        final String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" );
076                        APP_INFO = new ApplicationInfo();
077                        // ユーザーID,IPアドレス,ホスト名
078                        APP_INFO.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
079                        // 画面ID,操作,プログラムID
080                        APP_INFO.setModuleInfo( "Selection_DBRADIO",null,null );
081                }
082                else {
083                        APP_INFO = null;
084                }
085        }
086
087        /**
088         * コンストラクター
089         *
090         * DB検索用のSQL文を与えて、初期化します。
091         * SQL文は、KEY,SNAMEで、SNAMEが設定されてない場合は、LNAMEを使用します。
092         * LNAME は、通常の値を返す場合に、SNAME は、一覧表示の値を返す場合に使用します。
093         * 特別に、KEY のみの場合は、lang に基づく ResourceManager からラベルを取得します。
094         * ただし、その場合は、オーナー(SYSTEM_ID)は選べません。
095         *
096         * @og.rev 5.1.9.0 (2010/08/01) String[] value 廃止
097         * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
098         *
099         * @param       newQuery        DB検索(SQL)文字列
100         * @param dbid  データベース接続先ID
101         * @param lang  リソースを使用する場合の言語
102         */
103        public Selection_DBRADIO( final String newQuery,final String dbid,final String lang ) {
104                super();                // 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
105
106                final String[][] cols = DBUtil.dbExecute( newQuery,null,APP_INFO,dbid );
107                final int count = cols.length;
108
109                label   = new String[count];
110                cls             = new String[count];
111                disabled= new String[count];
112                adrsMap = Collections.synchronizedMap( new LinkedHashMap<>(count) );    // 6.4.3.1 (2016/02/12) ついでに変数名も変えておきます。
113
114                final int len   = count > 0 ? cols[0].length : 0 ;
115                isClass   = len > CLS ;                 // >= 3 と同意;
116                isDisable = len > DISABLED ;    // >= 4 と同意;
117
118                boolean useLabelData = false ;
119                ResourceManager resource = null;
120                if( len == 1 ) {
121                        useLabelData = true;
122                        resource = ResourceFactory.newInstance( lang );
123                }
124
125                for( int i=0; i<count; i++ ) {
126                        final String value = cols[i][VAL];
127                        if( useLabelData ) {
128                                label[i] = resource.getShortLabel( value );
129                        }
130                        else {
131                                label[i] = cols[i][LBL];
132                        }
133
134                        if( isClass ) {
135                                cls[i] = cols[i][CLS];
136                        }
137                        if( isDisable ) {
138                                disabled[i] = cols[i][DISABLED];
139                        }
140
141                        adrsMap.put( value, Integer.valueOf( i ) );             // 6.4.3.1 (2016/02/12) ついでに変数名も変えておきます。
142                }
143
144                createTime = System.currentTimeMillis() ;
145        }
146
147        /**
148         * 初期値が選択済みの 選択肢(オプション)を返します。
149         * このオプションは、引数の値を初期値とするオプションタグを返します。
150         *
151         * @og.rev 6.2.2.4 (2015/04/24) メソッド変更。旧 #getRadio( String , String , boolean )
152         * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
153         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
154         *
155         * @param   name         ラジオの name
156         * @param   selectValue  選択されている値
157         * @param   useLabel     ラベル表示の有無 [true:有/false:無]
158         *
159         * @return  オプションタグ
160         * @og.rtnNotNull
161         */
162        @Override
163        public String getOption( final String name,final String selectValue,final boolean useLabel ) {
164                final String inputTag = "<input type=\"radio\" name=\"" + name + "\" value=\"" ;
165                final StringBuilder buf = new StringBuilder( BUFFER_LARGE );
166                for( final Map.Entry<String, Integer> e : adrsMap.entrySet() ) {                // 6.4.3.1 (2016/02/12) ついでに変数名も変えておきます。
167                        final String val = e.getKey();  // Ver 5.0.0.0 value ⇒ val
168                        final int valIdx = e.getValue().intValue();
169                        // 6.0.2.5 (2014/10/31) char を append する。
170                        if( useLabel ) {
171                                buf.append( "<label" );
172                                if( isClass && cls[valIdx] != null && cls[valIdx].length() > 0 ) {
173                                        buf.append( " class=\"" ).append( cls[valIdx] ).append( '"' );
174                                }
175                                buf.append( '>' );
176                        }
177                        buf.append( inputTag ).append( val ).append( '"' );
178                        if( val.equals( selectValue ) ) {
179                                buf.append( " checked=\"checked\"" );
180                        }
181
182                        if( isDisable && disabled[valIdx] != null && disabled[valIdx].length() > 0 ) {
183                                if( "false".equalsIgnoreCase( disabled[valIdx] ) || "0".equals( disabled[valIdx] ) ) {
184                                        buf.append( " disabled=\"disabled\"" );
185                                }
186                        }
187
188//                      buf.append( "/>" );
189                        buf.append( '>' );                              // 7.0.1.0 (2018/10/15)
190                        if( useLabel ) { buf.append( label[valIdx] ).append( "</label>" ); }
191                }
192                return buf.toString();
193        }
194
195        /**
196         * 選択肢(value)に対するラベルを返します。
197         * 選択肢(value)が、存在しなかった場合は、選択肢そのものを返します。
198         * このメソッドでは、短縮ラベルを返すかどうかを指定するフラグを指定します。
199         * getValueLabel( XX,false ) は、getValueLabel( XX ) と同じです。
200         *
201         * @og.rev 6.2.3.0 (2015/05/01) マーク表示を廃止。
202         * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
203         *
204         * @param       selectValue     選択肢の値
205         * @param       isSLbl  短縮ラベルを使用する [true:使用する/false:しない]
206         *
207         * @return  選択肢のラベル
208         * @see     #getValueLabel( String )
209         */
210        @Override
211        public String getValueLabel( final String selectValue,final boolean isSLbl ) {
212                // マッチするアドレスを探す。
213                final Integer sel = adrsMap.get( selectValue );                 // 6.4.3.1 (2016/02/12) ついでに変数名も変えておきます。
214
215                // 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
216                return sel == null ? selectValue : label[sel.intValue()] ;
217        }
218
219        /**
220         * オブジェクトのキャッシュが時間切れかどうかを返します。
221         * キャッシュが時間切れ(無効)であれば、true を、有効であれば、
222         * false を返します。
223         *
224         * @return  キャッシュが時間切れなら true
225         */
226        @Override
227        public boolean isTimeOver() {
228                return ( System.currentTimeMillis() - createTime ) > DB_CACHE_TIME ;
229        }
230}