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