1 package charactermanaj.model.io;
\r
3 import java.io.BufferedOutputStream;
\r
5 import java.io.FileNotFoundException;
\r
6 import java.io.FileOutputStream;
\r
7 import java.io.IOException;
\r
8 import java.io.InputStream;
\r
10 import java.net.URL;
\r
11 import java.sql.Timestamp;
\r
12 import java.util.EnumSet;
\r
13 import java.util.Enumeration;
\r
14 import java.util.LinkedHashMap;
\r
15 import java.util.Map;
\r
16 import java.util.Properties;
\r
17 import java.util.logging.Level;
\r
18 import java.util.logging.Logger;
\r
20 import charactermanaj.model.CharacterData;
\r
21 import charactermanaj.util.ConfigurationDirUtilities;
\r
22 import charactermanaj.util.LocalizedResourcePropertyLoader;
\r
23 import charactermanaj.util.ResourceLoader;
\r
24 import charactermanaj.util.ResourceNames;
\r
25 import charactermanaj.util.SetupLocalization;
\r
28 * デフォルトキャラクターセットのプロバイダ
\r
32 public class CharacterDataDefaultProvider {
\r
35 * リソースに格納されているデフォルトのキャラクター定義のリソースパスまでのプレフィックス.<br>
\r
37 public static final String DEFAULT_CHARACTER_PREFIX = "template/";
\r
40 * テンプレートをリストしているXML形式のプロパティファイル名
\r
42 public static final String TEMPLATE_LIST_XML = "characterDataTemplates";
\r
45 * デフォルトのキャラクターセット名(ver2)
\r
47 public static final String DEFAULT_CHARACTER_NAME_V2 = "character2.xml";
\r
50 * デフォルトのキャラクターセット名(ver3)
\r
52 public static final String DEFAULT_CHARACTER_NAME_V3 = "character3.xml";
\r
57 private static final Logger logger = Logger
\r
58 .getLogger(CharacterDataDefaultProvider.class.getName());
\r
60 public enum DefaultCharacterDataVersion {
\r
62 public String getResourceName() {
\r
63 return DEFAULT_CHARACTER_NAME_V2;
\r
67 public String getResourceName() {
\r
68 return DEFAULT_CHARACTER_NAME_V3;
\r
72 public abstract String getResourceName();
\r
74 public CharacterData create(CharacterDataDefaultProvider prov) {
\r
76 throw new IllegalArgumentException();
\r
79 return prov.loadPredefinedCharacterData(getResourceName());
\r
81 } catch (IOException ex) {
\r
82 throw new RuntimeException(
\r
83 "can not create the default profile from application's resource",
\r
90 * デフォルトのキャラクター定義を生成して返す.<br>
\r
91 * 一度生成された場合はキャッシュされる.<br>
\r
92 * 生成されたキャラクター定義のdocBaseはnullであるため、docBaseをセットすること.<br>
\r
95 * デフォルトキャラクターセットのバージョン
\r
98 public synchronized CharacterData createDefaultCharacterData(
\r
99 DefaultCharacterDataVersion version) {
\r
100 if (version == null) {
\r
101 throw new IllegalArgumentException();
\r
103 return version.create(this);
\r
107 * テンプレートリストの定義プロパティを読み込む.<br>
\r
108 * neutral引数がfalseの場合は現在のロケールを優先する.<br>
\r
109 * 引数がtrueの場合は読み込み順を逆転させ、言語中立を優先する.<br>
\r
113 * @return テンプレートリストのプロパティ
\r
115 private Properties getTemplateListProperties(boolean neutral) {
\r
116 // テンプレートリソースは実行中に増減する可能性があるため、
\r
118 LocalizedResourcePropertyLoader loader = new LocalizedResourcePropertyLoader(
\r
120 String name = DEFAULT_CHARACTER_PREFIX + TEMPLATE_LIST_XML;
\r
121 ResourceNames resNames = LocalizedResourcePropertyLoader
\r
122 .getResourceNames(name, null);
\r
124 // 言語中立を優先する場合は、プロパティの重ね順を逆転させて言語中立で最後に上書きする.
\r
125 resNames = resNames.reverse();
\r
127 return loader.getLocalizedProperties(name);
\r
131 * キャラクターデータのxmlファイル名をキーとし、表示名を値とするマップ.<br>
\r
136 public Map<String, String> getCharacterDataTemplates() {
\r
137 // キャラクターデータのxmlファイル名をキーとし、表示名を値とするマップ
\r
138 final LinkedHashMap<String, String> templateNameMap = new LinkedHashMap<String, String>();
\r
140 // テンプレートの定義プロパティのロード
\r
141 Properties props = getTemplateListProperties(false);
\r
144 String strOrders = props.getProperty("displayOrder");
\r
145 if (strOrders != null) {
\r
146 for (String key : strOrders.split(",")) {
\r
148 String val = props.getProperty(key);
\r
149 if (val != null && val.trim().length() > 0) {
\r
150 String resKey = DEFAULT_CHARACTER_PREFIX + key;
\r
151 if (getResource(resKey) != null) {
\r
153 templateNameMap.put(key, val);
\r
159 // 順序が指定されていないアイテムの追加
\r
160 Enumeration<?> enm = props.propertyNames();
\r
161 while (enm.hasMoreElements()) {
\r
162 String key = (String) enm.nextElement();
\r
163 String val = props.getProperty(key);
\r
164 if (key.endsWith(".xml")) {
\r
165 String resKey = DEFAULT_CHARACTER_PREFIX + key;
\r
166 if (getResource(resKey) != null) {
\r
168 templateNameMap.put(key, val);
\r
173 // フォルダにある未登録のxmlファイルもテンプレート一覧に加える
\r
174 // (ただし、テンプレートリストプロパティを除く)
\r
176 File templDir = getTemplateDir(false);
\r
177 if (templDir.isDirectory()) {
\r
178 File[] files = templDir.listFiles(new java.io.FileFilter() {
\r
179 public boolean accept(File pathname) {
\r
180 String name = pathname.getName();
\r
181 if (templateNameMap.containsKey(name)) {
\r
182 // すでに登録済みなのでスキップする.
\r
185 if (name.startsWith(TEMPLATE_LIST_XML)) {
\r
186 // テンプレートリストプロパティファイルは除外する.
\r
189 return pathname.isFile() && name.endsWith(".xml");
\r
192 if (files == null) {
\r
193 files = new File[0];
\r
195 CharacterDataPersistent persist = CharacterDataPersistent
\r
197 for (File file : files) {
\r
199 URI docBase = file.toURI();
\r
200 CharacterData cd = persist.loadProfile(docBase);
\r
201 if (cd != null && cd.isValid()) {
\r
202 String name = file.getName();
\r
203 templateNameMap.put(name, cd.getName());
\r
205 } catch (IOException ex) {
\r
206 logger.log(Level.WARNING, "failed to read templatedir."
\r
212 } catch (IOException ex) {
\r
213 // ディレクトリの一覧取得に失敗しても無視する.
\r
214 logger.log(Level.FINE, "failed to read templatedir.", ex);
\r
217 return templateNameMap;
\r
221 * XMLリソースファイルから、定義済みのキャラクターデータを生成して返す.<br>
\r
222 * (現在のロケールの言語に対応するデータを取得し、なければ最初の言語で代替する.)<br>
\r
223 * 生成されたキャラクター定義のdocBaseはnullであるため、使用する場合はdocBaseをセットすること.<br>
\r
224 * 都度、XMLファイルから読み込まれる.<br>
\r
226 * @return デフォルトキャラクターデータ
\r
227 * @throws IOException
\r
230 public CharacterData loadPredefinedCharacterData(String name)
\r
231 throws IOException {
\r
233 String resKey = DEFAULT_CHARACTER_PREFIX + name;
\r
234 URL predefinedCharacter = getResource(resKey);
\r
235 if (predefinedCharacter == null) {
\r
236 throw new FileNotFoundException(resKey);
\r
238 InputStream is = predefinedCharacter.openStream();
\r
240 logger.log(Level.INFO, "load a predefined characterdata. resKey="
\r
242 CharacterDataXMLReader characterDataXmlReader = new CharacterDataXMLReader();
\r
243 cd = characterDataXmlReader.loadCharacterDataFromXML(is, null);
\r
256 * @return リソース、なければnull
\r
258 protected URL getResource(String resKey) {
\r
259 ResourceLoader resourceLoader = new ResourceLoader();
\r
260 return resourceLoader.getResource(resKey);
\r
264 * カスタマイズ用のテンプレートディレクトリを取得する.<br>
\r
265 * まだ作成されていない場合で、prepareが指示されている場合はフォルダを準備し、 既定のファイルを作成する.<br>
\r
268 * 実際にディレクトリを準備する場合はtrue
\r
269 * @return テンプレートディレクトリ
\r
271 public File getTemplateDir(boolean prepare) throws IOException {
\r
272 File baseDir = ConfigurationDirUtilities.getUserDataDir();
\r
273 SetupLocalization setup = new SetupLocalization(baseDir);
\r
274 File resourceDir = setup.getResourceDir();
\r
277 // テンプレートリソースが未設定であれば設定する.
\r
278 setup.setupToLocal(
\r
279 EnumSet.of(SetupLocalization.Resources.Template), false);
\r
281 // ディレクトリがなければ作成しておく
\r
282 if (resourceDir.exists()) {
\r
283 resourceDir.mkdirs();
\r
286 return new File(resourceDir, DEFAULT_CHARACTER_PREFIX);
\r
290 * "characterDataTemplates*.xml"のファイルは管理ファイルのため、 <br>
\r
291 * ユーザによる書き込みは禁止とする.<br>
\r
294 * @return 書き込み可能であるか?
\r
296 public boolean canFileSave(String name) {
\r
297 if (name.trim().startsWith("characterDataTemplates")) {
\r
304 * 指定したキャラクターデータをテンプレートとして保存する.<br>
\r
310 * @param localizedName
\r
312 * @throws IOException
\r
314 public void saveTemplate(String name, CharacterData cd, String localizedName)
\r
315 throws IOException {
\r
316 if (name == null || !canFileSave(name)) {
\r
317 throw new IllegalArgumentException();
\r
321 // (リソースが、まだファイルに展開されていなれば展開する)
\r
322 File templDir = getTemplateDir(true);
\r
323 File templFile = new File(templDir, name);
\r
325 // キャラクターデータをXML形式でテンプレートファイルへ保存
\r
326 CharacterDataXMLWriter characterDataXmlWriter = new CharacterDataXMLWriter();
\r
327 BufferedOutputStream bos = new BufferedOutputStream(
\r
328 new FileOutputStream(templFile));
\r
330 // パーツセットなしの状態とし、名前をローカライズ名に設定する.
\r
331 CharacterData templCd = cd.duplicateBasicInfo(false);
\r
332 templCd.setName(localizedName);
\r
334 characterDataXmlWriter.writeXMLCharacterData(templCd, bos);
\r
340 // テンプレートの定義プロパティのロード(言語中立を優先)
\r
341 Properties neutralProps = getTemplateListProperties(true);
\r
344 neutralProps.put(name, localizedName);
\r
347 File neutralPropsFile = new File(templDir, TEMPLATE_LIST_XML + ".xml");
\r
348 BufferedOutputStream fos = new BufferedOutputStream(
\r
349 new FileOutputStream(neutralPropsFile));
\r
351 neutralProps.storeToXML(fos,
\r
352 new Timestamp(System.currentTimeMillis()).toString());
\r