1 // ================================================================================================
3 // アプリケーションの設定を保持するクラスソース</summary>
5 // <copyright file="Config.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Wptscs.Models
14 using System.Collections.Generic;
16 using System.Windows.Forms;
18 using System.Xml.Serialization;
19 using Honememo.Utilities;
20 using Honememo.Wptscs.Logics;
21 using Honememo.Wptscs.Properties;
22 using Honememo.Wptscs.Utilities;
23 using Honememo.Wptscs.Websites;
26 /// アプリケーションの設定を保持するクラスです。
28 public class Config : IXmlSerializable
35 private IList<Website> websites = new List<Website>();
40 private IList<TranslationDictionary> itemTables = new List<TranslationDictionary>();
45 private TranslationTable headingTable = new TranslationTable();
54 /// <remarks>通常は<see cref="GetInstance(string)"/>で設定ファイルから読み込む。</remarks>
64 /// 設定ファイルと紐付いている場合のファイル名。
66 /// <remarks>ファイルと紐付いていない場合は空。</remarks>
74 /// 翻訳支援処理で使用するロジッククラス名。
76 public Type Translator
85 /// <exception cref="ArgumentNullException"><c>null</c>が指定された場合。</exception>
86 /// <remarks>空でもオブジェクトは存在。</remarks>
87 public IList<Website> Websites
96 this.websites = Validate.NotNull(value);
103 /// <exception cref="ArgumentNullException"><c>null</c>が指定された場合。</exception>
104 /// <remarks>空でもオブジェクトは存在。</remarks>
105 public IList<TranslationDictionary> ItemTables
109 return this.itemTables;
114 this.itemTables = Validate.NotNull(value);
121 /// <exception cref="ArgumentNullException"><c>null</c>が指定された場合。</exception>
122 /// <remarks>空でもオブジェクトは存在。</remarks>
123 public TranslationTable HeadingTable
127 return this.headingTable;
132 this.headingTable = Validate.NotNull(value);
141 /// アプリケーションの設定を取得する。
142 /// ユーザーごとの設定ファイルがあればその内容を、
143 /// なければアプリケーション標準の設定ファイルの内容を
144 /// 読み込んで、インスタンスを作成する。
146 /// <param name="file">設定ファイル名。</param>
147 /// <returns>作成したインスタンス。</returns>
148 /// <exception cref="FileNotFoundException">指定されたファイルがどこにも存在しない場合。</exception>
149 public static Config GetInstance(string file)
151 // ユーザーごと・または初期設定用の設定ファイルを読み込み
152 string path = FormUtils.SearchUserAppData(file, Settings.Default.ConfigurationCompatible);
153 if (string.IsNullOrEmpty(path))
156 throw new FileNotFoundException(file + " is not found");
159 // 設定ファイルを読み込み、読み込み元のファイル名は記録しておく
160 System.Diagnostics.Debug.WriteLine("Config.GetInstance > " + path + " を読み込み");
161 using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
163 Config config = new XmlSerializer(typeof(Config)).Deserialize(stream) as Config;
174 /// 設定をユーザーごとの設定ファイルに書き出し。
176 /// <exception cref="InvalidOperationException">
177 /// <see cref="File"/>にこのインスタンスと紐付くファイル名が指定されていない場合。
181 // このインスタンスとファイルが紐付いていない場合、実行不可
182 if (string.IsNullOrWhiteSpace(this.File))
184 throw new InvalidOperationException("file is empty");
187 // 最初にディレクトリの有無を確認し作成
188 string path = Application.UserAppDataPath;
189 if (!Directory.Exists(path))
191 Directory.CreateDirectory(path);
195 using (Stream stream = new FileStream(Path.Combine(path, this.File), FileMode.Create))
197 new XmlSerializer(typeof(Config)).Serialize(stream, this);
203 #region 設定値取得用インスタンスメソッド
206 /// 設定から、現在の処理対象・指定された言語のウェブサイトを取得する。
208 /// <param name="lang">言語コード。</param>
209 /// <returns>ウェブサイトの情報。存在しない場合は<c>null</c>返す。</returns>
210 public Website GetWebsite(string lang)
213 foreach (Website s in this.Websites)
215 if (s.Language.Code == lang)
222 // ※ こっちがNeedCreateじゃないのは、何をnewすればいいのか判らないため
227 /// 設定から、現在の処理対象・指定された言語の対訳表(項目)を取得する。
229 /// <param name="from">翻訳元言語。</param>
230 /// <param name="to">翻訳先言語。</param>
231 /// <returns>対訳表の情報。存在しない場合は新たに作成した対訳表を返す。</returns>
232 public TranslationDictionary GetItemTableNeedCreate(string from, string to)
234 // オブジェクトに用意されている共通メソッドをコール
235 return TranslationDictionary.GetDictionaryNeedCreate(this.ItemTables, from, to);
240 #region XMLシリアライズ用メソッド
243 /// シリアライズするXMLのスキーマ定義を返す。
245 /// <returns>XML表現を記述する<see cref="System.Xml.Schema.XmlSchema"/>。</returns>
246 public System.Xml.Schema.XmlSchema GetSchema()
252 /// XMLからオブジェクトを読み込む。
254 /// <param name="reader">読込元の<see cref="XmlReader"/>。</param>
255 public void ReadXml(XmlReader reader)
257 XmlDocument xml = new XmlDocument();
261 // ※ 以下、基本的に無かったらNGの部分はいちいちチェックしない。例外飛ばす
262 XmlElement rootElement = xml.DocumentElement;
265 this.Translator = this.ParseTranslator(rootElement.SelectSingleNode("Translator").InnerText);
268 foreach (XmlNode siteNode in rootElement.SelectSingleNode("Websites").ChildNodes)
270 // ノードに指定された内容に応じたインスタンスを取得する
271 this.Websites.Add(this.ParseWebsite(siteNode, reader.Settings));
275 XmlSerializer serializer = new XmlSerializer(typeof(TranslationDictionary), new XmlRootAttribute("ItemTable"));
276 foreach (XmlNode itemNode in rootElement.SelectSingleNode("ItemTables").ChildNodes)
278 using (XmlReader r = XmlReader.Create(new StringReader(itemNode.OuterXml), reader.Settings))
280 this.ItemTables.Add(serializer.Deserialize(r) as TranslationDictionary);
285 using (XmlReader r = XmlReader.Create(
286 new StringReader(rootElement.SelectSingleNode("HeadingTable").OuterXml),
289 this.HeadingTable = new XmlSerializer(typeof(TranslationTable), new XmlRootAttribute("HeadingTable"))
290 .Deserialize(r) as TranslationTable;
297 /// <param name="writer">出力先の<see cref="XmlWriter"/>。</param>
298 public void WriteXml(XmlWriter writer)
301 string translator = this.Translator.FullName;
302 if (translator.StartsWith(typeof(Translator).Namespace))
304 // 自前のエンジンの場合、クラス名だけを出力
305 translator = this.Translator.Name;
308 writer.WriteElementString("Translator", translator);
311 writer.WriteStartElement("Websites");
312 foreach (Website site in this.Websites)
314 // 通常はサイトのパッケージ名も含めたフル名を要素名とする
315 string siteName = site.GetType().FullName;
316 if (siteName.StartsWith(typeof(Website).Namespace))
318 // 自前のサイトの場合、クラス名だけを出力
319 siteName = site.GetType().Name;
322 new XmlSerializer(site.GetType(), new XmlRootAttribute(siteName)).Serialize(writer, site);
325 writer.WriteEndElement();
328 XmlSerializer serializer = new XmlSerializer(typeof(TranslationDictionary), new XmlRootAttribute("ItemTable"));
329 writer.WriteStartElement("ItemTables");
330 foreach (TranslationDictionary trans in this.ItemTables)
332 serializer.Serialize(writer, trans);
335 writer.WriteEndElement();
338 new XmlSerializer(this.HeadingTable.GetType(), new XmlRootAttribute("HeadingTable"))
339 .Serialize(writer, this.HeadingTable);
343 /// 指定されたXML値から<see cref="Translator"/>のクラスを取得する。
345 /// <param name="name">XMLのクラス名情報。</param>
346 /// <returns><see cref="Translator"/>クラス。</returns>
347 /// <remarks>クラスは動的に判定する。クラスが存在しない場合などは随時状況に応じた例外を投げる。</remarks>
348 private Type ParseTranslator(string name)
350 // Translateと同じパッケージに指定された名前のクラスがあるかを探す
351 Type type = Type.GetType(typeof(Translator).Namespace + "." + name, false, true);
354 // 存在しない場合、そのままの名前でクラスを探索、無ければ例外スロー
355 type = Type.GetType(name, true, true);
362 /// XMLノードから<see cref="Website"/>インスタンスをデシリアライズする。
364 /// <param name="node"><see cref="Website"/>をシリアライズしたノード。</param>
365 /// <param name="setting">XML読み込み時の設定。</param>
366 /// <returns>デシリアライズしたインスタンス。</returns>
367 /// <remarks>クラスはノード名から動的に判定する。クラスが存在しない場合などは随時状況に応じた例外を投げる。</remarks>
368 private Website ParseWebsite(XmlNode node, XmlReaderSettings setting)
370 // WebSiteと同じパッケージに指定された名前のクラスがあるかを探す
371 Type type = Type.GetType(typeof(Website).Namespace + "." + node.Name, false, true);
374 // 存在しない場合、そのままの名前でクラスを探索、無ければ例外スロー
375 type = Type.GetType(node.Name, true, true);
378 using (XmlReader r = XmlReader.Create(new StringReader(node.OuterXml), setting))
380 return new XmlSerializer(type).Deserialize(r) as Website;