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