2 // System.Web.SiteMapNode
5 // Ben Maurer (bmaurer@users.sourceforge.net)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Collections.Specialized;
36 using System.Web.UI.WebControls;
37 using System.ComponentModel;
38 using System.Resources;
40 namespace System.Web {
41 public class SiteMapNode : IHierarchyData, INavigateUIData, ICloneable {
43 private SiteMapNode () {}
45 public SiteMapNode (SiteMapProvider provider, string key)
46 : this (provider, key, null, null, null, null, null, null, null) {}
47 public SiteMapNode (SiteMapProvider provider, string key, string url)
48 : this (provider, key, url, null, null, null, null, null, null) {}
49 public SiteMapNode (SiteMapProvider provider, string key, string url, string title)
50 : this (provider, key, url, title, null, null, null, null, null) {}
51 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description)
52 : this (provider, key, url, title, description, null, null, null, null) {}
54 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description,
55 IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys,
56 string implicitResourceKey)
59 throw new ArgumentNullException ("provider");
61 throw new ArgumentNullException ("key");
63 this.provider = provider;
67 this.description = description;
69 this.attributes = attributes;
70 this.resourceKeys = explicitResourceKeys;
71 this.implicitResourceKey = implicitResourceKey;
74 public SiteMapDataSourceView GetDataSourceView (SiteMapDataSource owner, string viewName)
76 return new SiteMapDataSourceView (owner, viewName, this);
79 public SiteMapHierarchicalDataSourceView GetHierarchicalDataSourceView ()
81 return new SiteMapHierarchicalDataSourceView (this);
84 public virtual bool IsAccessibleToUser (System.Web.HttpContext ctx)
86 return provider.IsAccessibleToUser (ctx, this);
89 public override string ToString()
94 public virtual bool HasChildNodes {
95 get { return ChildNodes != null && ChildNodes.Count != 0; }
98 public SiteMapNodeCollection GetAllNodes ()
100 SiteMapNodeCollection ret;
102 ret = new SiteMapNodeCollection ();
103 GetAllNodesRecursive (ret);
104 return SiteMapNodeCollection.ReadOnly (ret);
107 void GetAllNodesRecursive(SiteMapNodeCollection c)
109 SiteMapNodeCollection childNodes = this.ChildNodes;
111 if (childNodes != null && childNodes.Count > 0) {
112 c.AddRange (childNodes);
113 foreach (SiteMapNode n in childNodes)
114 n.GetAllNodesRecursive (c);
119 public virtual bool IsDescendantOf (SiteMapNode node)
121 for (SiteMapNode n = ParentNode; n != null; n = n.ParentNode)
122 if (n == node) return true;
127 public virtual SiteMapNode NextSibling {
129 IList siblings = this.SiblingNodes;
130 if (siblings == null)
133 int pos = siblings.IndexOf (this);
134 if (pos >= 0 && pos < siblings.Count - 1)
135 return (SiteMapNode) siblings [pos + 1];
141 public virtual SiteMapNode PreviousSibling {
143 IList siblings = this.SiblingNodes;
144 if (siblings == null)
147 int pos = siblings.IndexOf (this);
148 if (pos > 0 && pos < siblings.Count)
149 return (SiteMapNode) siblings [pos - 1];
155 public virtual SiteMapNode ParentNode {
157 if (parent != null) return parent;
159 SiteMapProvider provider = this.provider;
162 parent = provider.GetParentNode (this);
166 provider = provider.ParentProvider;
167 } while (provider != null);
176 public virtual SiteMapNodeCollection ChildNodes {
178 if (childNodes != null) return childNodes;
179 return provider.GetChildNodes (this);
187 public virtual SiteMapNode RootNode { get { return provider.RootProvider.RootNode; } }
189 SiteMapNodeCollection SiblingNodes {
191 if (ParentNode != null)
192 return ParentNode.ChildNodes;
198 protected string GetExplicitResourceString (string attributeName, string defaultValue, bool throwIfNotFound)
200 if (attributeName == null)
201 throw new ArgumentNullException ("attributeName");
203 if (resourceKeys != null){
204 string[] values = resourceKeys.GetValues (attributeName);
205 if (values != null && values.Length == 2) {
207 object o = HttpContext.GetGlobalResourceObject (values [0], values [1]);
211 catch (MissingManifestResourceException) {
214 if (throwIfNotFound && defaultValue == null)
215 throw new InvalidOperationException (String.Format ("The resource object with classname '{0}' and key '{1}' was not found.", values [0], values [1]));
222 protected string GetImplicitResourceString (string attributeName)
224 if (attributeName == null)
225 throw new ArgumentNullException ("attributeName");
227 if (String.IsNullOrEmpty (implicitResourceKey))
231 string reskey = provider.ResourceKey;
233 if (!String.IsNullOrEmpty (reskey))
234 reskey = String.Format ("{0}.{1}.{2}", reskey, implicitResourceKey, attributeName);
236 reskey = String.Format ("{0}.{1}", implicitResourceKey, attributeName);
237 object o = HttpContext.GetGlobalResourceObject ("Web.sitemap", reskey);
241 catch (MissingManifestResourceException) {
247 public virtual string this [string key]
251 if (provider.EnableLocalization) {
252 val = GetImplicitResourceString (key);
254 val = GetExplicitResourceString (key, null, true);
256 if (val != null) return null;
257 if (attributes != null) return attributes [key];
262 if (attributes == null) attributes = new NameValueCollection ();
263 attributes [key] = value;
267 object ICloneable.Clone ()
269 return Clone (false);
272 public virtual SiteMapNode Clone ()
274 return Clone (false);
277 public virtual SiteMapNode Clone (bool cloneParentNodes)
279 SiteMapNode node = new SiteMapNode ();
280 node.provider = provider;
284 node.description = description;
286 node.roles = new ArrayList (roles);
287 if (attributes != null)
288 node.attributes = new NameValueCollection (attributes);
289 if (cloneParentNodes && ParentNode != null)
290 node.parent = (SiteMapNode) ParentNode.Clone (true);
294 public override bool Equals (object ob)
296 SiteMapNode node = ob as SiteMapNode;
297 if (node == null) return false;
299 if (node.key != key ||
301 node.title != title ||
302 node.description != description) {
306 if (roles == null || node.roles == null) {
307 if (roles != node.roles)
311 if (roles.Count != node.roles.Count)
314 foreach (object role in roles)
315 if (!node.roles.Contains (role)) return false;
317 if (attributes == null || node.attributes == null) {
318 if (attributes != node.attributes)
322 if (attributes.Count != node.attributes.Count)
325 foreach (string k in attributes)
326 if (attributes[k] != node.attributes[k])
332 public override int GetHashCode ()
334 return (key + url + title + description).GetHashCode ();
337 void CheckWritable ()
340 throw new InvalidOperationException ("Can't modify read-only node");
343 #region Field Accessors
345 protected NameValueCollection Attributes {
346 get { return attributes; }
347 set { CheckWritable (); attributes = value; }
351 public virtual string Description {
355 if (provider.EnableLocalization) {
356 ret = GetImplicitResourceString ("description");
358 ret = GetExplicitResourceString ("description", description, true);
362 return ret != null ? ret : String.Empty;
364 set { CheckWritable (); description = value; }
367 [LocalizableAttribute (true)]
368 public virtual string Title {
372 if (provider.EnableLocalization) {
373 ret = GetImplicitResourceString ("title");
375 ret = GetExplicitResourceString ("title", title, true);
379 return ret != null ? ret : String.Empty;
381 set { CheckWritable (); title = value; }
384 public virtual string Url {
385 get { return url != null ? url : ""; }
386 set { CheckWritable (); url = value; }
390 get { return roles; }
391 set { CheckWritable (); roles = value; }
394 public bool ReadOnly {
395 get { return readOnly; }
396 set { readOnly = value; }
399 public string ResourceKey {
400 get { return resourceKey; }
401 set { resourceKey = value; }
404 public string Key { get { return key; } }
405 public SiteMapProvider Provider { get { return provider; } }
409 #region INavigateUIData
410 IHierarchicalEnumerable System.Web.UI.IHierarchyData.GetChildren () { return ChildNodes; }
411 IHierarchyData System.Web.UI.IHierarchyData.GetParent ()
416 bool System.Web.UI.IHierarchyData.HasChildren { get { return HasChildNodes; } }
417 object System.Web.UI.IHierarchyData.Item { get { return this; } }
418 string System.Web.UI.IHierarchyData.Path { get { return Url; } }
419 string System.Web.UI.IHierarchyData.Type { get { return "SiteMapNode"; } }
422 #region INavigateUIData
423 string INavigateUIData.Name { get { return Title; } }
424 string INavigateUIData.NavigateUrl { get { return Url; } }
425 string INavigateUIData.Value { get { return Title; } }
429 SiteMapProvider provider;
435 NameValueCollection attributes;
436 NameValueCollection resourceKeys;
440 string implicitResourceKey;
441 SiteMapNodeCollection childNodes;