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     */
016    package org.opengion.hayabusa.resource;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.fukurou.util.ApplicationInfo;
020    import org.opengion.fukurou.db.DBUtil;
021    
022    import java.util.Map;
023    import java.util.HashMap;
024    import java.util.LinkedHashMap ;
025    import java.util.WeakHashMap ;
026    import java.util.Collections ;
027    
028    /**
029     * コードオブジェクトを作?する??タロードクラスです?
030     * systemId と lang に対応したコードオブジェクトを作?します?
031     *
032     * コードオブジェクト???目(CLM)に対して、?のコー?CODE)を持って?す?
033     * こ??のコードを表示?持つことで、?ル?ンメニュー等?表示??します?
034     *
035     * コードオブジェクトを作?する場合?、同??目・コードで、作?区?KBSAKU)違いの場合??
036     * ?大きな作?区?持つコードを使用します?
037     * 作?区?KBSAKU)は、他?リソースと異なり?同??目・コード単位に設定すべきです?
038     * これは??常は?単位に作?区?持つべきところを?コード単位でしか
039     * 持てな?ータベ?スの設計になって?為です?アプリケーション側で設定条件?
040     * きちんと管?れ?、作?区?使用できますが、?にはお奨めできません?
041     * 作?区?KBSAKU)='0' の??タは、?スタリソースとして、エンジンとともに
042     * 配?れるリソースになります?
043     *
044     * 読み込みフラグ(FGLOAD)は、使用しません?
045     * コードリソースに関しては、シス?起動時に、すべてのコードリソースをエンジン?
046     * に取り込みます?ただし?リソースのキャ?ュに、WeakHashMap クラスを使用して?ため?
047     * メモリオーバ?時には、クリアされるため?単独での読み取りも行います?
048     * SYSTEM_ID='**' は、?通リソースです?
049     * これは、シス?間で共通に使用されるリソース??を登録しておきます?
050     *
051     * @og.rev 4.0.0.0 (2004/12/31) 新規作?
052     * @og.group リソース管?
053     *
054     * @version  4.0
055     * @author   Kazuhiko Hasegawa
056     * @since    JDK5.0,
057     */
058    final class CodeDataLoader {
059            // リソースの接続?を?取得します?
060            private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );
061    
062            /** ??リソースの初期?読み込みのクエリー */
063            // キーブレイクで、SYSTEM_ID 違いは、まとめて処?る為、最初に ORDER BY しておく?があります?
064            //public static final String QUERY = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU" // 4.0.0.0(2007/10/17)
065    //      public static final String QUERY = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,''" // 4.3.8.0 (2009/08/01)
066    //                                                                      + " from GEA04 where SYSTEM_ID in ( ?,'**') and FGJ='1'"
067    //                                                                      + " order by SYSTEM_ID,KBSAKU,CLM,SEQNO,CODE" ;
068            // 5.1.9.0 (2010/08/01) order by 変更
069            public static final String QUERY = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,''" // 5.1.9.0 (2010/08/01)
070                                                                            + " from GEA04 where SYSTEM_ID in ( ?,'**') and FGJ='1'"
071                                                                            + " order by SYSTEM_ID,KBSAKU,CLM,SEQNO,CODELVL,CODE" ;
072    
073            /** ??リソースの個別読み込み時?クエリー */
074            //public static final String QUERY2 = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU" // 4.0.0.0(2007/10/17)
075    //      public static final String QUERY2 = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,''" // 4.3.8.0 (2009/08/01)
076    //                                                                      + " from GEA04 where SYSTEM_ID in ( ?,'**') and FGJ='1' and CLM=?"
077    //                                                                      + " order by SYSTEM_ID,KBSAKU,CLM,SEQNO,CODE" ;
078            // 5.1.9.0 (2010/08/01) order by 変更
079            public static final String QUERY2 = "select CLM,CODE,'','',CODELVL,CODEGRP,CODE_PARAM,ROLES,SYSTEM_ID,KBSAKU,''" // 5.1.9.0 (2010/08/01)
080                                                                            + " from GEA04 where SYSTEM_ID in ( ?,'**') and FGJ='1' and CLM=?"
081                                                                            + " order by SYSTEM_ID,KBSAKU,CLM,SEQNO,CODELVL,CODE" ;
082    
083            private final Map<String,CodeData> pool = Collections.synchronizedMap( new WeakHashMap<String,CodeData>() );        // キャ?ュ用プ?ル
084            private final String  SYSTEM_ID ;               // シス?ID
085    //      private final String  LANG ;                    // ??
086    
087            /** コネクションにアプリケーション??を追記するかど???*/
088            public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
089    
090            // 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
091            private final ApplicationInfo appInfo;
092    
093            private final LabelDataLoader LABEL_LOADER; // 見直し?!!
094    
095            /**
096             *  lang 毎に ファクトリオブジェクトを作?します?
097             *
098             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
099             *
100             * @param systemId シス?ID
101             * @param initLoad リソース??タの先読み可否(true:先読みする)
102             * @param lLoader ラベル??タロー??
103             */
104    //      CodeDataLoader( final String systemId,final String lang,final boolean initLoad ) {
105            CodeDataLoader( final String systemId,final boolean initLoad,final LabelDataLoader lLoader) {
106                    SYSTEM_ID = systemId;
107    //              LANG      = lang;
108                    LABEL_LOADER = lLoader;
109    
110                    // 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
111                    if( USE_DB_APPLICATION_INFO ) {
112                            appInfo = new ApplicationInfo();
113                            // ユーザーID,IPアドレス,ホスト名
114                            appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
115                            // 画面ID,操?プログラ?D
116                            appInfo.setModuleInfo( "CodeDataLoader",null,null );
117                    }
118                    else {
119                            appInfo = null;
120                    }
121    
122                    // ApplicationInfo の設定が終わってから実行します?
123                    if( initLoad ) { loadDBResource(); }
124            }
125    
126            /**
127             * ??リソースより コードデータを取得?設定します?
128             *
129             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
130             * @og.rev 4.3.8.0 (2009/08/01) rawShortLabel追?
131             */
132            private void loadDBResource() {
133    //              String[] args = new String[] { LANG,SYSTEM_ID };
134                    String[] args = new String[] { SYSTEM_ID };
135    
136                    String[][] vals = DBUtil.dbExecute( QUERY,args,appInfo,DBID );
137    
138                    Map<String,Map<String,String[]>> clmMap  = new HashMap<String,Map<String,String[]>>();
139                    int len = vals.length;
140                    String bkClm = null;                    // キーブレイク
141                    String bkSystem = null;
142                    String bkKbsaku = null;
143                    // 以下?処??、SYSTEM_ID違いを塊で処?ます?(混在させません?
144                    Map<String,String[]> codeMap = null;
145                    for( int i=0; i<len; i++ ) {
146                            String   clm  = vals[i][CodeData.CLM];
147                            String   code = vals[i][CodeData.CODE];
148                            String   systemId = vals[i][CodeData.SYSTEM_ID];
149                            String   kbsaku = vals[i][CodeData.KBSAKU];
150    //                      if( bkClm == null || !bkClm.equals( clm ) ) {
151                            if( bkClm == null || !bkClm.equals( clm ) || !bkSystem.equals(systemId) || !bkKbsaku.equals(kbsaku) ) {
152                                    codeMap = new LinkedHashMap<String,String[]>();
153                                    clmMap.put( clm,codeMap );
154                                    bkClm = clm;
155                                    bkSystem = systemId;
156                                    bkKbsaku = kbsaku;
157                            }
158    
159                            String lkey = clm+"."+code; // ?つけ?
160                            vals[i][CodeData.LNAME] = LABEL_LOADER.getLabelData(lkey).getLongLabel();
161                            vals[i][CodeData.SNAME] = LABEL_LOADER.getLabelData(lkey).getShortLabel();
162                            vals[i][CodeData.RSNAME] = LABEL_LOADER.getLabelData(lkey).getRawShortLabel(); // 4.3.8.0 (2009/08/01) spanが付かな?前短
163    
164                            codeMap.put( code,vals[i] );
165                    }
166    
167                    String[] clmKeys = clmMap.keySet().toArray( new String[clmMap.size()] );
168                    int size = clmKeys.length;
169                    for( int i=0; i<size; i++ ) {
170                            String clm = clmKeys[i];
171                            codeMap = clmMap.get( clm );
172    
173                            pool.put( clm,new CodeData( clm,codeMap ) );
174                    }
175    
176                    System.out.println( "  CodeDataLoader [" + size + "] loaded" );
177            }
178    
179            /**
180             * CodeData オブジェクトを取得します?
181             * 作?したCodeDataオブジェクト???部にプ?ルしておき?同じリソース要求が
182             * あったとき???ールの CodeDataを返します?
183             *
184             * @og.rev 4.3.8.0 (2009/08/01) rawShortLabel追?
185             *
186             * @param   key       コード?キー
187             *
188             * @return  CodeData  オブジェク?
189             */
190            public CodeData getCodeData( final String key ) {
191                    CodeData codeData = pool.get( key ) ;
192    
193                    if( codeData == null ) {
194    //                      String[] args = new String[] { LANG,SYSTEM_ID,key };
195                            String[] args = new String[] { SYSTEM_ID,key };
196                            String[][] vals = DBUtil.dbExecute( QUERY2,args,appInfo,DBID );
197    
198                            int len = vals.length;
199                            String bkSystem = null;                 // キーブレイク
200                            String bkKbsaku = null;
201                            // 以下?処??、SYSTEM_ID違いを塊で処?ます?(混在させません?
202                            Map<String,String[]> codeMap = null;
203                            for( int i=0; i<len; i++ ) {
204                                    String   systemId = vals[i][CodeData.SYSTEM_ID];
205                                    String   code     = vals[i][CodeData.CODE];
206                                    String   kbsaku = vals[i][CodeData.KBSAKU];
207    //                              if( bkSystem == null || !bkSystem.equals( systemId ) ) {
208                                    if( bkSystem == null || !bkSystem.equals( systemId ) || !bkKbsaku.equals(kbsaku) ) {
209                                            codeMap = new LinkedHashMap<String,String[]>();
210                                            bkSystem = systemId;
211                                            bkKbsaku = kbsaku;
212                                    }
213    
214                                    String lkey = key+"."+code; // ?つけ?
215                                    vals[i][CodeData.LNAME] = LABEL_LOADER.getLabelData(lkey).getLongLabel();
216                                    vals[i][CodeData.SNAME] = LABEL_LOADER.getLabelData(lkey).getShortLabel();
217                                    vals[i][CodeData.RSNAME] = LABEL_LOADER.getLabelData(lkey).getRawShortLabel(); // 4.3.8.0 (2009/08/01) spanが付かな?前短
218    
219                                    codeMap.put( code,vals[i] );
220                            }
221    
222                            if( codeMap != null ) {
223                                    codeData = new CodeData( key,codeMap );
224                                    pool.put( key,codeData );
225                            }
226                    }
227                    return codeData ;
228            }
229    
230            /**
231             * CodeData オブジェクトを取得します?
232             * 作?したCodeDataオブジェクト???部にプ?ルしておき?同じリソース要求が
233             * あったとき???ールの CodeDataを返します?
234             *
235             * 引数にQUERYを渡すことで、DBから、動?コードリソースを作?できます?
236             * 引数の?は、CodeData で定義して? CLM,CODE,LNAME,SNAME の?のままです?
237             * QUERY には、key を引数にとる?があります?つまり?WHERE CLM = ? の様な記述が?です?
238             *
239             * @og.rev 5.4.2.2 (2011/12/14) 新規追??
240             *
241             * @param   key   コード?キー
242             * @param       query 検索SQL(引数に? を?持つ)
243             *
244             * @return  CodeData  オブジェク?
245             */
246            public CodeData getCodeData( final String key,final String query ) {
247                    CodeData codeData = pool.get( key ) ;
248    
249                    if( codeData == null ) {
250                            String[] args = new String[] { key };
251                            String[][] vals = DBUtil.dbExecute( query,args,appInfo,DBID );
252    
253                            int len = vals.length;
254                            Map<String,String[]> codeMap = new LinkedHashMap<String,String[]>();
255                            for( int i=0; i<len; i++ ) {
256                                    String[] cdVals = new String[CodeData.MAX_LENGTH];      // 空の配?を毎回作?
257    
258                                    String   code   = vals[i][CodeData.CODE];
259    
260                                    cdVals[CodeData.CLM]   = key ;
261                                    cdVals[CodeData.CODE]  = code;
262                                    cdVals[CodeData.LNAME] = vals[i][CodeData.LNAME];
263                                    cdVals[CodeData.SNAME] = vals[i][CodeData.SNAME];
264    
265                                    codeMap.put( code,cdVals );
266                            }
267    
268                            if( ! codeMap.isEmpty() ) {
269                                    codeData = new CodeData( key,codeMap );
270                                    pool.put( key,codeData );
271                            }
272                    }
273                    return codeData ;
274            }
275    
276            /**
277             * CodeData オブジェクト?キャ?ュを?別にクリアします?
278             * リソース??タの更新など、???更新時に、すべてのキャ?ュ?
279             * 破?る?ではなく?????み破?きる機?です?
280             *
281             * @og.rev 4.0.2.0 (2007/12/25) コードリソースクリア時に対応するラベルリソースもクリアする?
282             *
283             * @param   key       コード?キー
284             */
285            public void clear( final String key ) {
286    
287                    // 4.0.2.0 (2007/12/25)
288                    CodeData cdata = pool.remove( key );
289                    if( cdata != null ) {
290                            String clm = cdata.getColumn();
291                            for( int i=0; i<cdata.getSize(); i++ ) {
292                                    LABEL_LOADER.clear( clm + '.' + cdata.getCodeKey( i ) );
293                            }
294                    }
295            }
296    
297            /**
298             * CodeData オブジェクト?キャ?ュをクリアして、?作?します?
299             *
300             */
301            public void clear() {
302                    pool.clear();
303            }
304    }