//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ /* * SiteMapNode class definition * * Copyright (c) 2002 Microsoft Corporation */ namespace System.Web { using System; using System.Configuration.Provider; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Resources; using System.Security.Permissions; using System.Web.Configuration; using System.Web.Compilation; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.Util; /// /// /// public class SiteMapNode : ICloneable, IHierarchyData, INavigateUIData { private static readonly string _siteMapNodeType = typeof(SiteMapNode).Name; private SiteMapProvider _provider; private bool _readonly; private bool _parentNodeSet; private bool _childNodesSet; private VirtualPath _virtualPath; private string _title; private string _description; private string _url; private string _key; private string _resourceKey; private IList _roles; private NameValueCollection _attributes; private NameValueCollection _resourceKeys; private SiteMapNode _parentNode; private SiteMapNodeCollection _childNodes; public SiteMapNode(SiteMapProvider provider, string key) : this(provider, key, null, null, null, null, null, null, null) { } public SiteMapNode(SiteMapProvider provider, string key, string url) : this(provider, key, url, null, null, null, null, null, null) { } public SiteMapNode(SiteMapProvider provider, string key, string url, string title) : this(provider, key, url, title, null, null, null, null, null) { } public SiteMapNode(SiteMapProvider provider, string key, string url, string title, string description) : this(provider, key, url, title, description, null, null, null, null) { } public SiteMapNode(SiteMapProvider provider, string key, string url, string title, string description, IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys, string implicitResourceKey) { _provider = provider; _title = title; _description = description; _roles = roles; _attributes = attributes; _key = key; _resourceKeys = explicitResourceKeys; _resourceKey = implicitResourceKey; if (url != null) { _url = url.Trim(); } _virtualPath = CreateVirtualPathFromUrl(_url); if (_key == null) { throw new ArgumentNullException("key"); } if (_provider == null) { throw new ArgumentNullException("provider"); } } protected NameValueCollection Attributes { get { return _attributes; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Attributes")); } _attributes = value; } } // Access custom attributes. public virtual string this[string key] { get { string text = null; if (_attributes != null) { text = _attributes[key]; } if (_provider.EnableLocalization) { // Try the implicit resource first string localizedText = GetImplicitResourceString(key); if (localizedText != null) { return localizedText; } // If not found, try the explicit resource. localizedText = GetExplicitResourceString(key, text, true); if (localizedText != null) { return localizedText; } } return text; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Item")); } if (_attributes == null) { _attributes = new NameValueCollection(); } _attributes[key] = value; } } public virtual SiteMapNodeCollection ChildNodes { get { if (_childNodesSet) return _childNodes; return _provider.GetChildNodes(this); } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "ChildNodes")); } _childNodes = value; _childNodesSet = true; } } [ Localizable(true) ] public virtual string Description { get { if (_provider.EnableLocalization) { string localizedText = GetImplicitResourceString("description"); if (localizedText != null) { return localizedText; } localizedText = GetExplicitResourceString("description", _description, true); if (localizedText != null) { return localizedText; } } return _description == null? String.Empty : _description; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Description")); } _description = value; } } public string Key { get { return _key; } } public virtual bool HasChildNodes { get { IList children = ChildNodes; return children != null && children.Count > 0; } } public virtual SiteMapNode NextSibling { get { IList siblings = SiblingNodes; if (siblings == null) { return null; } int index = siblings.IndexOf(this); if (index >= 0 && index < siblings.Count - 1) { return (SiteMapNode)siblings[index + 1]; } return null; } } // Get parent node. If not found in current provider, search recursively in parent providers. public virtual SiteMapNode ParentNode { get { if (_parentNodeSet) return _parentNode; return _provider.GetParentNode(this); } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "ParentNode")); } _parentNode = value; _parentNodeSet = true; } } public virtual SiteMapNode PreviousSibling { get { IList siblings = SiblingNodes; if (siblings == null) { return null; } int index = siblings.IndexOf(this); if (index > 0 && index <= siblings.Count - 1) { return (SiteMapNode)siblings[index - 1]; } return null; } } public SiteMapProvider Provider { get { return _provider; } } public bool ReadOnly { get { return _readonly; } set { _readonly = value; } } public String ResourceKey { get { return _resourceKey; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "ResourceKey")); } _resourceKey = value; } } public IList Roles { get { return _roles; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Roles")); } _roles = value; } } public virtual SiteMapNode RootNode { get { SiteMapNode root = _provider.RootProvider.RootNode; if (root == null) { String name = ((ProviderBase)_provider.RootProvider).Name; throw new InvalidOperationException(SR.GetString(SR.SiteMapProvider_Invalid_RootNode, name)); } return root; } } private SiteMapNodeCollection SiblingNodes { get { SiteMapNode parent = ParentNode; return parent == null? null : parent.ChildNodes; } } [ Localizable(true) ] public virtual string Title { get { if (_provider.EnableLocalization) { string localizedText = GetImplicitResourceString("title"); if (localizedText != null) { return localizedText; } localizedText = GetExplicitResourceString("title", _title, true); if (localizedText != null) { return localizedText; } } return _title == null? String.Empty : _title; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Title")); } _title = value; } } public virtual string Url { get { return _url == null? String.Empty : _url; } set { if (_readonly) { throw new InvalidOperationException(SR.GetString(SR.SiteMapNode_readonly, "Url")); } if (value != null) { _url = value.Trim(); } _virtualPath = CreateVirtualPathFromUrl(_url); } } internal VirtualPath VirtualPath { get { return _virtualPath; } } private VirtualPath CreateVirtualPathFromUrl(string url) { if (String.IsNullOrEmpty(url)) { return null; } if (!UrlPath.IsValidVirtualPathWithoutProtocol(url)) { return null; } if (UrlPath.IsAbsolutePhysicalPath(url)) { return null; } // Do not generate the virtualPath class at designtime. if (HttpRuntime.AppDomainAppVirtualPath == null) { return null; } if (UrlPath.IsRelativeUrl(url) && !UrlPath.IsAppRelativePath(url)) { url = UrlPath.Combine(HttpRuntime.AppDomainAppVirtualPathString, url); } // Remove the query string from url so the path can be validated by Authorization module. int queryStringIndex = url.IndexOf('?'); if (queryStringIndex != -1) { url = url.Substring(0, queryStringIndex); } return VirtualPath.Create(url, VirtualPathOptions.AllowAbsolutePath | VirtualPathOptions.AllowAppRelativePath); } public virtual SiteMapNode Clone() { ArrayList newRoles = null; NameValueCollection newAttributes = null; NameValueCollection newResourceKeys = null; if (_roles != null) { newRoles = new ArrayList(_roles); } if (_attributes != null) { newAttributes = new NameValueCollection(_attributes); } if (_resourceKeys != null) { newResourceKeys = new NameValueCollection(_resourceKeys); } SiteMapNode newNode = new SiteMapNode(_provider, Key, Url, Title, Description, newRoles, newAttributes, newResourceKeys, _resourceKey); return newNode; } public virtual SiteMapNode Clone(bool cloneParentNodes) { SiteMapNode current = Clone(); if (cloneParentNodes) { SiteMapNode node = current; SiteMapNode parent = ParentNode; while (parent != null) { SiteMapNode cloneParent = parent.Clone(); node.ParentNode = cloneParent; cloneParent.ChildNodes = new SiteMapNodeCollection(node); parent = parent.ParentNode; node = cloneParent; } } return current; } public override bool Equals(object obj) { SiteMapNode node = obj as SiteMapNode; return node != null && (_key == node.Key) && (String.Equals(_url, node._url, StringComparison.OrdinalIgnoreCase)); } public SiteMapNodeCollection GetAllNodes() { SiteMapNodeCollection collection = new SiteMapNodeCollection(); GetAllNodesRecursive(collection); return SiteMapNodeCollection.ReadOnly(collection); } private void GetAllNodesRecursive(SiteMapNodeCollection collection) { SiteMapNodeCollection childNodes = this.ChildNodes; if (childNodes != null && childNodes.Count > 0) { collection.AddRange(childNodes); foreach(SiteMapNode node in childNodes) node.GetAllNodesRecursive(collection); } } public SiteMapDataSourceView GetDataSourceView(SiteMapDataSource owner, string viewName) { return new SiteMapDataSourceView(owner, viewName, this); } public SiteMapHierarchicalDataSourceView GetHierarchicalDataSourceView() { return new SiteMapHierarchicalDataSourceView(this); } // Helpe method to retrieve localized string based on attribute name protected string GetExplicitResourceString(string attributeName, string defaultValue, bool throwIfNotFound) { if (attributeName == null) { throw new ArgumentNullException("attributeName"); } string text = null; if (_resourceKeys != null) { string[] keys = _resourceKeys.GetValues(attributeName); if (keys != null && keys.Length > 1) { try { text = ResourceExpressionBuilder.GetGlobalResourceObject(keys[0], keys[1]) as string; } catch (MissingManifestResourceException) { if (defaultValue != null) { return defaultValue; } } if (text == null && throwIfNotFound) { // throw if default value is not specified. throw new InvalidOperationException( SR.GetString(SR.Res_not_found_with_class_and_key, keys[0], keys[1])); ; } } } return text; } // Only use the key to get the hashcode since url can be changed and makes the objects mutable. public override int GetHashCode() { return _key.GetHashCode(); } // Helper method to retrieve localized string based on attribute name protected string GetImplicitResourceString(string attributeName) { if (attributeName == null) { throw new ArgumentNullException("attributeName"); } string text = null; if (!String.IsNullOrEmpty(_resourceKey)) { try { text = ResourceExpressionBuilder.GetGlobalResourceObject(Provider.ResourceKey, ResourceKey + "." + attributeName) as String; } catch { } } return text; } public virtual bool IsAccessibleToUser(HttpContext context) { return _provider.IsAccessibleToUser(context, this); } public virtual bool IsDescendantOf(SiteMapNode node) { SiteMapNode parent = ParentNode; while (parent != null) { if (parent.Equals(node)) { return true; } parent = parent.ParentNode; } return false; } public override string ToString() { return Title; } #region ICloneable implementation /// object ICloneable.Clone() { return Clone(); } #endregion #region IHierarchyData implementation /// bool IHierarchyData.HasChildren { get { return HasChildNodes; } } /// object IHierarchyData.Item { get { return this; } } /// string IHierarchyData.Path { get { return Key; } } /// string IHierarchyData.Type { get { return _siteMapNodeType; } } /// IHierarchicalEnumerable IHierarchyData.GetChildren() { return ChildNodes; } /// IHierarchyData IHierarchyData.GetParent() { SiteMapNode parentNode = ParentNode; if (parentNode == null) return null; return parentNode; } #endregion #region INavigateUIData implementations string INavigateUIData.Description { get { return Description; } } /// string INavigateUIData.Name { get { return Title; } } /// string INavigateUIData.NavigateUrl { get { return Url; } } /// string INavigateUIData.Value { get { return Title; } } #endregion } }