context: #region License
  /* Copyright (C) 2006-2009 Cristian Libardo
   *
   * This is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2.1 of
   * the License, or (at your option) any later version.
   *
   * This software is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this software; if not, write to the Free
   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   */
  #endregion
  
  using Castle.DynamicProxy;
  using N2.Collections;
  using N2.Definitions;
  using N2.Details;
  using N2.Engine;
  using N2.Persistence;
  using N2.Persistence.Proxying;
  using N2.Web;
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Linq;
  using System.Reflection;
  using System.Runtime.CompilerServices;
  using System.Security.Principal;
  using System.Text;
  using System.Web;
  
  namespace N2
  {
  	/// <summary>
  	/// The base of N2 content items. All content pages and data items are 
  	/// derived from this item. During the initialization phase the CMS looks 
  	/// for classes deriving from <see cref="ContentItem"/> marked with the 
  	/// <see cref="DefinitionAttribute"/> and makes them available for
  	/// editing and storage in the database.
  	/// </summary>
  	/// <example>
  	/// // Since the class is inheriting <see cref="ContentItem"/> it's 
  	/// // recognized by the CMS and made available for editing.
  	/// [PageDefinition(TemplateUrl = "~/Path/To/My/Template.aspx")]
  	/// public class MyPage : N2.ContentItem
  	/// {
  	///	}
  	/// </example>
  	/// <remarks>
  	/// Note that the class name (e.g. MyPage) is used as discriminator when
  	/// retrieving items from database storage. If you change the class name 
  	/// you should manually change the discriminator in the database or set the 
  	/// name of the definition attribute, e.g. [Definition("Title", "OldClassName")]
  	/// </remarks>
  	[Serializable, DebuggerDisplay("{TypeName, nq} #{ID}, Name = {Name}")]
  	[DynamicTemplate]
  	[SiblingInsertion(SortBy.CurrentOrder)]
  	[SortChildren(SortBy.CurrentOrder)]
  	[SyncChildCollectionState(syncEnabled: true)]
  #pragma warning disable 612, 618
  	public abstract class ContentItem : INode,
  #pragma warning restore 612, 618
   IComparable,
  		IComparable<ContentItem>,
  		ICloneable,
  		IInjectable<IUrlParser>,
  		IUpdatable<ContentItem>,
  		IInterceptableType,
  		INameable,
  		IPlaceable
  	{
  		#region Private Fields
  		private int id;
  		private string title;
  		private string name;
  		private string zoneName;
  		private string templateKey;
  		private int? translationKey;
  		private ContentItem parent = null;
  		private DateTime created;
  		private DateTime updated;
  		private DateTime? published = N2.Utility.CurrentTime();
  		private DateTime? expires = null;
  		private int sortOrder;
  		private string url = null;
  		private bool visible = true;
  		private ContentRelation versionOf;
  		private string savedBy;
  		private IList<Security.AuthorizedRole> authorizedRoles = null;
  		private IContentItemList<ContentItem> children = new ItemList<ContentItem>();
  		private IContentList<ContentDetail> details = new ContentList<ContentDetail>();
  		private IContentList<DetailCollection> detailCollections = new DetailCollectionList();
  		[NonSerialized]
  		private IUrlParser urlParser;
  		private string ancestralTrail;
  		private int versionIndex;
  		private ContentState state = ContentState.None;
  		private CollectionState childState = CollectionState.Unknown;
  		private N2.Security.Permission alteredPermissions = N2.Security.Permission.None;
  		private int? hashCode;
  		#endregion
  
  		#region Constructor
  		/// <summary>Creates a new instance of the ContentItem.</summary>
  		protected ContentItem()
  		{
  			var currentTime = Utility.CurrentTime();
  			created = currentTime;
  			updated = currentTime;
  			published = currentTime;
  		}
  		#endregion
  
  		#region Persisted Properties
  		/// <summary>Gets or sets item ID.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual int ID
  		{
  			get { return id; }
  			set { id = value; }
  		}
  
  		/// <summary>Gets or sets this item's parent. This can be null for root items and previous versions but should be another page in other situations.</summary>
  		[DisplayableAnchor, NonInterceptable]
  		public virtual ContentItem Parent
  		{
  			get { return parent; }
  			set { parent = value; }
  		}
  
  		/// <summary>Gets or sets the item's title. This is used in edit mode and probably in a custom implementation.</summary>
  		[DisplayableHeading(1), NonInterceptable]
  		public virtual string Title
  		{
  			get { return title; }
  			set { title = value; }
  		}
  
  		private static char[] invalidCharacters = new char[] { '%', '?', '&', '/', ':' };
  		/// <summary>Gets or sets the item's name. This is used to compute the item's url and can be used to uniquely identify the item among other items on the same level.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual string Name
  		{
  			get
  			{
  				return name ?? (ID > 0 ? ID.ToString() : null);
  			}
  			set
  			{
  				//if (value != null && value.IndexOfAny(invalidCharacters) >= 0) throw new N2Exception("Invalid characters in name, '%', '?', '&', '/', ':', '+', '.' not allowed.");
  				if (string.IsNullOrEmpty(value))
  					name = null;
  				else
  					name = value;
  				url = null;
  			}
  		}
  
  		/// <summary>Gets or sets zone name which is associated with data items and their placement on a page.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual string ZoneName
  		{
  			get { return zoneName; }
  			set { zoneName = value; }
  		}
  
  		/// <summary>Gets or sets the sub-definition name of this item.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual string TemplateKey
  		{
  			get { return templateKey; }
  			set { templateKey = value; }
  		}
  
  		/// <summary>A key shared by translations of an item. It's used to find translations and associate items as translations.</summary>
  		[NonInterceptable]
  		public virtual int? TranslationKey
  		{
  			get { return translationKey; }
  			set { translationKey = value; }
  		}
  
  		/// <summary>Gets or sets when this item was initially created.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual DateTime Created
  		{
  			get { return created; }
  			set { created = value; }
  		}
  
  		/// <summary>Gets or sets the date this item was updated.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual DateTime Updated
  		{
  			get { return updated; }
  			set { updated = value; }
  		}
  
  		/// <summary>Gets or sets the publish date of this item.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual DateTime? Published
  		{
  			get { return published; }
  			set { published = value; }
  		}
  
  		/// <summary>Gets or sets the expiration date of this item.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual DateTime? Expires
  		{
  			get { return expires; }
  			set { expires = value != DateTime.MinValue ? value : null; }
  		}
  
  		/// <summary>Gets or sets the sort order of this item.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual int SortOrder
  		{
  			get { return sortOrder; }
  			set { sortOrder = value; }
  		}
  
  		/// <summary>Gets or sets whether this item is visible. This is normally used to control its visibility in the site map provider.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual bool Visible
  		{
  			get { return visible; }
  			set { visible = value; }
  		}
  
  		/// <summary>Gets or sets the published version of this item. If this value is not null then this item is a previous version of the item specified by VersionOf.</summary>
  		[NonInterceptable]
  		public virtual ContentRelation VersionOf
  		{
  			get { return versionOf ?? (versionOf = new ContentRelation()); }
  			set
  			{
  				//if (versionOf != null && value != null)
  				//    value.ValueAccessor = versionOf.ValueAccessor;
  				versionOf = value;
  			}
  		}
  
  		/// <summary>Gets or sets the name of the identity who saved this item.</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual string SavedBy
  		{
  			get { return savedBy; }
  			set { savedBy = value; }
  		}
  
  		/// <summary>Gets or sets the details collection. These are usually accessed using the e.g. item["Detailname"]. This is a place to store content data.</summary>
  		[NonInterceptable]
  		public virtual IContentList<ContentDetail> Details
  		{
  			get { return details; }
  			set { details = value; }
  		}
  
  		/// <summary>Gets or sets the details collection collection. These are details grouped into a collection.</summary>
  		[NonInterceptable]
  		public virtual IContentList<DetailCollection> DetailCollections
  		{
  			get
  			{
  				var enclosed = detailCollections as IEncolsedComponent;
  				if (enclosed != null && enclosed.EnclosingItem == null)
  					enclosed.EnclosingItem = this;
  				return detailCollections;
  			}
  			set { detailCollections = value; }
  		}
  
  		/// <summary>Gets or sets all a collection of child items of this item ignoring permissions. If you want the children the current user has permission to use <see cref="GetChildPagesUnfiltered()"/> and <see cref="GetChildPartsUnfiltered()" /> instead.</summary>
  		[NonInterceptable]
  		public virtual IContentItemList<ContentItem> Children
  		{
  			get { return children; }
  			set { children = value; }
  		}
  
  		/// <summary>Represents the trail of id's uptil the current item e.g. "/1/10/14/". The current item id is the last item in the ancestral trail.</summary>
  		[NonInterceptable]
  		public virtual string AncestralTrail
  		{
  			get { return ancestralTrail; }
  			set { ancestralTrail = value; }
  		}
  
  		/// <summary>The version number of this item</summary>
  		[DisplayableLiteral, NonInterceptable]
  		public virtual int VersionIndex
  		{
  			get { return versionIndex; }
  			set { versionIndex = value; }
  		}
  
  		[DisplayableLiteral, NonInterceptable]
  		public virtual ContentState State
  		{
  			get { return state; }
  			set { state = value; }
  		}
  
  		[DisplayableLiteral, NonInterceptable]
  		public CollectionState ChildState
  		{
  			get { return childState; }
  			set { childState = value; }
  		}
  
  		[DisplayableLiteral, NonInterceptable]
  		public virtual N2.Security.Permission AlteredPermissions
  		{
  			get { return alteredPermissions; }
  			set { alteredPermissions = value; }
  		}
  		#endregion
  
  		#region Generated Properties
  		/// <summary>The default file extension for this content item, e.g. ".aspx".</summary>
  		[NonInterceptable]
  		public virtual string Extension
  		{
  			get { return Web.Url.DefaultExtension; }
  		}
  
  		/// <summary>Gets whether this item is a page. This is used for and site map purposes.</summary>
  		[NonInterceptable]
  		public virtual bool IsPage
  		{
  			get { return Definitions.Static.DefinitionMap.Instance.GetOrCreateDefinition(this).IsPage; }
  		}
  
  		/// <summary>Gets the public url to this item. This is computed by walking the parent path and prepending their names to the url.</summary>
  		[DisplayableAnchor, NonInterceptable]
  		public virtual string Url
  		{
  			get
  			{
  				if (url == null)
  				{
  					if (urlParser != null)
  						url = urlParser.BuildUrl(this);
  					else
  						url = FindPath(PathData.DefaultAction).GetRewrittenUrl();
  				}
  				return url;
  			}
  		}
  
  		/// <summary>Gets the template that handle the presentation of this content item. For non page items (IsPage) this can be a user control (ascx).</summary>
  		[NonInterceptable]
  		public virtual string TemplateUrl
  		{
  
gt: 			get { return "~/Default.aspx"; }