/// <summary>
        /// This method is called just before a node is updated by the repository.
        /// </summary>
        /// <param name="context">The <see cref="IMansionContext"/>.</param>
        /// <param name="node">The node which will be modified.</param>
        /// <param name="modifiedProperties">The updated properties of the node.</param>
        protected override void DoBeforeUpdate(IMansionContext context, Node node, IPropertyBag modifiedProperties)
        {
            // get the variables
            string currentTheme;
            var hasCurrentTheme = node.TryGet(context, "theme", out currentTheme) && !string.IsNullOrEmpty(currentTheme);
            string newTheme;
            var hasNewTheme = modifiedProperties.TryGet(context, "theme", out newTheme) && !string.IsNullOrEmpty(newTheme);

            // do nothing when the page does not have a theme yet
            if (!hasCurrentTheme)
                return;

            // retrieve the schema of the current theme
            var currentThemeSchema = ColumnSchema.GetSchema(context, currentTheme);

            // retrieve the blocks of this page
            var repository = context.Repository;
            var blockNodeset = repository.Retrieve(context, repository.ParseQuery(context, new PropertyBag
                                                                                           {
                                                                                           	{"baseType", "Block"},
                                                                                           	{"parentSource", node}
                                                                                           }));

            // check if a new theme is selected
            if (hasNewTheme)
            {
                // retrieve the schema of the new theme
                var newThemeSchema = ColumnSchema.GetSchema(context, newTheme);

                // loop through the blocks to find obsolete ones
                foreach (var blockNode in blockNodeset.Nodes)
                {
                    // get the column of this block
                    var column = blockNode.Get<string>(context, "column");

                    // check if this block lived in the old theme
                    if (!currentThemeSchema.ContainsColumn(column))
                        continue;

                    // check if the column exists in the new theme as well
                    if (newThemeSchema.ContainsColumn(column))
                        continue;

                    // block is obsolete delete it
                    repository.Delete(context, blockNode.Pointer);
                }
            }
            else
            {
                // theme is removed, delete all the theme blocks
                foreach (var blockNode in blockNodeset.Nodes.Where(candidate => currentThemeSchema.ContainsColumn(candidate.Get<string>(context, "column"))))
                    repository.Delete(context, blockNode.Pointer);
            }

            base.DoBeforeUpdate(context, node, modifiedProperties);
        }
        /// <summary>
        /// Generates an URL for the <paramref name="node"/>.
        /// </summary>
        /// <param name="context">The <see cref="IMansionWebContext"/>.</param>
        /// <param name="node">The <see cref="Node"/> for which to generate the URL.</param>
        /// <param name="nodeType">The <see cref="ITypeDefinition"/> of the node.</param>
        /// <param name="url">The <see cref="Url"/> which to use to build the url.</param>
        protected override void DoGenerate(IMansionWebContext context, Node node, ITypeDefinition nodeType, Url url)
        {
            // check if the site node has a prefered host header, or pick the first hostheader
            string preferedHostheader;
            String hostheaderString;
            if (node.TryGet(context, "preferedHostheader", out preferedHostheader) && !string.IsNullOrEmpty(preferedHostheader))
                url.HostName = preferedHostheader;
            else if (node.TryGet(context, "hostheaders", out hostheaderString))
            {
                var hostheaders = hostheaderString.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList();

                // if there are not hostheaders set or the current hostheader is in the hostheaders dont change the host
                if (hostheaders.Count == 0 || hostheaders.Contains(url.HostName, StringComparer.OrdinalIgnoreCase))
                    return;

                // set the new hostheader
                url.HostName = hostheaders[0];
            }
        }
        /// <summary>
        /// This method is called just before a node is created by the repository.
        /// </summary>
        /// <param name="context">The <see cref="IMansionContext"/>.</param>
        /// <param name="parent">The parent node to which the new child will be added.</param>
        /// <param name="newProperties">The new properties of the node.</param>
        protected override void DoBeforeCreate(IMansionContext context, Node parent, IPropertyBag newProperties)
        {
            // check if the layout is set
            string layout;
            if (newProperties.TryGet(context, "layout", out layout))
                return;
            if (!parent.TryGet(context, "layout", out layout))
                layout = "OneColumnLayout";

            // set the layout
            newProperties.TrySet("layout", layout);
        }
        /// <summary>
        /// This method is called just before a node is updated by the repository.
        /// </summary>
        /// <param name="context">The <see cref="IMansionContext"/>.</param>
        /// <param name="node">The node which will be modified.</param>
        /// <param name="modifiedProperties">The updated properties of the node.</param>
        protected override void DoBeforeUpdate(IMansionContext context, Node node, IPropertyBag modifiedProperties)
        {
            // check if the layout was not modified
            string newLayoutName;
            if (!modifiedProperties.TryGet(context, "layout", out newLayoutName))
                return;

            // check if there was no old layout
            string oldLayoutName;
            if (!node.TryGet(context, "layout", out oldLayoutName))
                return;

            // get the schemas
            var newColumnSchema = ColumnSchema.GetSchema(context, newLayoutName);
            var oldColumnSchema = ColumnSchema.GetSchema(context, oldLayoutName);

            // retrieve the blocks of this page
            var repository = context.Repository;
            var blockNodeset = repository.Retrieve(context, repository.ParseQuery(context, new PropertyBag
                                                                                           {
                                                                                           	{"baseType", "Block"},
                                                                                           	{"parentSource", node}
                                                                                           }));

            // loop through all the nodes
            foreach (var blockNode in blockNodeset.Nodes)
            {
                // check if this block was not in a column of the old schema so it wont have to move to the new schema
                var columnName = blockNode.Get<string>(context, "column");
                if (!oldColumnSchema.ContainsColumn(columnName))
                    continue;

                // check if the column is in the new schema as well so it wont have to move
                if (newColumnSchema.ContainsColumn(columnName))
                    continue;

                // move the block to the default column
                repository.Update(context, blockNode, new PropertyBag
                                                      {
                                                      	{"column", newColumnSchema.DefaultColumn}
                                                      });
            }
        }
        /// <summary>
        /// This method is called just after a node is created by the repository.
        /// </summary>
        /// <param name="context">The <see cref="IMansionContext"/>.</param>
        /// <param name="parent">The parent node to which the new child was be added.</param>
        /// <param name="node">The created node.</param>
        /// <param name="newProperties">The properties from which the <paramref name="node"/> was constructed.</param>
        protected override void DoAfterCreate(IMansionContext context, Node parent, Node node, IPropertyBag newProperties)
        {
            // get the layout schema
            string layoutName;
            if (!node.TryGet(context, "layout", out layoutName))
                throw new InvalidOperationException(string.Format("Template page {0} ({1}) does not have a layout", node.Pointer.PathString, node.Pointer.PointerString));
            var layoutSchema = ColumnSchema.GetSchema(context, layoutName);

            // add the content detail block to the primary column
            context.Repository.Create(context, node, new PropertyBag
                                                     {
                                                     	{"name", "Content Detail Block"},
                                                     	{"type", "ContentDetailBlock"},
                                                     	{"approved", true},
                                                     	{"column", layoutSchema.DefaultColumn}
                                                     });

            // invoke base
            base.DoAfterCreate(context, parent, node, newProperties);
        }
            /// <summary>
            /// Creates a leaf from the <paramref name="navigationNode"/>
            /// </summary>
            /// <param name="context"></param>
            /// <param name="navigationNode"></param>
            /// <param name="parentLeaf"></param>
            /// <returns></returns>
            public static Leaf Create(IMansionContext context, Node navigationNode, Leaf parentLeaf = null)
            {
                // validate arguments
                if (context == null)
                    throw new ArgumentNullException("context");
                if (navigationNode == null)
                    throw new ArgumentNullException("navigationNode");

                // if the node does not have a targetGuid set then it does not have a target node
                Guid targetGuid;
                if (!navigationNode.TryGet(context, "targetGuid", out targetGuid) || targetGuid == Guid.NewGuid())
                    return new Leaf(navigationNode, parentLeaf);

                // retrieve the target node
                var repository = context.Repository;
                var targetNode = repository.RetrieveSingleNode(context, new PropertyBag {{"guid", targetGuid}});

                if (targetNode == null)
                    return null;

                // return the leaf with target node
                return new Leaf(navigationNode, parentLeaf, targetNode);
            }