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.
31 using System.Collections;
32 using System.Collections.Specialized;
35 using System.Web.UI.WebControls;
36 using System.ComponentModel;
37 using System.Resources;
39 namespace System.Web {
40 public class SiteMapNode : IHierarchyData, INavigateUIData, ICloneable {
44 public SiteMapNode (SiteMapProvider provider, string key)
45 : this (provider, key, null, null, null, null, null, null, null) {}
46 public SiteMapNode (SiteMapProvider provider, string key, string url)
47 : this (provider, key, url, null, null, null, null, null, null) {}
48 public SiteMapNode (SiteMapProvider provider, string key, string url, string title)
49 : this (provider, key, url, title, null, null, null, null, null) {}
50 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description)
51 : this (provider, key, url, title, description, null, null, null, null) {}
53 public SiteMapNode (SiteMapProvider provider, string key, string url, string title, string description,
54 IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys,
55 string implicitResourceKey)
58 throw new ArgumentNullException ("provider");
60 throw new ArgumentNullException ("key");
62 this.provider = provider;
66 this.description = description;
68 this.attributes = attributes;
69 this.resourceKeys = explicitResourceKeys;
70 this.resourceKey = implicitResourceKey;
73 public SiteMapDataSourceView GetDataSourceView (SiteMapDataSource owner, string viewName)
75 return new SiteMapDataSourceView (owner, viewName, this);
78 public SiteMapHierarchicalDataSourceView GetHierarchicalDataSourceView ()
80 return new SiteMapHierarchicalDataSourceView (this);
83 public virtual bool IsAccessibleToUser (System.Web.HttpContext ctx)
85 return provider.IsAccessibleToUser (ctx, this);
88 public override string ToString()
93 public virtual bool HasChildNodes {
95 SiteMapNodeCollection childNodes = ChildNodes;
96 return childNodes != null && childNodes.Count > 0;
100 public SiteMapNodeCollection GetAllNodes ()
102 SiteMapNodeCollection ret;
104 ret = new SiteMapNodeCollection ();
105 GetAllNodesRecursive (ret);
106 return SiteMapNodeCollection.ReadOnly (ret);
109 void GetAllNodesRecursive(SiteMapNodeCollection c)
111 SiteMapNodeCollection childNodes = this.ChildNodes;
113 if (childNodes != null && childNodes.Count > 0) {
114 c.AddRange (childNodes);
115 foreach (SiteMapNode n in childNodes)
116 n.GetAllNodesRecursive (c);
121 public virtual bool IsDescendantOf (SiteMapNode node)
123 for (SiteMapNode n = ParentNode; n != null; n = n.ParentNode)
124 if (n == node) return true;
129 public virtual SiteMapNode NextSibling {
131 IList siblings = this.SiblingNodes;
132 if (siblings == null)
135 int pos = siblings.IndexOf (this);
136 if (pos >= 0 && pos < siblings.Count - 1)
137 return (SiteMapNode) siblings [pos + 1];
143 public virtual SiteMapNode PreviousSibling {
145 IList siblings = this.SiblingNodes;
146 if (siblings == null)
149 int pos = siblings.IndexOf (this);
150 if (pos > 0 && pos < siblings.Count)
151 return (SiteMapNode) siblings [pos - 1];
157 public virtual SiteMapNode ParentNode {
159 if (parent != null) return parent;
161 SiteMapProvider provider = this.provider;
164 parent = provider.GetParentNode (this);
168 provider = provider.ParentProvider;
169 } while (provider != null);
178 public virtual SiteMapNodeCollection ChildNodes {
180 if (childNodes == null)
181 childNodes = provider.GetChildNodes (this);
190 public virtual SiteMapNode RootNode { get { return provider.RootProvider.RootNode; } }
192 SiteMapNodeCollection SiblingNodes {
194 if (ParentNode != null)
195 return ParentNode.ChildNodes;
201 protected string GetExplicitResourceString (string attributeName, string defaultValue, bool throwIfNotFound)
203 if (attributeName == null)
204 throw new ArgumentNullException ("attributeName");
206 if (resourceKeys != null){
207 string[] values = resourceKeys.GetValues (attributeName);
208 if (values != null && values.Length == 2) {
210 object o = HttpContext.GetGlobalResourceObject (values [0], values [1]);
214 catch (MissingManifestResourceException) {
217 if (throwIfNotFound && defaultValue == null)
218 throw new InvalidOperationException (String.Format ("The resource object with classname '{0}' and key '{1}' was not found.", values [0], values [1]));
225 protected string GetImplicitResourceString (string attributeName)
227 if (attributeName == null)
228 throw new ArgumentNullException ("attributeName");
230 string resourceKey = ResourceKey;
231 if (String.IsNullOrEmpty (resourceKey))
235 object o = HttpContext.GetGlobalResourceObject (provider.ResourceKey, resourceKey + "." + attributeName);
238 } catch (MissingManifestResourceException) {
244 public virtual string this [string key]
247 if (provider.EnableLocalization) {
248 string val = GetImplicitResourceString (key);
250 val = GetExplicitResourceString (key, null, true);
254 if (attributes != null) return attributes [key];
259 if (attributes == null) attributes = new NameValueCollection ();
260 attributes [key] = value;
264 object ICloneable.Clone ()
266 return Clone (false);
269 public virtual SiteMapNode Clone ()
271 return Clone (false);
274 public virtual SiteMapNode Clone (bool cloneParentNodes)
276 SiteMapNode node = new SiteMapNode ();
277 node.provider = provider;
281 node.description = description;
283 node.roles = new ArrayList (roles);
284 if (attributes != null)
285 node.attributes = new NameValueCollection (attributes);
286 if (cloneParentNodes && ParentNode != null)
287 node.parent = (SiteMapNode) ParentNode.Clone (true);
291 public override bool Equals (object ob)
293 SiteMapNode node = ob as SiteMapNode;
294 if (node == null) return false;
296 if (node.key != key ||
298 node.title != title ||
299 node.description != description) {
303 if (roles == null || node.roles == null) {
304 if (roles != node.roles)
308 if (roles.Count != node.roles.Count)
311 foreach (object role in roles)
312 if (!node.roles.Contains (role)) return false;
314 if (attributes == null || node.attributes == null) {
315 if (attributes != node.attributes)
319 if (attributes.Count != node.attributes.Count)
322 foreach (string k in attributes)
323 if (attributes[k] != node.attributes[k])
329 public override int GetHashCode ()
331 return (key + url + title + description).GetHashCode ();
334 void CheckWritable ()
337 throw new InvalidOperationException ("Can't modify read-only node");
340 #region Field Accessors
342 protected NameValueCollection Attributes {
343 get { return attributes; }
344 set { CheckWritable (); attributes = value; }
348 public virtual string Description {
352 if (provider.EnableLocalization) {
353 ret = GetImplicitResourceString ("description");
355 ret = GetExplicitResourceString ("description", description, true);
359 return ret != null ? ret : String.Empty;
361 set { CheckWritable (); description = value; }
364 [LocalizableAttribute (true)]
365 public virtual string Title {
369 if (provider.EnableLocalization) {
370 ret = GetImplicitResourceString ("title");
372 ret = GetExplicitResourceString ("title", title, true);
376 return ret != null ? ret : String.Empty;
378 set { CheckWritable (); title = value; }
381 public virtual string Url {
382 get { return url != null ? url : ""; }
383 set { CheckWritable (); url = value; }
387 get { return roles; }
388 set { CheckWritable (); roles = value; }
391 public bool ReadOnly {
392 get { return readOnly; }
393 set { readOnly = value; }
396 public string ResourceKey {
397 get { return resourceKey; }
400 throw new InvalidOperationException ("The node is read-only.");
405 public string Key { get { return key; } }
406 public SiteMapProvider Provider { get { return provider; } }
410 #region INavigateUIData
411 IHierarchicalEnumerable System.Web.UI.IHierarchyData.GetChildren () { return ChildNodes; }
412 IHierarchyData System.Web.UI.IHierarchyData.GetParent ()
417 bool System.Web.UI.IHierarchyData.HasChildren { get { return HasChildNodes; } }
418 object System.Web.UI.IHierarchyData.Item { get { return this; } }
419 string System.Web.UI.IHierarchyData.Path { get { return Url; } }
420 string System.Web.UI.IHierarchyData.Type { get { return "SiteMapNode"; } }
423 #region INavigateUIData
424 string INavigateUIData.Name { get { return Title; } }
425 string INavigateUIData.NavigateUrl { get { return Url; } }
426 string INavigateUIData.Value { get { return Title; } }
430 SiteMapProvider provider;
436 NameValueCollection attributes;
437 NameValueCollection resourceKeys;
441 SiteMapNodeCollection childNodes;