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