PageRenderTime 34ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/0.8.x/src/Html.Downloader/Modules/RssMonitor/Engine/RssDataSerializer.cs

#
C# | 274 lines | 223 code | 51 blank | 0 comment | 8 complexity | 2055b8d488f3c2d6e9f275cb7d6959f8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.CompilerServices;
  5. using System.Text;
  6. using System.Xml;
  7. using System.Xml.Linq;
  8. using Html.Downloader.Engine.Common;
  9. using Melon.Commons.Configuration.Updates;
  10. using Melon.Commons.Repository;
  11. namespace Html.Downloader.Modules.RssMonitor.Engine
  12. {
  13. internal sealed class RssDataSerializer : IUpdateable
  14. {
  15. #region Private Fields
  16. private readonly VersionGraph graph;
  17. private readonly IRepositoryService repository;
  18. private readonly RepositoryPointcut pointcut;
  19. #endregion
  20. #region Constructors
  21. public RssDataSerializer(IRepositoryService repository, RepositoryPointcut pointcut)
  22. {
  23. this.graph = new VersionGraph();
  24. this.repository = repository;
  25. this.pointcut = pointcut;
  26. }
  27. #endregion
  28. #region IUpdateable Members
  29. public void SetCurrentVersion(int version)
  30. {
  31. this.graph.SetCurrentVersion(version);
  32. }
  33. public void SetDefaultVersion(int version)
  34. {
  35. this.graph.SetDefaultVersion(version);
  36. }
  37. public void AddUpdater(int from, int to, IUpdater updater)
  38. {
  39. this.graph.AddUpdater(from, to, updater);
  40. }
  41. #endregion
  42. #region ISerializer Members
  43. public void Serialize(RssData[] items)
  44. {
  45. var document = new XDocument(new XElement("Data", new XAttribute("version", 1)));
  46. foreach (var item in items)
  47. this.Serialize(document.Root, item);
  48. this.Save(document);
  49. }
  50. public RssData[] Deserialize()
  51. {
  52. var document = this.Load();
  53. var query = from element in document.Root.Elements()
  54. select this.Deserialize(element);
  55. return query.Where(x => x != null).ToArray();
  56. }
  57. #endregion
  58. #region Private Members
  59. [MethodImpl(MethodImplOptions.Synchronized)]
  60. private XDocument Load()
  61. {
  62. try
  63. {
  64. if (!this.repository.Exists(this.pointcut))
  65. return new XDocument(new XElement("Data", new XAttribute("version", 1)));
  66. var updater = new VersionUpdater(this.graph, new XmlVersionReader());
  67. using (var stream = updater.Update(this.repository.GetReadStream(this.pointcut)))
  68. using (var reader = XmlReader.Create(stream, new XmlReaderSettings { CloseInput = true }))
  69. return XDocument.Load(reader, LoadOptions.None);
  70. }
  71. catch (XmlException)
  72. {
  73. if (this.repository.HasCopy(this.pointcut))
  74. {
  75. this.repository.Revert(this.pointcut);
  76. return this.Load();
  77. }
  78. throw;
  79. }
  80. }
  81. [MethodImpl(MethodImplOptions.Synchronized)]
  82. private void Save(XDocument document)
  83. {
  84. using (var stream = this.repository.GetWriteStream(this.pointcut))
  85. using (var writer = new XmlTextWriter(stream, Encoding.UTF8) { Formatting = Formatting.Indented })
  86. document.Save(writer);
  87. }
  88. private void Serialize(XContainer container, RssData data)
  89. {
  90. var result = new XElement("Channel",
  91. new XAttribute("id", data.Channel.ToString()),
  92. new XAttribute("updated", data.Updated.ToString()),
  93. new XElement("Entries"));
  94. foreach (var entry in data.GetEntries())
  95. this.Serialize(result.Element("Entries"), entry);
  96. container.Add(result);
  97. }
  98. private void Serialize(XContainer container, RssEntry entry)
  99. {
  100. var result = new XElement("Entry",
  101. new XAttribute("id", entry.Id.ToString()),
  102. new XAttribute("updated", entry.Updated.ToString()),
  103. new XElement("Location", entry.Location.ToString()),
  104. new XElement("Title", entry.Title),
  105. new XElement("Published", entry.Published),
  106. new XElement("Content", new XCData(entry.Content)),
  107. new XElement("State", Enum.GetName(typeof(RssEntryState), entry.State)),
  108. new XElement("Links"),
  109. new XElement("Files"));
  110. foreach (var link in entry.GetLinks())
  111. this.Serialize(result.Element("Links"), link);
  112. foreach (var file in entry.GetFiles())
  113. this.Serialize(result.Element("Files"), file);
  114. container.Add(result);
  115. }
  116. private void Serialize(XContainer container, RssLink link)
  117. {
  118. var result = new XElement("Link",
  119. new XElement("Location", link.Location.ToString()),
  120. new XElement("State", Enum.GetName(typeof(RssLinkState), link.State == RssLinkState.Analyzing ? RssLinkState.Found : link.State)));
  121. container.Add(result);
  122. }
  123. private void Serialize(XContainer container, RssFile file)
  124. {
  125. var result = new XElement("File",
  126. new XAttribute("id", file.Id.ToString()),
  127. new XElement("Name", file.Name),
  128. new XElement("State", Enum.GetName(typeof(RssFileState), file.State)),
  129. new XElement("Verified", file.Verified == DateTime.MaxValue ? DateTime.MinValue : file.Verified),
  130. new XElement("Resources"));
  131. foreach (var resource in file.GetResources())
  132. this.Serialize(result.Element("Resources"), resource);
  133. container.Add(result);
  134. }
  135. private void Serialize(XContainer container, Resource resource)
  136. {
  137. var result = new XElement("Resource",
  138. new XAttribute("id", resource.Id),
  139. new XElement("Provider", resource.Provider.ToString()),
  140. new XElement("Name", resource.Name),
  141. new XElement("Location", resource.Location.ToString()),
  142. this.SerializeSize(resource.Size));
  143. container.Add(result);
  144. }
  145. private RssData Deserialize(XElement node)
  146. {
  147. var id = new Guid(node.Attribute("id").Value);
  148. var updated = DateTime.Parse(node.Attribute("updated").Value);
  149. var result = new RssData(id) { Updated = updated };
  150. var entries = from entry in node.Element("Entries").Elements("Entry")
  151. select this.Deserialize(entry, result);
  152. foreach (var entry in entries)
  153. result.AddEntry(entry);
  154. return result;
  155. }
  156. private RssEntry Deserialize(XElement node, RssData owner)
  157. {
  158. var id = new Guid(node.Attribute("id").Value);
  159. var updated = DateTime.Parse(node.Attribute("updated").Value);
  160. var location = new Uri(node.Element("Location").Value);
  161. var title = node.Element("Title").Value;
  162. var published = DateTime.Parse(node.Element("Published").Value);
  163. var content = node.Element("Content").Value;
  164. var state = (RssEntryState)Enum.Parse(typeof(RssEntryState), node.Element("State").Value);
  165. var result = new RssEntry(id, owner, location, title, published, content) { State = state, Updated = updated };
  166. var links = from link in node.Element("Links").Elements("Link")
  167. select this.DeserializeLink(link, result);
  168. foreach (var link in links)
  169. result.AddLink(link);
  170. var files = from file in node.Element("Files").Elements("File")
  171. select this.DeserializeFile(file, result);
  172. foreach (var file in files)
  173. result.AddFile(file);
  174. return result;
  175. }
  176. private RssLink DeserializeLink(XElement node, RssEntry owner)
  177. {
  178. var location = new Uri(node.Element("Location").Value);
  179. var state = (RssLinkState)Enum.Parse(typeof(RssLinkState), node.Element("State").Value);
  180. return new RssLink(owner, location) { State = state };
  181. }
  182. private RssFile DeserializeFile(XElement node, RssEntry owner)
  183. {
  184. var id = new Guid(node.Attribute("id").Value);
  185. var name = node.Element("Name").Value;
  186. var state = (RssFileState)Enum.Parse(typeof(RssFileState), node.Element("State").Value);
  187. var verified = DateTime.Parse(node.Element("Verified").Value);
  188. var result = new RssFile(id, owner, name) { State = state, Verified = verified };
  189. var resources = from resource in node.Element("Resources").Elements("Resource")
  190. select this.Deserialize(resource, result);
  191. foreach (var resource in resources)
  192. result.AddResource(resource);
  193. return result;
  194. }
  195. private Resource Deserialize(XElement node, RssFile owner)
  196. {
  197. var id = new Guid(node.Attribute("id").Value);
  198. var provider = new Guid(node.Element("Provider").Value);
  199. var name = node.Element("Name").Value;
  200. var size = this.DeserializeSize(node.Element("Size"));
  201. var location = new Uri(node.Element("Location").Value);
  202. return new Resource(id, provider, name, size, location);
  203. }
  204. private XElement SerializeSize(DataSize size)
  205. {
  206. var result = new XElement("Size",
  207. new XAttribute("mode", Enum.GetName(typeof(DataSizeMode), size.Mode)));
  208. if (size != DataSize.Unknown)
  209. result.Add(size.GetBytes());
  210. return result;
  211. }
  212. private DataSize DeserializeSize(XElement node)
  213. {
  214. var mode = (DataSizeMode)Enum.Parse(typeof(DataSizeMode), node.Attribute("mode").Value);
  215. var value = node.Value;
  216. var result = DataSize.Unknown;
  217. if (!String.IsNullOrEmpty(value))
  218. result = new DataSize(mode, Int64.Parse(value));
  219. return result;
  220. }
  221. #endregion
  222. }
  223. }