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}