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.fukurou.db;
017
018import java.sql.DatabaseMetaData;
019import java.sql.SQLException;
020import java.util.Locale;
021import java.util.Properties;
022
023import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
024import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
025import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
026import org.opengion.fukurou.util.StringUtil;                            // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientEmptyStringCheck 対応
027
028/**
029 * JAXBで自動生成されたDBIDクラスを拡張したクラスです。
030 * (継承しているわけではない)
031 * <BR>
032 * 以下の属性が追加されています。<BR>
033 * dbProductName<BR>
034 * dbProductVersion<BR>
035 * driverName<BR>
036 * driverVersion<BR>
037 *
038 * @og.rev 4.0.0.0 (2007/10/25) 新規作成
039 * @og.rev 5.1.7.0 (2010/06/01) メソッドの修正、Cloneable の追加(浅いコピー)
040 * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加
041 *
042 * @version  4.0
043 * @author       高橋正和
044 * @since        JDK5.0,
045 */
046public class EDbid implements Cloneable {
047
048        private String  dbidKey                 = "DEFAULT";
049        private String  title                   ;                                               // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
050        private String  url                             ;
051        private String  user                    ;
052        private String  password                = "";                                   // 5.7.2.0 (2014/01/10) パスワードは空文字を初期値とする。
053        private boolean readonly                ;
054        private int             mincount                = 3;
055        private int             maxcount                = 30;
056        private int             pooltime                = 3000;         // (秒数)
057        private boolean isUseAppInfo    = true;
058        private boolean isParamMetaData ;                                               // 5.3.8.0 (2011/08/01)
059
060        private String  dbProductName   ;
061        private String  dbProductVersion;
062        private String  driverName              ;
063        private String  driverVersion   ;
064
065        /* 5.5.2.0 (2012/05/01) DBConfigでpropertiesの指定を可能にします */
066        private final Properties props = new Properties();
067
068        /**
069         * デフォルトコンストラクター
070         *
071         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
072         */
073        public EDbid() { super(); }             // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
074
075        /**
076         * dbidKeyの取得
077         *
078         * 内部的には、大文字のみで管理します。
079         *
080         * @return      dbidキー
081         */
082        public String getDbidKey() {
083                return dbidKey;
084        }
085
086        /**
087         * dbidキーの設定
088         *
089         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
090         * 内部的には、大文字のみで管理します。
091         *
092         * @og.rev 4.1.0.1 (2008/01/21) 登録時に、大文字に変換する。
093         *
094         * @param value 接続先ID
095         */
096        protected void setDbidKey( final String value ) {
097                if( isNotNull( value ) ) { dbidKey = value.toUpperCase( Locale.JAPAN ); }
098        }
099
100        /**
101         * 表題(title)属性の取得
102         *
103         * この、dbidKey を表す表題を取得します。ラベル(名前)のようなものです。
104         *
105         * @og.rev 5.6.6.0 (2013/07/05) 新規追加
106         *
107         * @return      表題(title)
108         */
109        public String getTitle() {
110                return title;
111        }
112
113        /**
114         * 表題(title)の設定
115         *
116         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
117         *
118         * @og.rev 5.6.6.0 (2013/07/05) 新規追加
119         * @og.rev 5.6.8.0 (2013/09/06) title が未設定の時は、dbidKey をセットしておきます。
120         *
121         * @param value 表題(title)
122         */
123        protected void setTitle( final String value ) {
124                if( isNotNull( value ) ) { title = value; }
125                else                                     { title = dbidKey; }           // 5.6.8.0 (2013/09/06)
126        }
127
128        /**
129         * URLの取得。
130         *
131         * @return      URL
132         */
133        public String getUrl() {
134                return url;
135        }
136
137        /**
138         * URLの設定
139         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
140         *
141         * @param value URL文字列
142         */
143        protected void setUrl( final String value ) {
144                if( isNotNull( value ) ) { url = value; }
145        }
146
147        /**
148         * ユーザーの取得。
149         *
150         * @return      ユーザー
151         */
152        public String getUser() {
153                return user;
154        }
155
156        /**
157         * userの設定
158         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
159         *
160         * @param value user文字列
161         */
162        protected void setUser( final String value ) {
163                if( isNotNull( value ) ) { user = value; }
164        }
165
166        /**
167         * パスワードの取得。
168         *
169         * @return      パスワード
170         */
171        public String getPassword() {
172                return password;
173        }
174
175        /**
176         * パスワードの設定
177         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
178         *
179         * @param value パスワード文字列
180         */
181        protected void setPassword( final String value ) {
182                if( isNotNull( value ) ) { password = value; }
183        }
184
185        /**
186         * readonlyの取得。
187         *
188         * @return      [true:読み取り専用/false:通常]
189         */
190        public boolean isReadonly() {
191                return readonly ;
192        }
193
194        /**
195         * readonlyの設定
196         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
197         *
198         * @param value  readonly文字列 [true/false]
199         */
200        protected void setReadonly( final String value ) {
201                if( isNotNull( value ) ) { readonly = Boolean.parseBoolean( value ); }          // 6.1.0.0 (2014/12/26) refactoring
202        }
203
204        /**
205         * 最小数の取得。
206         *
207         * @return      最小数
208         */
209        public int getMincount() {
210                return mincount;
211        }
212
213        /**
214         * 最小数の設定
215         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
216         *
217         * @param value 最小数(数字タイプ文字列)
218         */
219        protected void setMincount( final String value ) {
220                if( isNotNull( value ) ) { mincount = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
221        }
222
223        /**
224         * 最大数の取得。
225         *
226         * @return      最大数
227         */
228        public int getMaxcount() {
229                return maxcount;
230        }
231
232        /**
233         * 最大数の設定
234         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
235         *
236         * @param value 最大数(数字タイプ文字列)
237         */
238        protected void setMaxcount( final String value ) {
239                if( isNotNull( value ) ) { maxcount = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
240        }
241
242        /**
243         * プールに保管して置く時間(秒数)の取得。
244         *
245         * @return      プールに保管する時間(秒数)
246         */
247        public int getPooltime() {
248                return pooltime;
249        }
250
251        /**
252         * プールに保管して置く時間(秒数))の設定
253         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
254         *
255         * @param value プールに保管して置く時間(秒数)(数字タイプ文字列)
256         */
257        protected void setPooltime( final String value ) {
258                if( isNotNull( value ) ) { pooltime = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
259        }
260
261        /**
262         * ApplicationInfoオブジェクトを使用するかどうか[true/false]の情報を取得。
263         *
264         * @return      使用するかどうか
265         */
266        public boolean isApplicationInfo() {
267                return isUseAppInfo ;
268        }
269
270        /**
271         * ApplicationInfoオブジェクトを使用するかどうか[true/false]の情報を設定
272         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
273         *
274         * @param value ApplicationInfoオブジェクトを使用するかどうか [true/false]
275         */
276        protected void setApplicationInfo( final String value ) {
277                if( isNotNull( value ) ) { isUseAppInfo = Boolean.parseBoolean( value ); }      // 6.1.0.0 (2014/12/26) refactoring
278        }
279
280        /**
281         * メタデータを受け取って dbProductName,dbProductVersion,driverName,driverVersion を一括で設定します。
282         *
283         * @og.rev 4.0.0.0 (2007/10/30) 保持情報オブジェクト化に伴う変更
284         * @og.rev 5.3.8.0 (2011/08/01) postgreSQL時のカラムタイプ判定の必要有無(ApplicationInfo.useParameterMetaData)
285         * @og.rev 6.4.9.5 (2016/09/09) DERBY も、isParamMetaData=true を返します。
286         * @og.rev 8.0.0.0 (2021/09/30) FIREBIRD も、isParamMetaData=true を返します。
287         *
288         * @param meta メタデータオブジェクト
289         * @throws SQLException データベースアクセスエラー
290         */
291        public void setMetaDataInfo( final DatabaseMetaData meta ) throws SQLException {
292                dbProductName   = meta.getDatabaseProductName() ;
293                dbProductVersion= meta.getDatabaseProductVersion() ;
294                driverName              = meta.getDriverName() ;
295                driverVersion   = meta.getDriverVersion() ;
296
297                // dbProductName は、大文字にしておいても問題は無いが、今は影響範囲を小さくしておきます。
298                final String dbName = dbProductName.toUpperCase( Locale.JAPAN );                // 6.4.9.5 (2016/09/09) 大文字化します。
299
300                isUseAppInfo    = isUseAppInfo && "ORACLE".equalsIgnoreCase( dbProductName ) ;
301                isParamMetaData = dbName.contains( "POSTGRES" )
302                                                || dbName.contains( "FIREBIRD" )                                                // 8.0.0.0 (2021/09/30)
303                                                || dbName.contains( "DERBY" );                                                  // 6.4.9.5 (2016/09/09)
304        }
305
306        /**
307         * DBプロダクト名の取得。
308         *
309         * @return      DBプロダクト名
310         */
311        public String getDbProductName() {
312                return dbProductName;
313        }
314
315        /**
316         * DBプロダクト・バージョンの取得。
317         *
318         * @return      DBプロダクト・バージョン
319         */
320        public String getDbProductVersion() {
321                return dbProductVersion;
322        }
323
324        /**
325         * ドライバー名の取得。
326         *
327         * @return      ドライバー名
328         */
329        public String getDriverName() {
330                return driverName;
331        }
332
333        /**
334         * ドライバーのバージョンの取得。
335         *
336         * @return      ドライバーのバージョン
337         */
338        public String getDriverVersion() {
339                return driverVersion;
340        }
341
342        /**
343         * ParamMetaData を利用するかどうか[true/false]を返します。
344         *
345         * これは、PostgreSQL の時は、trueになります。
346         *
347         * @og.rev 5.3.8.0 (2011/08/01) 新規追加
348         *
349         * @return      利用するかどうか[true/false]
350         */
351        public boolean useParamMetaData() {
352                return isParamMetaData ;
353        }
354
355        /**
356         * propMapへの追加。
357         *
358         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
359         * @param key プロパティのキー
360         * @param val ポロパティの値
361         */
362        protected void addProp( final String key, final String val ) {
363                props.put ( key, val );
364        }
365
366        /**
367         * propMapへの追加。
368         * 最初の=でkeyとvalueを分割する
369         *
370         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
371         * @og.rev 5.5.2.1 (2012/05/07) propsへの追加漏れ、カンマを=に変更
372         * @param prop プロパティのキーと値の組み合わせ
373         */
374        protected void addProp( final String prop ) {
375                if( prop!=null && prop.indexOf( '=' ) > 0 ){
376                        final String key = prop.substring( 0 , prop.indexOf('=') );
377                        final String val = prop.substring( prop.indexOf('=') + 1 );
378                        addProp( key, val ); // 5.5.2.1 (2012/05/07)
379                }
380        }
381
382        /**
383         * propMapの取得。
384         *
385         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
386         * @og.rev 6.3.9.0 (2015/11/06) 内部Propertiesオブジェクトではなく、複製して返します。
387         *
388         * @return 複製Propertiesオブジェクト
389         */
390        public Properties getProps(){
391                return new Properties( props );                 // 6.3.9.0 (2015/11/06)
392        }
393
394        /**
395         * 文字列がnullでも空文字列でもないかどうかを評価します。
396         *
397         * スペース文字は、trim() してから、!isEmpty() で判断しますので、false になります。
398         *
399         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
400         *
401         * @param value 評価する文字列
402         *
403         * @return 結果(true:nullでも空文字列でもない)
404         */
405        private boolean isNotNull( final String value ) {
406                // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientEmptyStringCheck 対応
407//              return value != null && !value.trim().isEmpty() ;                       // 6.0.2.5 (2014/10/31) refactoring
408                return StringUtil.isNotNull( value ) ;                                          // 8.5.4.2 (2024/01/12) refactoring
409        }
410
411        /**
412         * 自分自身の clone を返します。
413         *
414         * Cloneable の実装で、内部的には、Object クラスの clone メソッドを読んでいます。
415         *
416         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
417         *
418         * @return      自分自身の clone を返します。
419         * @throws      RuntimeException clone が失敗しました場合
420         * @og.rtnNotNull
421         */
422        @Override                               // Object
423        public EDbid clone() {
424                try {
425                        return (EDbid)super.clone() ;
426                }
427                catch( final CloneNotSupportedException ex ) {
428                        final String errMsg = "clone が失敗しました。"
429                                                                + ex.getMessage() ;
430                        throw new OgRuntimeException( errMsg,ex );
431                }
432        }
433
434        /**
435         * 自分自身の clone を返します。
436         *
437         * ここでは、dbidKey を指定した、clone() を作成します。
438         * Titleも、指定した、dbidKey をセットしておきます。
439         *
440         * @og.rev 6.4.3.4 (2016/03/11) 新規作成
441         *
442         * @param id 接続先ID
443         * @return      dbidKeyを指定して、自分自身のcloneを返します。
444         * @og.rtnNotNull
445         */
446        public EDbid clone( final String id ) {
447                final EDbid obj = this.clone();
448                obj.setDbidKey( id );
449                obj.setTitle( id );
450
451                return obj;
452        }
453
454        /**
455         * 簡易な内部情報の文字列化します。
456         *
457         * @og.rev 5.3.4.0 (2011/04/01) toString() の簡易版
458         * @og.rev 5.5.2.1 (2012/05/07) properties情報を出力するようにする
459         * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加
460         *
461         * @return 内部情報の文字列
462         * @og.rtnNotNull
463         */
464        public String info() {
465                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ConsecutiveLiteralAppends 対応
466//              final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
467                return new StringBuilder( BUFFER_MIDDLE )
468                        .append( "DBID=["      ).append( dbidKey )
469                        .append( "] , TITLE=[" ).append( title   )              // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
470                        .append( "] , URL=["   ).append( url     )
471                        .append( "] , USER=["  ).append( user    ).append( ']'  )
472                        .append( CR )
473                        .append( "DB Product=[" ).append( dbProductName )
474                        .append( '(' ).append( dbProductVersion ).append( ")]" )
475                        .append( CR )
476                        .append( "DB Driver =[" ).append( driverName )
477                        .append( '(' ).append( driverVersion ).append( ")]" )
478                        .append( CR )
479                        .append( "PROPERTIES=[" ).append( props.toString() ).append( ']' ) // 5.5.2.1 (2012/05/07)
480                        .append( CR )
481                        .toString();
482//              return buf.toString();
483        }
484
485        /**
486         * 内部情報を文字列化します。
487         *
488         * @og.rev 5.3.4.0 (2011/04/01) info() メソッドを利用するように変更
489         *
490         * @return      内部情報の文字列
491         * @og.rtnNotNull
492         */
493        @Override                               // Object
494        public String toString() {
495                // 8.5.4.2 (2024/01/12) PMD 7.0.0 ConsecutiveLiteralAppends 対応
496//              final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
497                return new StringBuilder( BUFFER_MIDDLE )
498                        .append( info() )
499                //      .append( "DBID=[" ).append( dbidKey ).append( "]," )
500                //      .append( "URL =[" ).append( url     ).append( "]," )
501                //      .append( "USER=[" ).append( user    ).append( "]," )
502                //      .append( CR )
503                //      .append( "DB Product=[" ).append( dbProductName )
504                //      .append( "(" ).append( dbProductVersion ).append( ")" ).append( "]" )
505                //      .append( CR )
506                //      .append( "DB Driver =[" ).append( driverName )
507                //      .append( "(" ).append( driverVersion ).append( ")" ).append( "]" )
508                //      .append( CR )
509                        .append( "MINCOUNT=["   ).append( mincount )
510                        .append( "],MAXCOUNT=[" ).append( maxcount )
511                        .append( "],POOLTIME=[" ).append( pooltime )
512                        .append( "],READONLY=[" ).append( readonly )
513                        .append( "],APPINFO =[" ).append( isUseAppInfo )                // 6.0.2.5 (2014/10/31) char を append する。
514                        .append( ']' ).append( CR )
515                        .toString();
516//              return buf.toString();
517        }
518}