PageRenderTime 33ms CodeModel.GetById 10ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Category.cs

#
C# | 388 lines | 210 code | 52 blank | 126 comment | 23 complexity | 3c7cbcb3f2b7d4d163ba76bd6a40d79d MD5 | raw file
  1namespace BlogEngine.Core
  2{
  3    using System;
  4    using System.Collections.Generic;
  5    using System.Linq;
  6    using System.Web;
  7
  8    using BlogEngine.Core.Providers;
  9
 10    /// <summary>
 11    /// Categories are a way to organize posts. 
 12    ///     A post can be in multiple categories.
 13    /// </summary>
 14    [Serializable]
 15    public class Category : BusinessBase<Category, Guid>, IComparable<Category>
 16    {
 17        #region Constants and Fields
 18
 19        /// <summary>
 20        ///     The sync root.
 21        /// </summary>
 22        private static readonly object SyncRoot = new object();
 23
 24        /// <summary>
 25        ///     The categories.
 26        /// </summary>
 27        private static Dictionary<Guid, List<Category>> categories;
 28
 29        /// <summary>
 30        ///     The description.
 31        /// </summary>
 32        private string description;
 33
 34        /// <summary>
 35        ///     The parent.
 36        /// </summary>
 37        private Guid? parent;
 38
 39        /// <summary>
 40        ///     The title.
 41        /// </summary>
 42        private string title;
 43
 44        #endregion
 45
 46        #region Constructors and Destructors
 47
 48        /// <summary>
 49        /// Initializes static members of the <see cref="Category"/> class. 
 50        /// </summary>
 51        static Category()
 52        {
 53            Blog.Saved += (s, e) =>
 54            {
 55                if (e.Action == SaveAction.Delete)
 56                {
 57                    Blog blog = s as Blog;
 58                    if (blog != null)
 59                    {
 60                        // remove deleted blog from static 'categories'
 61
 62                        if (categories != null && categories.ContainsKey(blog.Id))
 63                            categories.Remove(blog.Id);
 64                    }
 65                }
 66            };
 67        }
 68
 69        /// <summary>
 70        ///     Initializes a new instance of the <see cref = "Category" /> class.
 71        /// </summary>
 72        public Category()
 73        {
 74            this.Id = Guid.NewGuid();
 75        }
 76
 77        /// <summary>
 78        /// Initializes a new instance of the <see cref="Category"/> class.
 79        ///     The category.
 80        /// </summary>
 81        /// <param name="title">
 82        /// The title.
 83        /// </param>
 84        /// <param name="description">
 85        /// The description.
 86        /// </param>
 87        public Category(string title, string description)
 88        {
 89            this.Id = Guid.NewGuid();
 90            this.title = title;
 91            this.description = description;
 92            this.Parent = null;
 93        }
 94
 95        #endregion
 96
 97        #region Properties
 98
 99        /// <summary>
100        ///     Gets an unsorted list of all Categories.
101        /// </summary>
102        /// <value>The categories.</value>
103        public static List<Category> Categories
104        {
105            get
106            {
107                Blog blog = Blog.CurrentInstance;
108
109                if (categories == null || !categories.ContainsKey(blog.Id))
110                {
111                    lock (SyncRoot)
112                    {
113                        if (categories == null || !categories.ContainsKey(blog.Id))
114                        {
115                            if (categories == null)
116                                categories = new Dictionary<Guid, List<Category>>();
117
118                            categories[blog.Id] = BlogService.FillCategories();
119                            categories[blog.Id].Sort();
120                        }
121                    }
122                }
123
124                return categories[blog.Id];
125            }
126        }
127
128        /// <summary>
129        ///     Gets the absolute link to the page displaying all posts for this category.
130        /// </summary>
131        /// <value>The absolute link.</value>
132        public Uri AbsoluteLink
133        {
134            get
135            {
136                return Utils.ConvertToAbsolute(this.RelativeLink);
137            }
138        }
139
140        /// <summary>
141        ///     Gets or sets the Description of the object.
142        /// </summary>
143        /// <value>The description.</value>
144        public string Description
145        {
146            get
147            {
148                return this.description;
149            }
150
151            set
152            {
153                base.SetValue("Description", value, ref this.description);
154            }
155        }
156
157        /// <summary>
158        ///     Gets the absolute link to the feed for this category's posts.
159        /// </summary>
160        /// <value>The feed absolute link.</value>
161        public Uri FeedAbsoluteLink
162        {
163            get
164            {
165                return Utils.ConvertToAbsolute(this.FeedRelativeLink);
166            }
167        }
168
169        /// <summary>
170        ///     Gets the relative link to the feed for this category's posts.
171        /// </summary>
172        /// <value>The feed relative link.</value>
173        public string FeedRelativeLink
174        {
175            get
176            {
177                return string.Format(
178                    "{0}category/feed/{1}{2}",
179                    Utils.RelativeWebRoot,
180                    Utils.RemoveIllegalCharacters(this.Title),
181                    BlogConfig.FileExtension);
182            }
183        }
184
185        /// <summary>
186        ///     Gets or sets the Parent ID of the object
187        /// </summary>
188        /// <value>The parent.</value>
189        public Guid? Parent
190        {
191            get
192            {
193                return this.parent;
194            }
195
196            set
197            {
198                base.SetValue("Parent", value, ref this.parent);
199            }
200        }
201
202        /// <summary>
203        ///     Gets all posts in this category.
204        /// </summary>
205        /// <value>The posts.</value>
206        public List<Post> Posts
207        {
208            get
209            {
210                return Post.GetPostsByCategory(this.Id);
211            }
212        }
213
214        /// <summary>
215        ///     Gets the relative link to the page displaying all posts for this category.
216        /// </summary>
217        /// <value>The relative link.</value>
218        public string RelativeLink
219        {
220            get
221            {
222                return Utils.RelativeWebRoot + "category/" + Utils.RemoveIllegalCharacters(this.Title) +
223                       BlogConfig.FileExtension;
224            }
225        }
226
227        /// <summary>
228        ///     Gets or sets the Title or the object.
229        /// </summary>
230        /// <value>The title.</value>
231        public string Title
232        {
233            get
234            {
235                return this.title;
236            }
237
238            set
239            {
240                base.SetValue("Title", value, ref this.title);
241            }
242        }
243
244        #endregion
245
246        #region Public Methods
247
248        /// <summary>
249        /// Returns a category based on the specified id.
250        /// </summary>
251        /// <param name="id">
252        /// The category id.
253        /// </param>
254        /// <returns>
255        /// The category.
256        /// </returns>
257        public static Category GetCategory(Guid id)
258        {
259            return Categories.FirstOrDefault(category => category.Id == id);
260        }
261
262        /// <summary>
263        /// Gets the full title with Parent names included
264        /// </summary>
265        /// <returns>
266        /// The complete title.
267        /// </returns>
268        public string CompleteTitle()
269        {
270            return this.parent == null
271                       ? this.title
272                       : string.Format("{0} - {1}", GetCategory((Guid)this.parent).CompleteTitle(), this.title);
273        }
274
275
276        /// <summary>
277        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
278        /// </summary>
279        /// <returns>
280        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
281        /// </returns>
282        public override string ToString()
283        {
284            return this.CompleteTitle();
285        }
286
287        #endregion
288
289        #region Implemented Interfaces
290
291        #region IComparable<Category>
292
293        /// <summary>
294        /// Compares the current object with another object of the same type.
295        /// </summary>
296        /// <param name="other">
297        /// An object to compare with this object.
298        /// </param>
299        /// <returns>
300        /// A 32-bit signed integer that indicates the relative order of the objects being compared. 
301        ///     The return value has the following meanings: Value Meaning Less than zero This object is 
302        ///     less than the other parameter.Zero This object is equal to other. Greater than zero This object is greater than other.
303        /// </returns>
304        public int CompareTo(Category other)
305        {
306            return this.CompleteTitle().CompareTo(other.CompleteTitle());
307        }
308
309        #endregion
310
311        #endregion
312
313        #region Methods
314
315        /// <summary>
316        /// Deletes the object from the data store.
317        /// </summary>
318        protected override void DataDelete()
319        {
320            if (this.Deleted)
321            {
322                foreach (var c in
323                    Categories.ToArray().Where(
324                        c => !c.Id.Equals(this.Id) && c.Parent.HasValue && c.Parent.Value.Equals(this.Id)))
325                {
326                    c.Parent = null;
327                    c.Save();
328                }
329
330                BlogService.DeleteCategory(this);
331            }
332
333            if (Categories.Contains(this))
334            {
335                Categories.Remove(this);
336            }
337
338            this.Dispose();
339        }
340
341        /// <summary>
342        /// Inserts a new object to the data store.
343        /// </summary>
344        protected override void DataInsert()
345        {
346            if (this.New)
347            {
348                BlogService.InsertCategory(this);
349            }
350        }
351
352        /// <summary>
353        /// Retrieves the object from the data store and populates it.
354        /// </summary>
355        /// <param name="id">
356        /// The unique identifier of the object.
357        /// </param>
358        /// <returns>
359        /// True if the object exists and is being populated successfully
360        /// </returns>
361        protected override Category DataSelect(Guid id)
362        {
363            return BlogService.SelectCategory(id);
364        }
365
366        /// <summary>
367        /// Updates the object in its data store.
368        /// </summary>
369        protected override void DataUpdate()
370        {
371            if (this.IsChanged)
372            {
373                BlogService.UpdateCategory(this);
374            }
375        }
376
377        /// <summary>
378        /// Reinforces the business rules by adding additional rules to the
379        ///     broken rules collection.
380        /// </summary>
381        protected override void ValidationRules()
382        {
383            this.AddRule("Title", "Title must be set", string.IsNullOrEmpty(this.Title));
384        }
385
386        #endregion
387    }
388}