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.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
019import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.3 (2016/03/04)
020
021import org.opengion.hayabusa.common.HybsSystem;
022import org.opengion.hayabusa.common.SystemManager;
023import org.opengion.fukurou.util.Cleanable;
024
025/**
026 * java.util.ResourceBundle クラスを複数管理するResourceManager をリソース毎に作成します。
027 * ResourceFactory#newInstance( String lang ) により、ResourceManager の要求毎に
028 * 新しくオブジェクトを作成するのではなく、ロケール毎に ResourceManager を作成します。
029 * ResourceManagerは、ロケール毎に 内部のプールに保存されています。
030 *
031 * リソース作成時に指定するロケールは、ISO 言語コード(ISO-639 で定義される 2 桁の小文字)
032 * <a href ="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
033 * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt</a>を使用して下さい。
034 * ただし、内部的に Locale を構築していますが、その正しさは、チェックされていませんので、
035 * 指定するロケールに応じた properties ファイルを用意しておいて下さい。
036 *
037 * @og.group リソース管理
038 *
039 * @version  4.0
040 * @author   Kazuhiko Hasegawa
041 * @since    JDK5.0,
042 */
043public final class ResourceFactory {
044        private static final String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" );
045
046        // デフォルトシステムIDの日本語(ja)は、特別扱いする。
047        // 6.4.1.1 (2016/01/16) ja_Manager → JA_MANAGER  refactoring
048        private static final ResourceManager JA_MANAGER = new ResourceManager( SYSTEM_ID,"ja",true );
049
050        /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
051        private static final ConcurrentMap<String,ResourceManager> POOL = new ConcurrentHashMap<>();    // 6.4.3.3 (2016/03/04)
052
053        // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
054        static {
055                final Cleanable clr = new Cleanable() {
056                        /**
057                         * 初期化(クリア)します。
058                         * 主に、キャッシュクリアで利用します。
059                         */
060                        public void clear() {
061                                ResourceFactory.clear();
062                        }
063                };
064
065                SystemManager.addCleanable( clr );
066        }
067
068        /**
069         * デフォルトコンストラクターをprivateにして、
070         * オブジェクトの生成をさせないようにする。
071         *
072         */
073        private ResourceFactory() {}
074
075        /**
076         * ResourceManager オブジェクトを取得します。
077         * 引数の言語コードに応じたリソースを1度だけ作成します。
078         * 作成したリソースオブジェクトは、内部にプールしておき、同じリソース要求が
079         * あったときは、プールのリソースを返します。
080         *
081         * @param       lang    言語コード(null の場合は、"ja" とします。)
082         *
083         * @return      ResourceManagerオブジェクト
084         * @og.rtnNotNull
085         */
086        public static ResourceManager newInstance( final String lang ) {
087                // 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
088                return lang == null || "ja".equalsIgnoreCase( lang ) ? JA_MANAGER : newInstance( SYSTEM_ID,lang,true ) ;
089        }
090
091        /**
092         * ResourceManager オブジェクトを取得します。
093         * 引数の言語コードに応じたリソースを1度だけ作成します。
094         * 作成したリソースオブジェクトは、内部にプールしておき、同じリソース要求が
095         * あったときは、プールのリソースを返します。
096         *
097         * @og.rev 6.4.3.3 (2016/03/04) Map#computeIfAbsent で対応する。
098         *
099         * @param       systemId        システムID(null の場合は、HybsSystem の SYSTEM_ID パラメータ)
100         * @param       lang            言語コード(null の場合は、"ja" とします。)
101         * @param       initLoad        リソースデータの先読み可否(true:先読みする)
102         *
103         * @return      ResourceManagerオブジェクト
104         */
105        public static ResourceManager newInstance( final String systemId,final String lang,final boolean initLoad ) {
106                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
107                final String sys = (systemId == null ) ? SYSTEM_ID : systemId ;
108                final String lg  = (lang     == null ) ? "ja"      : lang;
109
110                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
111                final ResourceManager rtnObj;
112
113                if( SYSTEM_ID.equalsIgnoreCase( sys ) && "ja".equalsIgnoreCase( lg ) ) {
114//                      return JA_MANAGER ;
115                        rtnObj = JA_MANAGER ;
116                }
117                else {
118                        final String key = sys + lg ;
119
120                        // Map#computeIfAbsent : 戻り値は、新しい値。追加有り、置換有り、削除有り
121//                      return POOL.computeIfAbsent( key , k -> new ResourceManager( sys,lg,initLoad ) );
122                        rtnObj = POOL.computeIfAbsent( key , k -> new ResourceManager( sys,lg,initLoad ) );
123                }
124                return rtnObj;
125        }
126
127        /**
128         * キャッシュ(プール)から、すべてのオブジェクトをクリアします。
129         * この時、POOLされているオブジェクトは、ResourceManager#clear() メソッドを
130         * 呼び出します。
131         *
132         * @og.rev 3.5.5.7 (2004/05/10) CodeSelectionFactoryをクリアします。
133         * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。
134         */
135        public static void clear() {
136                JA_MANAGER.clear();
137
138        //      POOL.forEach( (k,v) -> v.clear() );                     // ConcurrentMap なのでnullチェック不要
139                POOL.values().forEach( v -> v.clear() );        // ConcurrentMap なのでnullチェック不要
140                POOL.clear();
141        }
142
143        /**
144         * キャッシュ(プール)から、すべてのGUI情報オブジェクトをクリアします。
145         *
146         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
147         * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。
148         */
149        public static void guiClear() {
150                JA_MANAGER.guiClear();
151
152        //      POOL.forEach( (k,v) -> v.guiClear() );                  // ConcurrentMap なのでnullチェック不要
153                POOL.values().forEach( v -> v.guiClear() );             // ConcurrentMap なのでnullチェック不要
154        }
155}