    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         * @return      DBColumnオブジェクト
    173         * @see         #getDBColumn( String )
    174         */
    175        public DBColumn makeDBColumn( final String key ) {
    176                DBColumn dbColumn = getDBColumn( key );
    177                if( dbColumn == null ) {
    178                        final DBColumnConfig config = new DBColumnConfig( key );
    179                        config.setLabelData( getLabelData( key ) );
    180                        config.setLang( getLang() );
    181                        dbColumn = new DBColumn( config );
    182                }
    183                return dbColumn;
    184        }
    185
    186        /**
    187         * DBColumn オブジェクトを作成します。
    188         * 内部にプールに存在すればそれを、なければ新規に作成します。
    189         * それでも存在しない場合は、DBColumnConfig より、ラベルと言語を指定して
    190         * 新規に作成します。
    191         * lbl引数が、nullか、ゼロ文字列の場合は、#makeDBColumn(String) と同じです。
    192         *
    193         * @og.rev 6.9.1.0 (2018/02/26) unionLbls追加
    194         *
    195         * @param       key     カラムID(not null)
    196         * @param       lbl     ラベル(nullか、ゼロ文字列の場合は、設定しません)
    197         *
    198         * @return      DBColumnオブジェクト
    199         * @see         #getDBColumn( String )
    200         */
    201        public DBColumn makeDBColumn( final String key , final String lbl ) {
    202                if( lbl == null || lbl.isEmpty() ) { return makeDBColumn( key ); }
    203
    204                final DBColumn dbColumn = getDBColumn( key );
    205                final DBColumnConfig config ;
    206
    207                if( dbColumn == null ) {
    208                        config = new DBColumnConfig( key );
    209                        config.setLang( getLang() );
    210                }
    211                else {
    212                        config = dbColumn.getConfig();
    213                }
    214
    215                config.setLabelData( getLabelData( lbl ) );
    216
    217                return new DBColumn( config );
    218        }
    219
    220        /**
    221         * DBColumn オブジェクトをプールに登録します。
    222         * DBColumn を動的に作成する機能で、作成したカラムオブジェクトを
    223         * プールに登録することで、通常のリソースと同じように利用できるように
    224         * します。
    225         *
    226         * @og.rev 5.4.2.2 (2011/12/14) 新規追加
    227         *
    228         * @param       key  カラムID
    229         * @param       dbColumn DBColumnオブジェクト
    230         */
    231        public void setDBColumn( final String key , final DBColumn dbColumn ) {
    232                if( key != null && key.length() > 0 && dbColumn != null ) {
    233                        columnPool.put( key,dbColumn );
    234                }
    235        }
    236
    237        /**
    238         * ラベルリソースから,ラベルを返します。
    239         * 引数の言語コードに応じたリソースが登録されていない場合は,
    240         * 引数のラベルキーそのまま返します。
    241         *
    242         * @og.rev 4.0.0.0 (2005/01/31) オラクルとWindowsとの間の "～"の文字化け対策中止
    243         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソースとの統合化
    244         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    245         *
    246         * @param       key ラベルキー
    247         *
    248         * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    249         */
    250        public String getLabel( final String key ) {
    251                final LabelData lblData = labelLoader.getLabelData( key );
    252                // 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
    253                // 反転注意
    254                final String rtn = lblData.getLabel();
    255                return rtn == null ? key : rtn ;                // なければ key を返す
    256
    257        }
    258
    259        /**
    260         * メッセージリソースから,キーで指定されたメッセージに,
    261         * 引数で指定された変数値をセットしたメッセージを返します。
    262         *
    263         * このメッセージは,リソースで選ばれたロケール毎のメッセージに，
    264         * MessageFormat#format でフォーマットする事により,作成されます。
    265         * メッセージがリソースに存在しない場合は,キーを返します。
    266         *
    267         * @og.rev 4.0.0.0 (2005/01/31) オラクルとWindowsとの間の "～"の文字化け対策
    268         * @og.rev 4.0.0.0 (2007/10/17) メッセージリソース統合に伴いラベルローダーを使用する
    269         * @og.rev 4.0.0.0 (2007/10/18) 名称変更 getMessage ⇒ getLabel
    270         * @og.rev 5.1.1.0 (2009/12/01) #XXXXの変換で、カラム名が複数指定されている場合の対応
    271         * @og.rev 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    272         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    273         * @og.rev 6.6.0.0 (2016/12/01) 引数の配列を可変長配列に変更します。
    274         *
    275         * @param       key キー
    276         * @param       args メッセージの配列
    277         *
    278         * @return      メッセージ(無ければ キー)
    279         */
    280        public String getLabel( final String key,final String... args ) {                       // 6.6.0.0 (2016/12/01)
    281                final String msglbl ;
    282
    283                if( args == null || args.length == 0 ){
    284                        msglbl = getLabel( key );
    285                }
    286                else {
    287                        // 6.1.0.0 (2014/12/26) メソッド化
    288                        final String[] msgArgs = makeLabelArray( args );        // 6.1.0.0 (2014/12/26) メソッド化
    289
    290                        // 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    291                        final LabelData lblData = labelLoader.getLabelData( key );
    292                        // 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    293                                msglbl = lblData.getMessage( msgArgs );
    294                }
    295
    296                return msglbl;
    297        }
    298
    299        /**
    300         * ラベルリソースから,ラベルを返します。
    301         * ただし、キーに、「スペース＋%＋記号」を判定、処理する機能を用意します。
    302         *
    303         * 記号は、Label,Short,Tips,Description,RawShortLabel,CodeData の頭文字一つ目です。
    304         * ('L','S','T','D','R','C') となります。
    305         * 'L' は通常のﾗﾍﾞﾙと同じ。'C' は、'S'(Short)と同じになります。
    306         *
    307         * 「スペース＋%＋記号」が無ければ、通常のラベルと同じ処理を行います。
    308         * つまり、このメソッドは、getLabel(String) より、ほんの少し処理時間を稼ぐために用意しました。
    309         * なので、一応、内部からしか呼ばない事とし、private にしておきます。
    310         *
    311         * @og.rev 6.3.8.4 (2015/10/09) XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    312         * @og.rev 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
    313         *
    314         * @param       key ラベルキー
    315         *
    316         * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    317         */
    318        private String getExtLabel( final String key ) {
    319                final String val ;
    320
    321                final int ad = key.indexOf( " %" );
    322                if( ad < 0 ) {
    323                        val = getLabel( key );
    324                }
    325                else if( ad+2 <= key.length() ) {               // " %" の後ろの文字が存在しない場合
    326                        val = getLabel( key.substring( 0,ad ) );
    327                }
    328                else {
    329                        final String tmpKey = key.substring( 0,ad );
    330                        // 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
    331                        switch( key.charAt( ad+2 ) ) {
    332                                case 'L': val = getLabel(         tmpKey );     break;
    333                                case 'S':
    334                                case 'C': val = getShortLabel(    tmpKey );     break;  // 6.3.9.0 (2015/11/06) findbugs対応
    335                                case 'T': val = getLongLabel(     tmpKey );     break;
    336                                case 'D': val = getDescription(   tmpKey );     break;
    337                                case 'R': val = getRawShortLabel( tmpKey );     break;
    338                                default : val = getLabel(         tmpKey );     break;
    339                        }
    340                }
    341                return val;
    342        }
    343
    344        /**
    345         * ラベルリソースの引数で、#XXXXの変換で、カラム名が複数指定されている場合の対応を行います。
    346         *
    347         * 一つの引数に、#CLM,LANG,KBSAKU 等の項目名が複数指定指定された場合に、
    348         * それぞれを解析してラベルに戻します。
    349         * 該当するラベルが存在しない場合は、そのままの値を返します。
    350         * 返される文字列配列は、元の引数とは異なる新しい文字列配列で返されます。
    351         *
    352         * @og.rev 6.1.0.0 (2014/12/26) #XXXXの変換で、カラム名が複数指定されている場合の対応
    353         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    354         * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. Java8 ラムダ式を使用して、大幅書き直し。
    355         *
    356         * @param       args メッセージの配列
    357         *
    358         * @return      ラベル置換後の新しい文字列配列
    359         */
    360        private String[] makeLabelArray( final String[] args ) {
    361                final int size = args.length;
    362                final String[] msgArgs = new String[size];
    363
    364                for( int i=0; i<size; i++ ) {
    365                        final String arg = args[i] ;
    366                        if( StringUtil.startsChar( arg , '#' ) ) {
    367                                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid instantiating new objects inside loops
    368                                msgArgs[i] = Stream.of( StringUtil.csv2Array( arg.substring( 1 ) ) )
    369                                                                .map( lbl -> getExtLabel( lbl ) )
    370                                                                .collect( Collectors.joining( "," ) );
    371
    372                        }
    373                        else {
    374                                msgArgs[i] = arg ;
    375                        }
    376                }
    377                return msgArgs ;
    378        }
    379
    380        /**
    381         * メッセージリソースから,ErrMsgオブジェクトで指定されたメッセージを返します。
    382         *
    383         * このエラーメッセージは,リソースで選ばれたロケール毎のメッセージに，
    384         * MessageFormat#format でフォーマットする事により,作成されます。
    385         * エラーメッセージがリソースに存在しない場合は,エラーコードを返します。
    386         *
    387         * @og.rev 4.0.0.0 (2004/12/31) 新規追加
    388         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソースとの統合化
    389         *
    390         * @param       errMsgObj ErrMsgオブジェクト
    391         *
    392         * @return      エラーメッセージ(無ければ ErrMsgオブジェクトの toString() )
    393         */
    394        public String getLabel( final ErrMsg errMsgObj ) {
    395                return getLabel( errMsgObj.getId(),errMsgObj.getArgs() );
    396        }
    397
    398        /**
    399         * ラベルリソースから,ラベル(短)を返します。
    400         * 引数の言語コードに応じたリソースが登録されていない場合は,
    401         * 引数のラベルキーそのまま返します。
    402         *
    403         * @og.rev 4.3.3.0 (2008/10/01) 新規作成
    404         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    405         *
    406         * @param       key ラベルキー
    407         *
    408         * @return      リソースに応じたラベル文字列(無ければ ラベルキー)
    409         */
    410        public String getShortLabel( final String key ) {
    411                final LabelData lblData = labelLoader.getLabelData( key );
    412                // 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
    413                // 反転注意
    414                final String rtn = lblData.getShortLabel();
    415                return rtn == null ? key : rtn ;                // なければ key を返す
    416
    417        }
    418
    419        /**
    420         * ラベルリソースから,ラベル(長)を返します。
    421         * 概要説明が存在する場合は、ツールチップに概要説明が
    422         * 表示されます。
    423         * 引数の言語コードに応じたリソースが登録されていない場合は,
    424         * 引数のラベルキーそのまま返します。
    425         *
    426         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    427         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    428         *
    429         * @param       key ラベルキー
    430         *
    431         * @return      リソースに応じたラベル(長)文字列(無ければ ラベルキー)
    432         */
    433        public String getLongLabel( final String key ) {
    434                final LabelData lblData = labelLoader.getLabelData( key );
    435                // 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
    436                // 反転注意
    437                final String rtn = lblData.getLongLabel();
    438                return rtn == null ? key : rtn ;                // なければ key を返す
    439
    440        }
    441
    442        /**
    443         * ラベルオブジェクトの名称(短)をspanタグを付けない状態で返します。
    444         * SNAMEが未設定の場合は、LNAME が返されます。
    445         * 引数の言語コードに応じたリソースが登録されていない場合は,
    446         * 引数のラベルキーそのまま返します。
    447         *
    448         * @og.rev 6.3.8.4 (2015/10/09) #XXXX %S などの対応。getLabel(String) は汎用過ぎるので、少し分ける。
    449         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    450         *
    451         * @param       key ラベルキー
    452         *
    453         * @return      リソースに応じたラベル(長)文字列(無ければ ラベルキー)
    454         */
    455        public String getRawShortLabel( final String key ) {
    456                final LabelData lblData = labelLoader.getLabelData( key );
    457                // 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
    458                // 反転注意
    459                final String rtn = lblData.getRawShortLabel();
    460                return rtn == null ? key : rtn ;                // なければ key を返す
    461
    462        }
    463
    464        /**
    465         * ラベルリソースから,概要説明を返します。
    466         * キーのデータが存在しない場合はnullを返します。
    467         *
    468         * @og.rev 4.3.4.5 (2009/01/08) 新規作成
    469         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    470         *
    471         * @param       key ラベルキー
    472         *
    473         * @return      リソースに応じた概要説明(無ければ null)
    474         */
    475        public String getDescription( final String key ) {
    476                final LabelData lblData = labelLoader.getLabelData( key );
    477
    478                // 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
    479                return lblData.getDescription();        // キーが存在しなければnullで返す
    480
    481        }
    482
    483        /**
    484         * ラベルリソースから,概要説明を返します。
    485         * {0},{1}...の置換えを行います。
    486         * キーのデータが存在しない場合はnullを返します。
    487         * ただし、パラメータのデータがあれば、それを返します。
    488         *
    489         * @og.rev 4.3.7.6 (2009/07/15) 新規作成
    490         * @og.rev 6.1.0.0 (2014/12/26) #XXXXの変換で、カラム名が複数指定されている場合の対応
    491         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    492         *
    493         * @param       key ラベルキー
    494         * @param       args パラメータ配列(可変長引数)
    495         *
    496         * @return      リソースに応じた概要説明(無ければ null)
    497         */
    498        public String getDescription( final String key, final String[] args ) {
    499                final String msgdesc ;
    500                if( args == null || args.length == 0 ){
    501                        msgdesc = getDescription( key );
    502                }
    503                else {
    504                        // 6.1.0.0 (2014/12/26) getLabel( String ,String[] ) と同様に複数ラベル対応
    505                        final String[] msgArgs = makeLabelArray( args );
    506
    507                        // 6.1.0.0 (2014/12/26) LabelData が存在しなかった場合の処理
    508                        final LabelData lblData = labelLoader.getLabelData( key );
    509                                msgdesc = lblData.getDescription( msgArgs );
    510                }
    511                return msgdesc ;
    512
    513        }
    514
    515        /**
    516         * ErrMsgオブジェクトの内容を元に、ラベルリソースから,概要説明を返します。
    517         * キーのデータが存在しない場合はnullを返します。
    518         *
    519         * @og.rev 4.3.7.6 (2009/07/15) 新規作成
    520         *
    521         * @param       errMsgObj ErrMsgオブジェクト
    522         *
    523         * @return      エラーメッセージ(キーが無ければnull)
    524         */
    525        public String getDescription( final ErrMsg errMsgObj ) {
    526                return getDescription( errMsgObj.getId(),errMsgObj.getArgs() );
    527        }
    528
    529        /**
    530         * ラベルキーに対応する、LabelDataオブジェクトを返します。
    531         *
    532         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
    533         * @og.rev 6.3.9.0 (2015/11/06) labelLoader.getLabelDataは、nullを返しません。
    534         *
    535         * @param       key ラベルキー
    536         *
    537         * @return      LabelDataオブジェクト
    538         * @og.rtnNotNull
    539         */
    540        public LabelData getLabelData( final String key ) {
    541                return labelLoader.getLabelData( key );
    542        }
    543
    544        /**
    545         * コードキーに対応する、CodeDataオブジェクトを返します。
    546         *
    547         * @param       key コードキー
    548         *
    549         * @return      CodeDataオブジェクト(無ければ null)
    550         */
    551        public CodeData getCodeData( final String key ) {
    552                return codeLoader.getCodeData( key );
    553        }
    554
    555        /**
    556         * コードリソースから,コード文字列を返します。
    557         * 引数にQUERYを渡すことで、DBから、動的にコードリソースを作成できます。
    558         *
    559         * @og.rev 5.4.2.2 (2011/12/14) 新規追加。
    560         *
    561         * @param       key コードキー
    562         * @param       query 検索SQL(引数に、? を一つ持つ)
    563         *
    564         * @return      コードデータオブジェクト(無ければ null)
    565         */
    566        public CodeData getCodeData( final String key,final String query ) {
    567                return codeLoader.getCodeData( key,query );
    568        }
    569
    570        /**
    571         * ログインユーザーで使用する画面オブジェクトを、UserInfoにセットします。
    572         * 各、UserInfo は、自分自身が使用する 画面オブジェクトのみを管理することで、
    573         * 画面アクセス有無を、すばやく検索することが可能になります。
    574         *
    575         * @og.rev 3.1.0.1 (2003/03/26) GUIInfo のキー順サポートの為に、引数追加。
    576         * @og.rev 4.0.0.0 (2005/01/31) 使用画面のMap を UserInfo にセットします。
    577         * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
    578         * @og.rev 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加
    579         * @og.rev 6.4.3.4 (2016/03/11) forループを、removeAll メソッドに置き換えます。
    580         * @og.rev 6.4.4.2 (2016/04/01) guiMap.values() では、GUIInfo だが、remove するのは、gui.getAddress() の値。
    581         *
    582         * @param       user    指定のユーザーロールに対応する画面だけをMapにセットする。
    583         */
    584        public void makeGUIInfos( final UserInfo user ) {
    585                final GUIData[] guiDatas = guiLoader.getAllData();
    586
    587                // guikey に対してユニークになるように Map に追加します。後登録が優先されます。
    588                final Map<String,GUIInfo> guiMap = new HashMap<>();
    589                final Set<String> forbidAddrSet  = new HashSet<>();
    590                int size = guiDatas.length;
    591                for( int i=0; i<size; i++ ) {
    592                        final GUIData gui = guiDatas[i];
    593                        final byte bitMode = user.getAccessBitMode( gui.getRoleMode() );
    594                        if(  bitMode > 0 ) {
    595                                final String      guikey        = gui.getGuiKey();
    596                                final LabelData labelData = getLabelData( gui.getLabelClm() );
    597                                guiMap.put( guikey,new GUIInfo( gui,labelData,bitMode ) );
    598                        }
    599                        // 5.2.0.0 (2010/09/01) アクセス禁止アドレスによる不正アクセス防止機能追加
    600                        else {
    601                                final String addr = gui.getAddress();
    602                                if( addr.indexOf( '/' ) < 0 ) {
    603                                        forbidAddrSet.add( addr );
    604                                }
    605                        }
    606                }
    607
    608                // もし、禁止リストの中に画面ID違いで許可リストと同じアドレスが
    609                // 含まれている場合は、禁止リスト中から該当のアドレスを削除する。
    610                // 6.4.3.4 (2016/03/11) forループを、removeAll メソッドに置き換えます。
    611                // 6.4.4.2 (2016/04/01) guiMap.values() では、GUIInfo だが、remove するのは、gui.getAddress() の値。
    612                guiMap.forEach( (id,gui) -> forbidAddrSet.remove( gui.getAddress() ) );
    613
    614                // GUIInfo をその順番(SEQNO順)でソートし直します。SYSTEM_ID や、KBSAKU の影響を排除します。
    615                final GUIInfo[] guiInfos = guiMap.values().toArray( new GUIInfo[ guiMap.size() ] ) ;
    616                Arrays.sort( guiInfos );
    617                final Map<String,GUIInfo> sortMap = new LinkedHashMap<>();
    618                size = guiInfos.length;
    619                for( int i=0; i<size; i++ ) {
    620                        final GUIInfo guiInfo = guiInfos[i];
    621                        final String guikey     = guiInfo.getKey();
    622                        sortMap.put( guikey,guiInfo );
    623                }
    624
    625                user.setGUIMap( sortMap, forbidAddrSet );
    626        }
    627
    628        /**
    629         * 指定されたクエリを発行し、ラベルマップを作成します。
    630         *
    631         * @og.rev 4.3.4.0 (2008/12/01) 新規作成
    632         * @og.rev 6.4.0.5 (2016/01/09) useLabelMap="true" 時のSQL文の実行は、dbid を使用して行う。
    633         *
    634         * @param       query   ラベルマップを作成するクエリ
    635         * @param       dbid    接続先ID
    636         *
    637         * @return      ラベルマップ
    638         * @see org.opengion.hayabusa.resource.LabelDataLoader#getLabelMap( String,String )
    639         */
    640        public Map<String, LabelData> getLabelMap( final String query , final String dbid ) {
    641                return labelLoader.getLabelMap( query , dbid );
    642        }
    643
    644        /**
    645         * リソースマネージャーをキーに基づいて部分クリアします。
    646         * ここでは、部分クリアなため、GUIData に関しては、処理されません。
    647         * また、存在しないキーを指定されたリソースは、何も処理されません。
    648         *
    649         * @og.rev 5.4.3.4 (2012/01/12) labelPool の削除追加
    650         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
    651         * @og.rev 6.9.0.1 (2018/02/05) どのシステムIDのﾘｿｰｽがクリアされたかを表示します。
    652         *
    653         * @param   key         カラムのキー
    654         */
    655        public void clear( final String key ) {
    656                // 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限
    657                if( key != null ) {
    658//                      System.out.println( "Key=[" + key + "] の部分リソースクリアを実施しました。" );   // 6.9.0.1 (2018/02/05) columnLoader へ移動
    659                        columnLoader.clear( key );
    660                        codeLoader.clear( key );
    661                        labelLoader.clear( key );
    662                        columnPool.remove( key );
    663                }
    664        }
    665
    666        /**
    667         * GUI情報をクリアします。
    668         * ここでは、関連するラベル、コードリソースの部分クリアも行います。
    669         * GUI情報は、シーケンスに管理しているため、この処理１回ごとに、
    670         * GUIData を全件再読み込みを行いますので、ご注意ください。
    671         *
    672         */
    673        public void guiClear() {
    674                final GUIData[] gui = guiLoader.getAllData();
    675
    676                for( int i=0; i<gui.length; i++ ) {
    677                        final String key = gui[i].getGuiKey();
    678                        labelLoader.clear( key );
    679                }
    680                codeLoader.clear( "CLASSIFY" );
    681                guiLoader.clear();
    682        }
    683
    684        /**
    685         * リソースマネージャーをクリア(初期化)します。
    686         *
    687         * @og.rev 5.4.3.4 (2012/01/12) labelPool の削除追加
    688         *
    689         */
    690        public void clear() {
    691                columnLoader.clear();
    692                codeLoader.clear();
    693                labelLoader.clear();
    694                guiLoader.clear();
    695                columnPool.clear();
    696        }
    697}