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 org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.SystemManager; 020import org.opengion.fukurou.util.Cleanable; 021 022import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 023import java.util.concurrent.ConcurrentHashMap; // 6.4.3.3 (2016/03/04) 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 private static final ResourceManager JA_MANAGER = new ResourceManager( SYSTEM_ID,"ja",true ); // 6.4.1.1 (2016/01/16) ja_Manager → JA_MANAGER refactoring 048 049 /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */ 050 private static final ConcurrentMap<String,ResourceManager> POOL = new ConcurrentHashMap<>(); // 6.4.3.3 (2016/03/04) 051 052 // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理 053 static { 054 final Cleanable clr = new Cleanable() { 055 /** 056 * 初期化(クリア)します。 057 * 主に、キャッシュクリアで利用します。 058 */ 059 public void clear() { 060 ResourceFactory.clear(); 061 } 062 }; 063 064 SystemManager.addCleanable( clr ); 065 } 066 067 /** 068 * デフォルトコンストラクターをprivateにして、 069 * オブジェクトの生成をさせないようにする。 070 * 071 */ 072 private ResourceFactory() { 073 } 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 if( SYSTEM_ID.equalsIgnoreCase( sys ) && "ja".equalsIgnoreCase( lg ) ) { 111 return JA_MANAGER ; 112 } 113 114 final String key = sys + lg ; 115 116 // Map#computeIfAbsent : 戻り値は、新しい値。追加有り、置換有り、削除有り 117 return POOL.computeIfAbsent( key , k -> new ResourceManager( sys,lg,initLoad ) ); 118 119 } 120 121 /** 122 * キャッシュ(プール)から、すべてのオブジェクトをクリアします。 123 * この時、POOLされているオブジェクトは、ResourceManager#clear() メソッドを 124 * 呼び出します。 125 * 126 * @og.rev 3.5.5.7 (2004/05/10) CodeSelectionFactoryをクリアします。 127 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 128 */ 129 public static void clear() { 130 JA_MANAGER.clear(); 131 132 // POOL.forEach( (k,v) -> v.clear() ); // ConcurrentMap なのでnullチェック不要 133 POOL.values().forEach( v -> v.clear() ); // ConcurrentMap なのでnullチェック不要 134 POOL.clear(); 135 136 } 137 138 /** 139 * キャッシュ(プール)から、すべてのGUI情報オブジェクトをクリアします。 140 * 141 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 142 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 143 */ 144 public static void guiClear() { 145 JA_MANAGER.guiClear(); 146 147 // POOL.forEach( (k,v) -> v.guiClear() ); // ConcurrentMap なのでnullチェック不要 148 POOL.values().forEach( v -> v.guiClear() ); // ConcurrentMap なのでnullチェック不要 149 150 } 151}