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 * の3つのプロパティーファイルを内部に持っており,それぞれのメソッドにより,
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 * 3通り考えられます。
068 * 1つ目は、毎回 要求が発生する毎に CodeSelection を作成し、プールしていきます。こうすることで、
069 * 初めて使用されたときだけオブジェクト化されますので、メモリの節約が可能です。ただし、
070 * プールにヒットしなかった場合は、やはりリソースから検索しますので、元々ヒットしない
071 * キーに対しては、毎回リソースを検索するため、非効率です。
072 * 2つめは、元々ヒットしないキーに対して、NullCodeSelectionオブジェクトを登録しておくことで、
073 * プールにため込んで行くと言う方法です。この場合は、シングルトーンにしてメモリを節約しますが、
074 * それでもプール自体の容量は、確保しておく必要があります。
075 * 3つめは、この ResourceManager がインスタンス化されるときに、すべての CodeSelectionオブジェクトを
076 * あらかじめ プールしておく方法です。使わない CodeSelection もインスタンス化する変わりに、
077 * キャッシュにヒットしない場合は、即 CodeSelection が存在しないと判断できるため、
078 * もっともパフォーマンスが高くなります。
079 * 本 ResourceManager の実装は、3つめの、あらかじめ、すべてをキャッシュしておく方法を
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         *      システムIDと言語コードを指定して,生成します。
101         *
102         * @param       systemId システムID
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情報は、シーケンスに管理しているため、この処理1回ごとに、
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}