    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.resource;
    017
    018import java.util.Arrays;
    019import java.util.HashMap;
    020import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
    021import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.1 (2016/02/12) refactoring
    022import java.util.HashSet;
    023import java.util.LinkedHashMap;
    024import java.util.Map;
    025import java.util.Set;
    026
    027import java.util.stream.Stream;                                                                         // 6.4.1.1 (2016/01/16)
    028import java.util.stream.Collectors;                                                                     // 6.4.1.1 (2016/01/16)
    029
    030import org.opengion.fukurou.util.ErrMsg;
    031import org.opengion.fukurou.util.StringUtil;
    032import org.opengion.hayabusa.db.DBColumn;
    033import org.opengion.hayabusa.db.DBColumnConfig;
    034import static org.opengion.fukurou.system.HybsConst.BUFFER_LARGE;               // 6.1.0.0 (2014/12/26) refactoring
    035import org.opengion.hayabusa.common.HybsSystemException;                                // 6.4.3.3 (2016/03/04)
    036
    037/**
    038 * java.util.ResourceBundle クラスを複数管理するリソースクラスです。
    039 *
    040 * ResourceManager は、
    041 *      LabelResource.properties   ラベルリソース(テーブル定義やカラム名などの画面に表示するリソース)
    042 *      CodeResource.properties    コードリソース(選択データなどプルダウンメニューで選択するリソース)
    043 *      MessageResource.properties メッセージリソース(エラーコードやメッセージなどを表示するリソース)
    044 *
    045 * の３つのプロパティーファイルを内部に持っており,それぞれのメソッドにより，
    046 * リソースの返す値を決めています。
    047 *
    048 * ResourceManagerは,単独でも生成できますが，各ユーザー毎に作成するよりも
    049 * ResourceFactory#newInstance( lang )メソッドより生成した方が,プーリングされるので
    050 * 効率的です。
    051 *
    052 * リソース作成時に指定するロケールは,ISO 言語コード(ISO-639 で定義される 2 桁の小文字)
    053 * <a href ="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
    054 * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt</a>を使用して下さい。
    055 * ただし，内部的に Locale を構築していますが,その正しさは,チェックされていませんので,
    056 * 指定するロケールに応じた properties ファイルを用意しておいて下さい。
    057 *
    058 * 日本語の場合は, 言語コードは "jp" なので，
    059 *      LabelResource_jp.properties   ラベルリソース(日本語)
    060 *      CodeResource_jp.properties    コードリソース(日本語)
    061 *      MessageResource_jp.properties メッセージリソース(日本語)
    062 *
    063 * を用意して下さい。
    064 *
    065 * CodeResource については、リソースファイルから CodeSelectionオブジェクトを
    066 * 作成して利用します。この、CodeSelectionオブジェクトの作成方法として、
    067 * ３通り考えられます。
    068 * １つ目は、毎回 要求が発生する毎に CodeSelection を作成し、プールしていきます。こうすることで、
    069 * 初めて使用されたときだけオブジェクト化されますので、メモリの節約が可能です。ただし、
    070 * プールにヒットしなかった場合は、やはりリソースから検索しますので、元々ヒットしない
    071 * キーに対しては、毎回リソースを検索するため、非効率です。
    072 * ２つめは、元々ヒットしないキーに対して、NullCodeSelectionオブジェクトを登録しておくことで、
    073 * プールにため込んで行くと言う方法です。この場合は、シングルトーンにしてメモリを節約しますが、
    074 * それでもプール自体の容量は、確保しておく必要があります。
    075 * ３つめは、この ResourceManager がインスタンス化されるときに、すべての CodeSelectionオブジェクトを
    076 * あらかじめ プールしておく方法です。使わない CodeSelection もインスタンス化する変わりに、
    077 * キャッシュにヒットしない場合は、即 CodeSelection が存在しないと判断できるため、
    078 * もっともパフォーマンスが高くなります。
    079 * 本 ResourceManager の実装は、３つめの、あらかじめ、すべてをキャッシュしておく方法を
    080 * 採用しています。
    081 *
    082 * @og.group リソース管理
    083 *
    084 * @version  4.0
    085 * @author       Kazuhiko Hasegawa
    086 * @since    JDK5.0,
    087 */
    088public final class ResourceManager {
    089        private final ColumnDataLoader  columnLoader ;
    090        private final CodeDataLoader    codeLoader;
    091        private final LabelDataLoader   labelLoader;
    092        private final GUIDataLoader             guiLoader;
    093
    094        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。  */
    095        private final ConcurrentMap<String,DBColumn> columnPool = new ConcurrentHashMap<>( BUFFER_LARGE );
    096        private final String    lang ;
    097
    098        /**
    099         *      コンストラクター
    100         *      システムＩＤと言語コードを指定して,生成します。
    101         *
    102         * @param       systemId システムＩＤ
    103         * @param       lg 言語コード
    104         * @param       initLoad リソースデータの先読み可否(true:先読みする)
    105         */
    106        public ResourceManager( final String systemId,final String lg,final boolean initLoad ) {
    107                this.lang               = lg;
    108
    109                columnLoader    = new ColumnDataLoader( systemId,initLoad );
    110                labelLoader             = new LabelDataLoader( systemId,lang,initLoad );
    111                codeLoader              = new CodeDataLoader( systemId,initLoad,labelLoader ); // 4.0.0.0(2007/10/17)
    112                guiLoader               = new GUIDataLoader( systemId );
    113        }
    114
    115        /**
    116         * 設定されている言語を返します。
    117         *
    118         * @return      言語
    119         */
    120        public String getLang() {
    121                return lang;
    122        }
    123
    124        /**
    125         * DBColumn オブジェクトを取得します。
    126         * 作成したDBColumnオブジェクトは，内部にプールしておき，同じオブジェクト要求が
    127         * あったときは，プールのオブジェクトを利用して,DBColumnを返します。
    128         *
    129         * @og.rev 3.4.0.0 (2003/09/01) ラベルカラム、コードカラム、表示パラメータ、編集パラメータ、文字パラメータの追加。
    130         * @og.rev 3.5.6.4 (2004/07/16) 追加パラメータ取り込み時に、"_" は、null 扱いとする。
    131         * @og.rev 3.6.0.7 (2004/11/06) DBColumn の official属性追加
    132         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
    133         *
    134         * @param       key     カラムID(not null)
    135         *
    136         * @return      DBColumnオブジェクト
    137         */
    138        public DBColumn getDBColumn( final String key ) {
    139                // 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
    140                if( key == null ) {
    141                        final String errMsg = "カラムIDに、NULL は指定できません。";
    142                        throw new HybsSystemException( errMsg );
    143                }
    144
    145                DBColumn clm = columnPool.get( key );
    146                if( clm == null ) {
    147                        final ColumnData clmDt = columnLoader.getColumnData( key );
    148                        if( clmDt != null ) {
    149                                final String label_clm = clmDt.getLabelColumn();
    150                                final String code_clm  = clmDt.getCodeColumn();
    151
    152                                clm = new DBColumn(
    153                                                        lang,
    154                                                        clmDt,
    155                                                        labelLoader.getLabelData( label_clm ),
    156                                                        codeLoader.getCodeData( code_clm ) );
    157
    158                                columnPool.put( key,clm );
    159                        }
    160                }
    161                return clm;
    162        }
    163
    164        /**
    165         * DBColumn オブジェクトを作成します。
    166         * 内部にプールに存在すればそれを、なければ新規に作成します。
    167         * それでも存在しない場合は、DBColumnConfig より、ラベルと言語を指定して
    168         * 新規に作成します。
    169         *
    170         * @param       key             カラムID(not null)
    171         *
    172         * @og.rev 7.1.0.0 (2020/01/27) LabelDataを直接呼び出します。
    173         *
    174         * @return      DBColumnオブジェクト
    175         * @see         #getDBColumn( String )
    176         */
    177        public DBColumn makeDBColumn( final String key ) {
    178                DBColumn dbColumn = getDBColumn( key );
    179                if( dbColumn == null ) {
    180                        final DBColumnConfig config = new DBColumnConfig( key );
    181                        config.setLabelData( labelLoader.getLabelData( key ) );         // 7.1.0.0 (2020/01/27)
    182//                      config.setLabelData( getLabelData( key ) );
    183//                      config.setLang( getLang() );
    184                        config.setLang( lang );
    185                        dbColumn = new DBColumn( config );
    186                }
    187                return dbColumn;
    188        }
    189
    190        /**
    191         * DBColumn オブジェクトを作成します。
    192         * 内部にプールに存在すればそれを、なければ新規に作成します。
    193         * それでも存在しない場合は、DBColumnConfig より、ラベルと言語を指定して
    194         * 新規に作成します。
    195         * lbl引数が、nullか、ゼロ文字列の場合は、#makeDBColumn(String) と同じです。
    196         *
    197         * @og.rev 6.9.1.0 (2018/02/26) unionLbls追加
    198         * @og.rev 7.1.0.0 (2020/01/27) LabelDataを直接呼び出します。
    199         *
    200         * @param       key     カラムID(not null)
    201         * @param       lbl     ラベル(nullか、ゼロ文字列の場合は、設定しません)
    202         *
    203         * @return      DBColumnオブジェクト
    204         * @see         #getDBColumn( String )
    205         */
    206        public DBColumn makeDBColumn( final String key , final String lbl ) {
    207                if( lbl == null || lbl.isEmpty() ) { return makeDBColumn( key ); }
    208
    209                final DBColumn dbColumn = getDBColumn( key );
    210                final DBColumnConfig config ;
    211
    212                if( dbColumn == null ) {
    213                        config = new DBColumnConfig( key );
    214//                      config.setLang( getLang() );
    215                        config.setLang( lang );
    216                }
    217                else {
    218                        config = dbColumn.getConfig();
    219                }
    220
    221//              config.setLabelData( getLabelData( lbl ) );
    222                config.setLabelData( labelLoader.getLabelData( lbl ) );         // 7.1.0.0 (2020/01/27)
    223
    224                return new DBColumn( config );
    225        }
    226
    227//      /**
    228//       * DBColumn オブジェクトをプールに登録します。
    229//       * DBColumn を動的に作成する機能で、作成したカラムオブジェクトを
    230//       * プールに登録することで、通常のリソースと同じように利用できるように
    231//       * します。
    232//       *
    233//       * @og.rev 5.4.2.2 (2011/12/14) 新規追加
    234//       * @og.rev 7.1.0.0 (2020/01/27) Editor_ENTCLM 廃止に伴い、ﾒｿｯﾄﾞ削除
    235//       *
    236//       * @param       key  カラムID
    237//       * @param       dbColumn DBColumnオブジェクト
    238//       */
    239//      public void setDBColumn( final String key , final DBColumn dbColumn ) {
    240//              if( key != null && key.length() > 0 && dbColumn != null ) {
    241//                      columnPool.put( key,dbColumn );
    242//              }
    243//      }
    244
    245//      /**
    246//       * ラベルリソースから,ラベルを返します。
    247//       * 引数の言語コードに応じたリソースが登録されていない場合は,
    248//       * 引数のラベルキーそのまま返します。
    249//       *
    250//       * @og.rev 4.0.0.0 (2005/01/31) オラクルとWindowsとの間の "～"の文字化け対策中止
    251//       * @og.rev 4.0.0.0 (2007/10/18) メッセージリソースとの統合化
    252//       * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    253//       * @og.rev 7.0.7.0 (2019/12/13) #getLabel( String,String... ) と統合します。
    254//       *
    255//       * @param       key ラベルキー
    256//       *
    257//       * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    258//       */
    259//      public String getLabel( final String key ) {
    260//              final LabelData lblData = labelLoader.getLabelData( key );
    261//              // 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
    262//              // 反転注意
    263//              final String rtn = lblData.getLabel();
    264//
    265//              return rtn == null ? key : rtn ;                // なければ key を返す
    266//      }
    267
    268        /**
    269         * メッセージリソースから,キーで指定されたメッセージに,
    270         * 引数で指定された変数値をセットしたメッセージを返します。
    271         *
    272         * このメッセージは,リソースで選ばれたロケール毎のメッセージに，
    273         * MessageFormat#format でフォーマットする事により,作成されます。
    274         * メッセージがリソースに存在しない場合は,キーを返します。
    275         *
    276         * @og.rev 4.0.0.0 (2005/01/31) オラクルとWindowsとの間の "～"の文字化け対策
    277         * @og.rev 4.0.0.0 (2007/10/17) メッセージリソース統合に伴いラベルローダーを使用する
    278         * @og.rev 4.0.0.0 (2007/10/18) 名称変更 getMessage ⇒ getLabel
    279         * @og.rev 5.1.1.0 (2009/12/01) #XXXXの変換で、カラム名が複数指定されている場合の対応
    280         * @og.rev 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    281         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    282         * @og.rev 6.6.0.0 (2016/12/01) 引数の配列を可変長配列に変更します。
    283         * @og.rev 7.0.7.0 (2019/12/13) #getLabel( String ) と統合します。
    284         *
    285         * @param       key キー
    286         * @param       args メッセージの配列
    287         *
    288         * @return      メッセージ(無ければ キー)
    289         */
    290        public String getLabel( final String key,final String... args ) {                       // 6.6.0.0 (2016/12/01)
    291                final LabelData lblData = labelLoader.getLabelData( key );
    292
    293                final String msglbl ;
    294
    295                if( args == null || args.length == 0 ){
    296//                      msglbl = getLabel( key );
    297                        msglbl = lblData.getLabel();
    298                }
    299                else {
    300                        // 6.1.0.0 (2014/12/26) メソッド化
    301                        final String[] msgArgs = makeLabelArray( args );        // 6.1.0.0 (2014/12/26) メソッド化
    302
    303//                      // 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    304//                      final LabelData lblData = labelLoader.getLabelData( key );
    305                        // 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    306                        msglbl = lblData.getMessage( msgArgs );
    307                }
    308
    309//              return msglbl;
    310                return msglbl == null ? key : msglbl ;          // なければ key を返す
    311        }
    312
    313        /**
    314         * ラベルリソースから,ラベルを返します。
    315         * ただし、キーに、「スペース＋%＋記号」を判定、処理する機能を用意します。
    316         *
    317         * 記号は、Label,Short,Tips,Description,RawShortLabel,CodeData の頭文字一つ目です。
    318         * ('L','S','T','D','R','C') となります。
    319         * 'L' は通常のﾗﾍﾞﾙと同じ。'C' は、'S'(Short)と同じになります。
    320         *
    321         * 「スペース＋%＋記号」が無ければ、通常のラベルと同じ処理を行います。
    322         * つまり、このメソッドは、getLabel(String) より、ほんの少し処理時間を稼ぐために用意しました。
    323         * なので、一応、内部からしか呼ばない事とし、private にしておきます。
    324         *
    325         * @og.rev 6.3.8.4 (2015/10/09) XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    326         * @og.rev 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
    327         *
    328         * @param       key ラベルキー
    329         *
    330         * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    331         */
    332        private String getExtLabel( final String key ) {
    333                final String val ;
    334
    335                final int ad = key.indexOf( " %" );
    336                if( ad < 0 ) {
    337                        val = getLabel( key );
    338                }
    339                else if( ad+2 <= key.length() ) {               // " %" の後ろの文字が存在しない場合
    340                        val = getLabel( key.substring( 0,ad ) );
    341                }
    342                else {
    343                        final String tmpKey = key.substring( 0,ad );
    344                        // 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
    345                        switch( key.charAt( ad+2 ) ) {
    346                                case 'L': val = getLabel(         tmpKey );     break;
    347                                case 'S':
    348                                case 'C': val = getShortLabel(    tmpKey );     break;  // 6.3.9.0 (2015/11/06) findbugs対応
    349                                case 'T': val = getLongLabel(     tmpKey );     break;
    350                                case 'D': val = getDescription(   tmpKey );     break;
    351                                case 'R': val = getRawShortLabel( tmpKey );     break;
    352                                default : val = getLabel(         tmpKey );     break;
    353                        }
    354                }
    355                return val;
    356        }
    357
    358        /**
    359         * ラベルリソースの引数で、#XXXXの変換で、カラム名が複数指定されている場合の対応を行います。
    360         *
    361         * 一つの引数に、#CLM,LANG,KBSAKU 等の項目名が複数指定指定された場合に、
    362         * それぞれを解析してラベルに戻します。
    363         * 該当するラベルが存在しない場合は、そのままの値を返します。
    364         * 返される文字列配列は、元の引数とは異なる新しい文字列配列で返されます。
    365         *
    366         * @og.rev 6.1.0.0 (2014/12/26) #XXXXの変換で、カラム名が複数指定されている場合の対応
    367         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    368         * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. Java8 ラムダ式を使用して、大幅書き直し。
    369         * @og.rev 7.0.4.2 (2019/06/17) # のみの場合は、特別に、# を返すように対応。
    370         *
    371         * @param       args メッセージの配列
    372         *
    373         * @return      ラベル置換後の新しい文字列配列
    374         */
    375        private String[] makeLabelArray( final String[] args ) {
    376                final int size = args.length;
    377                final String[] msgArgs = new String[size];
    378
    379                for( int i=0; i<size; i++ ) {
    380                        final String arg = args[i] ;
    381//                      if( StringUtil.startsChar( arg , '#' ) ) {
    382                        if( StringUtil.startsChar( arg , '#' ) && arg.length() > 1 ) {                                  // 7.0.4.2 (2019/06/17)
    383                                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid instantiating new objects inside loops
    384                                msgArgs[i] = Stream.of( StringUtil.csv2Array( arg.substring( 1 ) ) )
    385                                                                .map( lbl -> getExtLabel( lbl ) )
    386                                                                .collect( Collectors.joining( "," ) );
    387                        }
    388                        else {
    389                                msgArgs[i] = arg ;
    390                        }
    391                }
    392                return msgArgs ;
    393        }
    394
    395        /**
    396         * ラベルリソースから,ラベル(短)を返します。
    397         * 引数の言語コードに応じたリソースが登録されていない場合は,
    398         * 引数のラベルキーそのまま返します。
    399         *
    400         * @og.rev 4.3.3.0 (2008/10/01) 新規作成
    401         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    402         *
    403         * @param       key ラベルキー
    404         *
    405         * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    406         */
    407        public String getShortLabel( final String key ) {
    408                final LabelData lblData = labelLoader.getLabelData( key );
    409                // 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
    410                // 反転注意
    411                final String rtn = lblData.getShortLabel();
    412
    413                return rtn == null ? key : rtn ;                // なければ key を返す
    414        }
    415
    416        /**
    417         * ラベルリソースから,ラベル(長)を返します。
    418         * 概要説明が存在する場合は、ツールチップに概要説明が
    419         * 表示されます。
    420         * 引数の言語コードに応じたリソースが登録されていない場合は,
    421         * 引数のラベルキーそのまま返します。
    422         *
    423         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    424         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    425         *
    426         * @param       key ラベルキー
    427         *
    428         * @return      リソースに応じたラベル(長)文字列(無ければ ラベルキー)
    429         */
    430        public String getLongLabel( final String key ) {
    431                final LabelData lblData = labelLoader.getLabelData( key );
    432                // 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
    433                // 反転注意
    434                final String rtn = lblData.getLongLabel();
    435
    436                return rtn == null ? key : rtn ;                // なければ key を返す
    437        }
    438
    439        /**
    440         * ラベルオブジェクトの名称(短)をspanタグを付けない状態で返します。
    441         * SNAMEが未設定の場合は、LNAME が返されます。
    442         * 引数の言語コードに応じたリソースが登録されていない場合は,
    443         * 引数のラベルキーそのまま返します。
    444         *
    445         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    446         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    447         * @og.rev 7.0.7.0 (2019/12/13) args パラメータ配列(可変長引数)を追加します。
    448         *
    449         * @param       key ラベルキー
    450         * @param       args パラメータ配列(可変長引数)
    451         *
    452         * @return      リソースに応じたラベル(長)文字列(無ければ ラベルキー)
    453         */
    454        public String getRawShortLabel( final String key,final String... args ) {
    455                final LabelData lblData = labelLoader.getLabelData( key );
    456
    457                final String msglbl ;
    458                if( args == null || args.length == 0 ){
    459                        msglbl = lblData.getRawShortLabel();
    460                }
    461                else {
    462                        // 6.1.0.0 (2014/12/26) メソッド化
    463                        final String[] msgArgs = makeLabelArray( args );        // 6.1.0.0 (2014/12/26) メソッド化
    464
    465                        // 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    466                        msglbl = lblData.getShortMessage( msgArgs );
    467                }
    468
    469                return msglbl == null ? key : msglbl ;          // なければ key を返す
    470        }
    471//      public String getRawShortLabel( final String key ) {
    472//              final LabelData lblData = labelLoader.getLabelData( key );
    473//              // 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
    474//              // 反転注意
    475//              final String rtn = lblData.getRawShortLabel();
    476//
    477//              return rtn == null ? key : rtn ;                // なければ key を返す
    478//      }
    479
    480//      /**
    481//       * ラベルリソースから,概要説明を返します。
    482//       * キーのデータが存在しない場合はnullを返します。
    483//       *
    484//       * @og.rev 4.3.4.5 (2009/01/08) 新規作成
    485//       * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    486//       * @og.rev 7.0.7.0 (2019/12/13) #getDescription( String ) と統合します。
    487//       *
    488//       * @param       key ラベルキー
    489//       *
    490//       * @return      リソースに応じた概要説明(無ければ null)
    491//       */
    492//      public String getDescription( final String key ) {
    493//              final LabelData lblData = labelLoader.getLabelData( key );
    494//
    495//              // 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
    496//              return lblData.getDescription();        // キーが存在しなければnullで返す
    497//      }
    498
    499        /**
    500         * ラベルリソースから,概要説明を返します。
    501         * {0},{1}...の置換えを行います。
    502         * キーのデータが存在しない場合はnullを返します。
    503         * ただし、パラメータのデータがあれば、それを返します。
    504         *
    505         * @og.rev 4.3.7.6 (2009/07/15) 新規作成
    506         * @og.rev 6.1.0.0 (2014/12/26) #XXXXの変換で、カラム名が複数指定されている場合の対応
    507         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    508         * @og.rev 7.0.7.0 (2019/12/13) #getDescription( String ) と統合します。
    509         *
    510         * @param       key ラベルキー
    511         * @param       args パラメータ配列(可変長引数)
    512         *
    513         * @return      リソースに応じた概要説明(無ければ null)
    514         */
    515//      public String getDescription( final String key, final String[] args ) {
    516        public String getDescription( final String key,final String... args ) {                 // 6.6.0.0 (2016/12/01)
    517                final LabelData lblData = labelLoader.getLabelData( key );
    518
    519                final String msgdesc ;
    520                if( args == null || args.length == 0 ){
    521//                      msgdesc = getDescription( key );
    522                        msgdesc = lblData.getDescription();
    523                }
    524                else {
    525                        // 6.1.0.0 (2014/12/26) getLabel( String ,String[] ) と同様に複数ラベル対応
    526                        final String[] msgArgs = makeLabelArray( args );
    527
    528//                      // 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    529//                      final LabelData lblData = labelLoader.getLabelData( key );
    530                        msgdesc = lblData.getDescription( msgArgs );
    531                }
    532
    533//              return msgdesc ;
    534                return msgdesc == null ? key : msgdesc ;                // なければ key を返す
    535        }
    536
    537        /**
    538         * メッセージリソースから,ErrMsgオブジェクトで指定されたメッセージを返します。
    539         *
    540         * このエラーメッセージは,リソースで選ばれたロケール毎のメッセージに，
    541         * MessageFormat#format でフォーマットする事により,作成されます。
    542         * エラーメッセージがリソースに存在しない場合は,エラーコードを返します。
    543         *
    544         * @og.rev 4.0.0.0 (2004/12/31) 新規追加
    545         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソースとの統合化
    546         *
    547         * @param       errMsgObj ErrMsgオブジェクト
    548         *
    549         * @return      エラーメッセージ(無ければ ErrMsgオブジェクトの toString() )
    550         */
    551        public String getLabel( final ErrMsg errMsgObj ) {
    552                return getLabel( errMsgObj.getId(),errMsgObj.getArgs() );
    553        }
    554
    555        /**
    556         * メッセージリソースから,ErrMsgオブジェクトで指定されたショートメッセージを返します。
    557         *
    558         * このエラーメッセージは,リソースで選ばれたロケール毎のメッセージに，
    559         * MessageFormat#format でフォーマットする事により,作成されます。
    560         * エラーメッセージがリソースに存在しない場合は,エラーコードを返します。
    561         *
    562         * @og.rev 7.0.7.0 (2019/12/13) 新規追加
    563         *
    564         * @param       errMsgObj ErrMsgオブジェクト
    565         *
    566         * @return      エラーメッセージ(無ければ ErrMsgオブジェクトの toString() )
    567         */
    568        public String getRawShortLabel( final ErrMsg errMsgObj ) {
    569                return getRawShortLabel( errMsgObj.getId(),errMsgObj.getArgs() );
    570        }
    571
    572        /**
    573         * ErrMsgオブジェクトの内容を元に、ラベルリソースから,概要説明を返します。
    574         * キーのデータが存在しない場合はnullを返します。
    575         *
    576         * @og.rev 4.3.7.6 (2009/07/15) 新規作成
    577         *
    578         * @param       errMsgObj ErrMsgオブジェクト
    579         *
    580         * @return      エラーメッセージ(キーが無ければnull)
    581         */
    582        public String getDescription( final ErrMsg errMsgObj ) {
    583                return getDescription( errMsgObj.getId(),errMsgObj.getArgs() );
    584        }
    585
    586        /**
    587         * ラベルキーに対応する、LabelDataオブジェクトを返します。
    588         *
    589         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
    590         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    591         *
    592         * @param       key ラベルキー
    593         *
    594         * @return      LabelDataオブジェクト
    595         * @og.rtnNotNull
    596         */
    597        public LabelData getLabelData( final String key ) {
    598                return labelLoader.getLabelData( key );
    599        }
    600
    601        /**
    602         * コードキーに対応する、CodeDataオブジェクトを返します。
    603         *
    604         * @param       key コードキー
    605         *
    606         * @return      CodeDataオブジェクト(無ければ null)
    607         */
    608        public CodeData getCodeData( final String key ) {
    609                return codeLoader.getCodeData( key );
    610        }
    611
    612        /**
    613         * コードリソースから,コード文字列を返します。
    614         * 引数にQUERYを渡すことで、DBから、動的にコードリソースを作成できます。
    615         *
    616         * @og.rev 5.4.2.2 (2011/12/14) 新規追加。
    617         *
    618         * @param       key コードキー
    619         * @param       query 検索SQL(引数に、? を一つ持つ)
    620         *
    621         * @return      コードデータオブジェクト(無ければ null)
    622         */
    623        public CodeData getCodeData( final String key,final String query ) {
    624                return codeLoader.getCodeData( key,query );
    625        }
    626
    627        /**
    628         * ログインユーザーで使用する画面オブジェクトを、UserInfoにセットします。
    629         * 各、UserInfo は、自分自身が使用する 画面オブジェクトのみを管理することで、
    630         * 画面アクセス有無を、すばやく検索することが可能になります。
    631         *
    632         * @og.rev 3.1.0.1 (2003/03/26) GUIInfo のキー順サポートの為に、引数追加。
    633         * @og.rev 4.0.0.0 (2005/01/31) 使用画面のMap を UserInfo にセットします。
    634         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
    635         * @og.rev 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加
    636         * @og.rev 6.4.3.4 (2016/03/11) forループを、removeAll メソッドに置き換えます。
    637         * @og.rev 6.4.4.2 (2016/04/01) guiMap.values() では、GUIInfo だが、remove するのは、gui.getAddress() の値。
    638         * @og.rev 7.1.0.0 (2020/01/27) LabelDataを直接呼び出します。
    639         *
    640         * @param       user    指定のユーザーロールに対応する画面だけをMapにセットする。
    641         */
    642        public void makeGUIInfos( final UserInfo user ) {
    643                final GUIData[] guiDatas = guiLoader.getAllData();
    644
    645                // guikey に対してユニークになるように Map に追加します。後登録が優先されます。
    646                final Map<String,GUIInfo> guiMap = new HashMap<>();
    647                final Set<String> forbidAddrSet  = new HashSet<>();
    648                int size = guiDatas.length;
    649                for( int i=0; i<size; i++ ) {
    650                        final GUIData gui = guiDatas[i];
    651                        final byte bitMode = user.getAccessBitMode( gui.getRoleMode() );
    652                        if(  bitMode > 0 ) {
    653                                final String      guikey        = gui.getGuiKey();
    654//                              final LabelData labelData       = getLabelData( gui.getLabelClm() );
    655                                final LabelData labelData       = labelLoader.getLabelData( gui.getLabelClm() );        // 7.1.0.0 (2020/01/27)
    656                                guiMap.put( guikey,new GUIInfo( gui,labelData,bitMode ) );
    657                        }
    658                        // 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加
    659                        else {
    660                                final String addr = gui.getAddress();
    661                                if( addr.indexOf( '/' ) < 0 ) {
    662                                        forbidAddrSet.add( addr );
    663                                }
    664                        }
    665                }
    666
    667                // もし、禁止リストの中に画面ID違いで許可リストと同じアドレスが
    668                // 含まれている場合は、禁止リスト中から該当のアドレスを削除する。
    669                // 6.4.3.4 (2016/03/11) forループを、removeAll メソッドに置き換えます。
    670                // 6.4.4.2 (2016/04/01) guiMap.values() では、GUIInfo だが、remove するのは、gui.getAddress() の値。
    671                guiMap.forEach( (id,gui) -> forbidAddrSet.remove( gui.getAddress() ) );
    672
    673                // GUIInfo をその順番(SEQNO順)でソートし直します。SYSTEM_ID や、KBSAKU の影響を排除します。
    674                final GUIInfo[] guiInfos = guiMap.values().toArray( new GUIInfo[ guiMap.size() ] ) ;
    675                Arrays.sort( guiInfos );
    676                final Map<String,GUIInfo> sortMap = new LinkedHashMap<>();
    677                size = guiInfos.length;
    678                for( int i=0; i<size; i++ ) {
    679                        final GUIInfo guiInfo = guiInfos[i];
    680                        final String guikey     = guiInfo.getKey();
    681                        sortMap.put( guikey,guiInfo );
    682                }
    683
    684                user.setGUIMap( sortMap, forbidAddrSet );
    685        }
    686
    687        /**
    688         * 指定されたクエリを発行し、ラベルマップを作成します。
    689         *
    690         * @og.rev 4.3.4.0 (2008/12/01) 新規作成
    691         * @og.rev 6.4.0.5 (2016/01/09) useLabelMap="true" 時のSQL文の実行は、dbid を使用して行う。
    692         *
    693         * @param       query   ラベルマップを作成するクエリ
    694         * @param       dbid    接続先ID
    695         *
    696         * @return      ラベルマップ
    697         * @see org.opengion.hayabusa.resource.LabelDataLoader#getLabelMap( String,String )
    698         */
    699        public Map<String, LabelData> getLabelMap( final String query , final String dbid ) {
    700                return labelLoader.getLabelMap( query , dbid );
    701        }
    702
    703        /**
    704         * リソースマネージャーをキーに基づいて部分クリアします。
    705         * ここでは、部分クリアなため、GUIData に関しては、処理されません。
    706         * また、存在しないキーを指定されたリソースは、何も処理されません。
    707         *
    708         * @og.rev 5.4.3.4 (2012/01/12) labelPool の削除追加
    709         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
    710         * @og.rev 6.9.0.1 (2018/02/05) どのシステムIDのﾘｿｰｽがクリアされたかを表示します。
    711         *
    712         * @param   key         カラムのキー
    713         */
    714        public void clear( final String key ) {
    715                // 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限
    716                if( key != null ) {
    717//                      System.out.println( "Key=[" + key + "] の部分リソースクリアを実施しました。" );   // 6.9.0.1 (2018/02/05) columnLoader へ移動
    718                        columnLoader.clear( key );
    719                        codeLoader.clear( key );
    720                        labelLoader.clear( key );
    721                        columnPool.remove( key );
    722                }
    723        }
    724
    725        /**
    726         * GUI情報をクリアします。
    727         * ここでは、関連するラベル、コードリソースの部分クリアも行います。
    728         * GUI情報は、シーケンスに管理しているため、この処理１回ごとに、
    729         * GUIData を全件再読み込みを行いますので、ご注意ください。
    730         *
    731         */
    732        public void guiClear() {
    733                final GUIData[] gui = guiLoader.getAllData();
    734
    735                for( int i=0; i<gui.length; i++ ) {
    736                        final String key = gui[i].getGuiKey();
    737                        labelLoader.clear( key );
    738                }
    739                codeLoader.clear( "CLASSIFY" );
    740                guiLoader.clear();
    741        }
    742
    743        /**
    744         * リソースマネージャーをクリア(初期化)します。
    745         *
    746         * @og.rev 5.4.3.4 (2012/01/12) labelPool の削除追加
    747         *
    748         */
    749        public void clear() {
    750                columnLoader.clear();
    751                codeLoader.clear();
    752                labelLoader.clear();
    753                guiLoader.clear();
    754                columnPool.clear();
    755        }
    756}