PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Web/HttpHandlers/Apml.cs

#
C# | 347 lines | 176 code | 50 blank | 121 comment | 5 complexity | 8d0b10c2ddb4416fa9ba4f1285bb9e15 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. namespace BlogEngine.Core.Web.HttpHandlers
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Web;
  9. using System.Xml;
  10. /// <summary>
  11. /// Based on John Dyer's (http://johndyer.name/) extension.
  12. /// </summary>
  13. public class Apml : IHttpHandler
  14. {
  15. #region Properties
  16. /// <summary>
  17. /// Gets a value indicating whether another request can use the <see cref = "T:System.Web.IHttpHandler"></see> instance.
  18. /// </summary>
  19. /// <value></value>
  20. /// <returns>true if the <see cref = "T:System.Web.IHttpHandler"></see> instance is reusable; otherwise, false.</returns>
  21. public bool IsReusable
  22. {
  23. get
  24. {
  25. return false;
  26. }
  27. }
  28. #endregion
  29. #region Implemented Interfaces
  30. #region IHttpHandler
  31. /// <summary>
  32. /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"></see> interface.
  33. /// </summary>
  34. /// <param name="context">
  35. /// An <see cref="T:System.Web.HttpContext"></see> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.
  36. /// </param>
  37. public void ProcessRequest(HttpContext context)
  38. {
  39. context.Response.ContentType = "text/xml";
  40. WriteApmlDocument(context.Response.OutputStream);
  41. }
  42. #endregion
  43. #endregion
  44. #region Methods
  45. /// <summary>
  46. /// Finds the max.
  47. /// </summary>
  48. /// <param name="dic">The dictionary.</param>
  49. /// <returns>A list of Concept.</returns>
  50. private static IEnumerable<Concept> FindMax(Dictionary<string, Concept> dic)
  51. {
  52. float max = 0;
  53. float max1 = max;
  54. foreach (var concept in dic.Values.Where(concept => concept.Score > max1))
  55. {
  56. max = concept.Score;
  57. }
  58. // reset values as a percentage of the max
  59. var list = dic.Keys.Select(key => new Concept(dic[key].LastUpdated, dic[key].Score / max, key)).ToList();
  60. list.Sort((c1, c2) => c2.Score.CompareTo(c1.Score));
  61. return list;
  62. }
  63. /// <summary>
  64. /// Closes the writer.
  65. /// </summary>
  66. /// <param name="xmlWriter">The XML writer.</param>
  67. private static void CloseWriter(XmlWriter xmlWriter)
  68. {
  69. xmlWriter.WriteEndElement(); // APML
  70. xmlWriter.WriteEndDocument();
  71. xmlWriter.Close();
  72. }
  73. //// modified version of what's happening in the tag cloud
  74. // private Dictionary<string, Concept> CreateCategoryList()
  75. // {
  76. // // get all the tags and count the number of usages
  77. // Dictionary<string, Concept> dic = new Dictionary<string, Concept>();
  78. // foreach (Post post in Post.Posts)
  79. // {
  80. // if (post.Visible)
  81. // {
  82. // foreach (Category cat in post.Categories)
  83. // {
  84. // if (dic.ContainsKey(cat.Title))
  85. // {
  86. // Concept concept = dic[cat.Title];
  87. // concept.Score++;
  88. // if (post.DateModified > concept.LastUpdated)
  89. // concept.LastUpdated = post.DateModified;
  90. // dic[cat.Title] = concept;
  91. // }
  92. // else
  93. // {
  94. // dic[cat.Title] = new Concept(post.DateModified, 1);
  95. // }
  96. // }
  97. // }
  98. // }
  99. // return FindMax(dic);
  100. // }
  101. /// <summary>
  102. /// Creates the link list.
  103. /// </summary>
  104. /// <returns>A dictionary of string, string.</returns>
  105. private static Dictionary<string, string> CreateLinkList()
  106. {
  107. var dic = new Dictionary<string, string>();
  108. foreach (var br in BlogRollItem.BlogRolls)
  109. {
  110. var title = br.Title;
  111. var website = br.BlogUrl.ToString();
  112. dic.Add(title, website);
  113. }
  114. return dic;
  115. }
  116. /// <summary>
  117. /// Creates the tag list.
  118. /// </summary>
  119. /// <returns>A list of concepts.</returns>
  120. private static IEnumerable<Concept> CreateTagList()
  121. {
  122. // get all the tags and count the number of usages
  123. var dic = new Dictionary<string, Concept>();
  124. foreach (var post in Post.Posts)
  125. {
  126. if (!post.IsVisible)
  127. {
  128. continue;
  129. }
  130. foreach (var tag in post.Tags)
  131. {
  132. if (dic.ContainsKey(tag))
  133. {
  134. var concept = dic[tag];
  135. concept.Score++;
  136. if (post.DateModified > concept.LastUpdated)
  137. {
  138. concept.LastUpdated = post.DateModified;
  139. }
  140. dic[tag] = concept;
  141. }
  142. else
  143. {
  144. dic[tag] = new Concept(post.DateModified, 1, tag);
  145. }
  146. }
  147. }
  148. return FindMax(dic);
  149. }
  150. /// <summary>
  151. /// Gets the writer.
  152. /// </summary>
  153. /// <param name="stream">The stream.</param>
  154. /// <returns>An xml writer.</returns>
  155. private static XmlWriter GetWriter(Stream stream)
  156. {
  157. var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true };
  158. var xmlWriter = XmlWriter.Create(stream, settings);
  159. xmlWriter.WriteStartDocument();
  160. xmlWriter.WriteStartElement("APML");
  161. return xmlWriter;
  162. }
  163. /// <summary>
  164. /// The write apml document.
  165. /// </summary>
  166. /// <param name="stream">
  167. /// The stream.
  168. /// </param>
  169. private static void WriteApmlDocument(Stream stream)
  170. {
  171. var writer = GetWriter(stream);
  172. // HEAD
  173. writer.WriteStartElement("Head");
  174. writer.WriteElementString(
  175. "Title", "APML data for " + BlogSettings.Instance.Name + " - " + BlogSettings.Instance.Description);
  176. writer.WriteElementString("Generator", "BlogEngine.NET " + BlogSettings.Instance.Version());
  177. writer.WriteElementString("UserEmail", string.Empty);
  178. writer.WriteElementString("DateCreated", DateTime.Now.ToString());
  179. writer.WriteEndElement(); // Head
  180. // BODY
  181. writer.WriteStartElement("Body");
  182. writer.WriteAttributeString("defaultProfile", "tags");
  183. // tags
  184. writer.WriteStartElement("Profile");
  185. writer.WriteAttributeString("name", "tags");
  186. writer.WriteStartElement("ImplicitData");
  187. writer.WriteStartElement("Concepts");
  188. var tagList = CreateTagList();
  189. foreach (var key in tagList)
  190. {
  191. writer.WriteStartElement("Concept");
  192. writer.WriteAttributeString("key", key.Title);
  193. writer.WriteAttributeString("value", key.Score.ToString());
  194. writer.WriteAttributeString("from", Utils.AbsoluteWebRoot.ToString());
  195. writer.WriteAttributeString("updated", key.LastUpdated.ToString());
  196. writer.WriteEndElement(); // Concept
  197. }
  198. writer.WriteEndElement(); // Concepts
  199. writer.WriteEndElement(); // ImplicitData
  200. writer.WriteEndElement(); // Profile
  201. // categories
  202. // writer.WriteStartElement("Profile");
  203. // writer.WriteAttributeString("name", "categories");
  204. // writer.WriteStartElement("ImplicitData");
  205. // writer.WriteStartElement("Concepts");
  206. // Dictionary<string, Concept> catList = CreateCategoryList();
  207. // foreach (string key in catList.Keys)
  208. // {
  209. // writer.WriteStartElement("Concept");
  210. // writer.WriteAttributeString("key", key);
  211. // writer.WriteAttributeString("value", catList[key].Score.ToString());
  212. // writer.WriteAttributeString("from", Utils.AbsoluteWebRoot.ToString());
  213. // writer.WriteAttributeString("updated", catList[key].LastUpdated.ToString());
  214. // writer.WriteEndElement(); // Concept
  215. // }
  216. // writer.WriteEndElement(); // Concepts
  217. // writer.WriteEndElement(); // ImplicitData
  218. // writer.WriteEndElement(); // Profile
  219. // links
  220. writer.WriteStartElement("Profile");
  221. writer.WriteAttributeString("name", "links");
  222. writer.WriteStartElement("ExplicitData");
  223. writer.WriteStartElement("Concepts");
  224. var links = CreateLinkList();
  225. if (links != null)
  226. {
  227. foreach (var title in links.Keys)
  228. {
  229. var website = links[title];
  230. writer.WriteStartElement("Source");
  231. writer.WriteAttributeString("key", website);
  232. writer.WriteAttributeString("name", title);
  233. writer.WriteAttributeString("value", "1.0");
  234. writer.WriteAttributeString("type", "text/html");
  235. writer.WriteAttributeString("from", Utils.AbsoluteWebRoot.ToString());
  236. writer.WriteAttributeString("updated", DateTime.Now.ToString());
  237. writer.WriteStartElement("Author");
  238. writer.WriteAttributeString("key", title);
  239. writer.WriteAttributeString("value", "1.0");
  240. writer.WriteAttributeString("from", Utils.AbsoluteWebRoot.ToString());
  241. writer.WriteAttributeString("updated", DateTime.Now.ToString());
  242. writer.WriteEndElement(); // Author
  243. writer.WriteEndElement(); // Source
  244. }
  245. }
  246. writer.WriteEndElement(); // Concepts
  247. writer.WriteEndElement(); // ImplicitData
  248. writer.WriteEndElement(); // Profile
  249. writer.WriteEndElement(); // Body
  250. CloseWriter(writer);
  251. }
  252. #endregion
  253. /// <summary>
  254. /// The concept.
  255. /// </summary>
  256. private class Concept
  257. {
  258. #region Constructors and Destructors
  259. /// <summary>
  260. /// Initializes a new instance of the <see cref="Concept"/> class.
  261. /// </summary>
  262. /// <param name="lastUpdated">
  263. /// The last updated.
  264. /// </param>
  265. /// <param name="score">
  266. /// The score.
  267. /// </param>
  268. /// <param name="title">
  269. /// The title.
  270. /// </param>
  271. public Concept(DateTime lastUpdated, float score, string title)
  272. {
  273. this.LastUpdated = lastUpdated;
  274. this.Score = score;
  275. this.Title = title;
  276. }
  277. #endregion
  278. #region Properties
  279. /// <summary>
  280. /// Gets or sets the last updated.
  281. /// </summary>
  282. /// <value>The last updated.</value>
  283. public DateTime LastUpdated { get; set; }
  284. /// <summary>
  285. /// Gets or sets the score.
  286. /// </summary>
  287. /// <value>The score.</value>
  288. public float Score { get; set; }
  289. /// <summary>
  290. /// Gets the title.
  291. /// </summary>
  292. /// <value>The title.</value>
  293. public string Title { get; private set; }
  294. #endregion
  295. }
  296. }
  297. }