/BlogEngine/DotNetSlave.BusinessLogic/API/BlogML/BlogReader.cs
C# | 406 lines | 287 code | 64 blank | 55 comment | 53 complexity | 9a93813964d4848671e61a51c8cf3ca1 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
- namespace BlogEngine.Core.API.BlogML
- {
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using System.Xml;
- using System.Linq;
- using System.Globalization;
-
- using global::BlogML;
- using global::BlogML.Xml;
-
- /// <summary>
- /// Class to validate BlogML data and import it into Blog
- /// </summary>
- public class BlogReader : BaseReader
- {
- #region Constants and Fields
-
- /// <summary>
- /// The xml data.
- /// </summary>
- private string xmlData = string.Empty;
-
- /// <summary>
- /// The category lookup.
- /// </summary>
- private List<Category> categoryLookup = new List<Category>();
-
- private List<BlogMlExtendedPost> blogsExtended = new List<BlogMlExtendedPost>();
-
- #endregion
-
- #region Properties
-
- /// <summary>
- /// imported posts counter
- /// </summary>
- public int PostCount { get; set; }
-
- /// <summary>
- /// Sets BlogML data uploaded and saved as string
- /// </summary>
- public string XmlData
- {
- set
- {
- xmlData = value;
- }
- }
-
- /// <summary>
- /// Gets an XmlReader that converts BlogML data saved as string into XML stream
- /// </summary>
- private XmlTextReader XmlReader
- {
- get
- {
- var byteArray = Encoding.UTF8.GetBytes(this.xmlData);
- var stream = new MemoryStream(byteArray);
- return new XmlTextReader(stream);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- /// <summary>
- /// Imports BlogML file into blog
- /// </summary>
- /// <returns>
- /// True if successful
- /// </returns>
- public override bool Import()
- {
- Message = string.Empty;
- var blog = new BlogMLBlog();
- try
- {
- blog = BlogMLSerializer.Deserialize(XmlReader);
- }
- catch (Exception ex)
- {
- Message = string.Format("BlogReader.Import: BlogML could not load with 2.0 specs. {0}", ex.Message);
- Utils.Log(Message);
- return false;
- }
-
- try
- {
- LoadFromXmlDocument();
-
- LoadBlogCategories(blog);
-
- LoadBlogExtendedPosts(blog);
-
- LoadBlogPosts();
-
- Message = string.Format("Imported {0} new posts", PostCount);
- }
- catch (Exception ex)
- {
- Message = string.Format("BlogReader.Import: {0}", ex.Message);
- Utils.Log(Message);
- return false;
- }
-
- return true;
- }
-
- #endregion
-
- #region Methods
-
- private Dictionary<string, Dictionary<string, Guid>> _substitueGuids;
- private Guid GetGuid(string type, string value)
- {
- value = (value ?? string.Empty).Trim();
-
- // Value might be a GUID, or it could be a simple integer.
-
- if (!Utils.StringIsNullOrWhitespace(value) &&
- value.Length == 36)
- {
- return new Guid(value);
- }
-
- // If we've already retrieved a Guid for a particular type/value, then
- // return the same Guid. This is in case the type/value is referenced by
- // other objects, we would want to use the same Guid to keep the
- // references correct.
-
- if (_substitueGuids == null)
- {
- _substitueGuids = new Dictionary<string, Dictionary<string, Guid>>(StringComparer.OrdinalIgnoreCase);
- }
-
- if (!_substitueGuids.ContainsKey(type))
- _substitueGuids.Add(type, new Dictionary<string, Guid>(StringComparer.OrdinalIgnoreCase));
-
- if (!_substitueGuids[type].ContainsKey(value))
- _substitueGuids[type].Add(value, Guid.NewGuid());
-
- return _substitueGuids[type][value];
- }
-
- private T GetAttributeValue<T>(XmlAttribute attr)
- {
- if (attr == null)
- return default(T);
-
- return (T)Convert.ChangeType(attr.Value, typeof(T));
- }
-
- private DateTime GetDate(XmlAttribute attr)
- {
- string value = GetAttributeValue<string>(attr);
- DateTime defaultDate = DateTime.Now;
-
- DateTime dt = defaultDate;
- if (!Utils.StringIsNullOrWhitespace(value))
- {
- if (!DateTime.TryParseExact(value, "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
- dt = defaultDate;
- }
-
- return dt;
- }
-
- private Uri GetUri(string value)
- {
- Uri uri;
- if (Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out uri))
- return uri;
-
- return null;
- }
-
- /// <summary>
- /// BlogML does not support tags - load directly fro XML
- /// </summary>
- private void LoadFromXmlDocument()
- {
- var doc = new XmlDocument();
- doc.Load(XmlReader);
- var posts = doc.GetElementsByTagName("post");
-
- foreach (XmlNode post in posts)
- {
- var blogX = new BlogMlExtendedPost();
-
- if (post.Attributes != null)
- blogX.PostUrl = GetAttributeValue<string>(post.Attributes["post-url"]);
-
- if (post.ChildNodes.Count <= 0)
- {
- blogsExtended.Add(blogX);
- continue;
- }
-
- foreach (XmlNode child in post.ChildNodes)
- {
- if (child.Name == "tags")
- {
- foreach (XmlNode tag in child.ChildNodes)
- {
- if (tag.Attributes != null)
- {
- if (blogX.Tags == null) blogX.Tags = new StateList<string>();
- blogX.Tags.Add(GetAttributeValue<string>(tag.Attributes["ref"]));
- }
- }
- }
-
- if (child.Name == "comments")
- LoadBlogComments(blogX, child);
-
- if (child.Name == "trackbacks")
- LoadBlogTrackbacks(blogX, child);
- }
- blogsExtended.Add(blogX);
- }
- }
-
- /// <summary>
- /// Lost post comments from xml file
- /// </summary>
- /// <param name="blogX">extended blog</param>
- /// <param name="child">comments xml node</param>
- private void LoadBlogComments(BlogMlExtendedPost blogX, XmlNode child)
- {
- foreach (XmlNode com in child.ChildNodes)
- {
- if(com.Attributes != null)
- {
- var c = new Comment
- {
- Id = GetGuid("comment", GetAttributeValue<string>(com.Attributes["id"])),
- Author = GetAttributeValue<string>(com.Attributes["user-name"]),
- Email = GetAttributeValue<string>(com.Attributes["user-email"]),
- ParentId = GetGuid("comment", GetAttributeValue<string>(com.Attributes["parentid"])),
- IP = GetAttributeValue<string>(com.Attributes["user-ip"]),
- DateCreated = GetDate(com.Attributes["date-created"])
- };
-
- if (!string.IsNullOrEmpty(GetAttributeValue<string>(com.Attributes["user-url"])))
- c.Website = GetUri(GetAttributeValue<string>(com.Attributes["user-url"]));
-
- c.IsApproved = GetAttributeValue<bool>(com.Attributes["approved"]);
-
- foreach (XmlNode comNode in com.ChildNodes)
- {
- if(comNode.Name == "content")
- {
- c.Content = comNode.InnerText;
- }
- }
- if(blogX.Comments == null) blogX.Comments = new List<Comment>();
- blogX.Comments.Add(c);
- }
- }
- }
-
- /// <summary>
- /// Lost post trackbacks and pingbacks from xml file
- /// </summary>
- /// <param name="blogX">extended blog</param>
- /// <param name="child">comments xml node</param>
- private void LoadBlogTrackbacks(BlogMlExtendedPost blogX, XmlNode child)
- {
- foreach (XmlNode com in child.ChildNodes)
- {
- if (com.Attributes != null)
- {
- var c = new Comment
- {
- Id = GetGuid("comment", GetAttributeValue<string>(com.Attributes["id"])),
- IP = "127.0.0.1",
- IsApproved = GetAttributeValue<bool>(com.Attributes["approved"]),
- DateCreated = GetDate(com.Attributes["date-created"])
- };
-
- if (!string.IsNullOrEmpty(GetAttributeValue<string>(com.Attributes["url"])))
- c.Website = GetUri(GetAttributeValue<string>(com.Attributes["url"]));
-
- foreach (XmlNode comNode in com.ChildNodes)
- {
- if (comNode.Name == "title")
- {
- c.Content = comNode.InnerText;
- }
- }
-
- c.Email = c.Content.ToLowerInvariant().Contains("pingback") ? "pingback" : "trackback";
- c.Author = c.Email;
-
- if (blogX.Comments == null) blogX.Comments = new List<Comment>();
- blogX.Comments.Add(c);
- }
- }
- }
-
- /// <summary>
- /// Load blog categories
- /// </summary>
- /// <param name="blog">BlogML blog</param>
- private void LoadBlogCategories(BlogMLBlog blog)
- {
- foreach (var cat in blog.Categories)
- {
- var c = new Category
- {
- Id = GetGuid("category", cat.ID),
- Title = cat.Title,
- Description = string.IsNullOrEmpty(cat.Description) ? "" : cat.Description,
- DateCreated = cat.DateCreated,
- DateModified = cat.DateModified
- };
-
- if (!string.IsNullOrEmpty(cat.ParentRef) && cat.ParentRef != "0")
- c.Parent = GetGuid("category", cat.ParentRef);
-
- categoryLookup.Add(c);
-
- if (Category.GetCategory(c.Id) == null)
- {
- c.Save();
- }
- }
- }
-
- /// <summary>
- /// extended post has all BlogML plus fields not supported
- /// by BlogML like tags. here we assign BlogML post
- /// to extended matching on post URL
- /// </summary>
- /// <param name="blog">BlogML blog</param>
- private void LoadBlogExtendedPosts(BlogMLBlog blog)
- {
- foreach (var post in blog.Posts)
- {
- if (post.PostType == BlogPostTypes.Normal)
- {
- BlogMLPost p = post;
- blogsExtended.Where(b => b.PostUrl == p.PostUrl).FirstOrDefault().BlogPost = post;
- }
- }
- }
-
- /// <summary>
- /// Loads the blog posts.
- /// </summary>
- private void LoadBlogPosts()
- {
- var bi = new BlogImporter();
- Utils.Log("BlogReader.LoadBlogPosts: Start importing posts");
-
- foreach (BlogMlExtendedPost extPost in blogsExtended)
- {
- try
- {
- BlogMlExtendedPost post = extPost;
-
- if (extPost.BlogPost.Categories.Count > 0)
- {
- for (var i = 0; i < extPost.BlogPost.Categories.Count; i++)
- {
- int i2 = i;
- var cId = GetGuid("category", post.BlogPost.Categories[i2].Ref);
-
- foreach (var category in categoryLookup)
- {
- if (category.Id == cId)
- {
- if (extPost.Categories == null)
- extPost.Categories = new StateList<Category>();
-
- extPost.Categories.Add(category);
- }
- }
- }
- }
-
- if (!string.IsNullOrEmpty(bi.AddPost(extPost)))
- {
- PostCount++;
- }
- else
- {
- Utils.Log("Post '{0}' has been skipped" + extPost.BlogPost.Title);
- }
- }
- catch (Exception ex)
- {
- Utils.Log("BlogReader.LoadBlogPosts: " + ex.Message);
- }
- }
- bi.ForceReload();
- Utils.Log(string.Format("BlogReader.LoadBlogPosts: Completed importing {0} posts", PostCount));
- }
-
- #endregion
- }
- }